Quantcast

Ruby on Rails, Io, Lisp, JavaScript, Dynamic Languages, Prototype-based programming and more...

Technoblog reader special: $10 off web hosting by FatCow!

Monday, November 13, 2006

A Fatal Flaw in Opinionated Software

David Heinemeier Hansson has written a lot about opinionated software and syntactic vinegar. At first glance, the term opinionated software sounds perfectly reasonable. It seems, at least to me, to mean that the software looks and acts in a certain way... it has opinions like DRY and convention over configuration. That is not what opinionated software means to David. To David, a piece of opinionated software is written in such a way that makes it easy to do things one way and ugly and difficult to do things another way.

What does this mean? Glad you asked. Let's look for example at the ActiveRecord find method.

User.find(:first, :conditions => "active = 1")
# => # "1", "active"=>"1"}>

User.find(:first, :with => {:active => 1})
# ArgumentError: Unknown key(s): with

Ok, so the find method does not accept the key :with. That is fine, but let's say you and I are clever hackers and we wanted to enhance ActiveRecord to accept the :with key in order to do some neat magic that reduces the amount of code we have to write. For a Ruby developer, this type of modification sounds like it should be easy, but this is what I found when I first looked at the Rails source.

def validate_find_options(options) #:nodoc:

options.assert_valid_keys([:conditions, :include, :joins, :limit, :offset, :order, :select, :readonly, :group, :from])

end

That is right, the keys were all hard coded, meaning that if I wanted to add my own :with key, I would have to completely overwrite the undocumented
validate_find_options method, which inevitably would break things down the line as Rails added its own new keys.

When I first saw this I thought to myself: ah, must be an oversight. I wrote a patch in a few seconds that abstracted the array passed to options.assert_valid_keys into something mutable. I submitted the patch and had a lengthy discussion with DHH in which I was slapped by the opinionated software stick. Apparently, David thought that if I wanted to hack ActiveRecord, I was going to have to be punished by writing ugly code. It was the "opinion" of ActiveRecord that people shouldn't add a key to the find method, so David intentionally made it much harder than necessary to accomplish.

That is right, this was not a simple oversight, this type of code was completely intentional. It is David's opinion that Rails be harder than necessary to hack around and play with. That if I was going to stretch the limits of Rails, take it places nobody else had thought of, that I should be punished for doing so, and that punishment is ugly code.

This is the fatal flaw of opinionated software... in order to make design decisions that limit people's ability to do things you don't think they should do, you must punish them. The form of punishment that David is interested in is syntactic vinegar, like having to override a method instead of append to an array.

The problem with this approach is that punishment is only appropriate for children and criminals. By actively working to make my life as a hacker more difficult, David is treating me like a child or a criminal. Saying either that I am not old enough to know what I am doing and must be punished for doing it, or that I am wrong to think that way at all. Punishment is a very dangerous tool to use because it is fundamentally condescending.

Rails is David's baby, so he can do whatever he wants to it, and that is fine, but to treat a seasoned professional as a child only goes so far in my book. Some might argue that it is for the greater good... that it makes people who don't know what they are doing write better code, keeps people in their place. First of all, the people who end up being punished the most are the ones who want to push the envelope--a beginner is never going to try to add a keyword to the find method. Second of all, I don't want to give up my work productivity for the productivity of those who do not know what they are doing, I want a tool that works best for me. Every time I run into "opinionated software" in Rails, it makes the back of my ears burn reminding me of how much I can't wait to find, start, or help the next generation of highly productive web development software.

Opinionated software is fine until you want to do interesting, new, and innovative things with ease. I am not interested in being treated like a child or a criminal for doing so, which means those opinions which David holds most dear are the ones that will eventually drive out the people that Rails initially attracted... the hackers, the innovators, the bleeding edge developers. Give us freedom or give us another tool that provides freedom.

As a side note, apparently I may have been the first but certainly not the last to complain about the particular form of syntactic vinegar presented with validate_find_options because I see now that they ended up abstracting it and you can now add accepted keys by modifying the VALID_FIND_OPTIONS array. If you would like to see my failed attempt over a year ago to add this feature, check out this ticket.

You should follow me on twitter here.

Technoblog reader special: click here to get $10 off web hosting by FatCow!

59 Comments:

Anonymous Martin May said...

That is right, the keys were all hard coded, meaning that if I wanted to add my own :with key, I would have to completely overwrite the undocumented validate_find_options method, which inevitably would break things down the line as Rails added its own new keys.

Mmm...how about aliasing the method, and then wrapping it in your own method which adds the desired keys?

Something like this:

alias_method :old_validate_find_options, : validate_find_options

def new_validate_find_options(options)
options.assert_valid_keys([:where]) or validate_find_options(options)
end

alias_method :validate_find_options, :new_validate_find_options

2:09 PM, November 13, 2006

 
Blogger Lucas Carlson said...

That is incredibly ugly and quite convoluted. It is punishment even though it works.

2:15 PM, November 13, 2006

 
Anonymous Anonymous said...

the next generation of web development tools is in Python, and theres a wide variety of options. While we have a dictator as well, hes not nearly so micromanaging.

2:18 PM, November 13, 2006

 
Blogger jamie said...

I have come across this kind of problem on numerous occasions with Rails. I hate having to alias methods etc. as you inevitably end up in a big mess with aliased-aliased methods when things need extending further.

2:24 PM, November 13, 2006

 
Blogger Lucas Carlson said...

Saying that the next great framework is going to be in Python is like saying: "the next great novel is going to be written in Italian."

2:26 PM, November 13, 2006

 
Blogger Michael said...

First of all, ActiveRecord already supports passing a hash for your :conditions, though I don't remember as of what version. (I remember there being discussion about it on the rails-core mailing list a good while ago.) So this would work as is, I think:

User.find(:first, :conditions => {:active => 1})

Even if that feature didn't exist, aren't you just translating a hash into a condition string? If that's the case, why couldn't you just use the :conditions key instead? Is there something particularly with-like about the finding you're doing? If so, perhaps you ought not to go through "find"? Perhaps declaring a method named like "find" like "find_with_whatever" would be more appropriate? Then you have the advantage of keeping your stuff further separate from the core.

3:11 PM, November 13, 2006

 
Blogger Lucas Carlson said...

Michael, your comment is off topic, you are not addressing any of the issues I brought up. But for you edification, the example I used for this post was chosen because it is easy to see why it could be useful to add keys to the find method. It was chosen for illustrative purposes and was not what I happened to be trying to do at the time.

3:19 PM, November 13, 2006

 
Blogger Kevin said...

The next great web dev tool is going to be Grok. Or if not Grok specifically, any large, rich, mature framework in a dynamic language that then has a layer of rapid development Models n' Views wrapped around it. When you want to grow the complexity of the software beyond the rapid development phase it's good to have something there that manage additional complexity.

3:25 PM, November 13, 2006

 
Blogger Lucas Carlson said...

"large, rich, mature framework in a dynamic language"

1) Rails was not large, rich or mature when it started to take off

2) OCaml is not a dynamic language, but I would certainly not be surprised to see OCaml be the base of the next great web dev tool

3:32 PM, November 13, 2006

 
Anonymous Adam Jones said...

I fail to see why this kind of discouragement is necessary. If you don't want ActiveRecord to support :with, don't accept patches that implement it. It is that simple, and still allows those with motivation and capability to make it happen if they want/need it.

Not to be an annoying advocate, but this is one of the biggest reasons turbogears is my web framework of choice. Community participation is actively encouraged, and I have yet to see any code that is deliberately obtuse.

8:10 PM, November 13, 2006

 
Anonymous Mr eel said...

Personally I think the Rails team should be encouraging hacking of ActiveRecord where ever possible. My opinion of AR has dropped lower and lower as I've had to struggle with it's performance issues.

Allowing folks to hack the code will encourage them to find better solutions for the problems that it has — eager loading for example is awful awful awful.

IMO opinionated software is saying 'this is what we think is the right way'. It works because it limits the choices you can make. Rather than having to cook up your own way of doing something there is The Rails Way.

In this case I think DHH is wrong. Locking down the code isn't opinionated at all. If anything it undermines the current position of the Rail Core regarding patches. Make a plugin they say, while measures like this make it difficult to actually do so.

You're not encouraging people to make a better choice, you're just making it more difficult for them to probe and possibly improve Rails.

9:43 PM, November 13, 2006

 
Anonymous Anonymous said...

Try Django. Those boys have mastered loose coupling and abstraction. The 'pieces' from which the framework is built are all easy to extend or change, and it doesn't feel like you're hacking something rigid; it feels like you're extending something very pragmatic.

9:56 PM, November 13, 2006

 
Blogger Lucas Carlson said...

I have tried Django and am not a fan, but I will keep trying it and might change my mind at some point.

9:59 PM, November 13, 2006

 
Blogger Michael said...

It's more SPECIFIC than off-topic I think, and I apologize for taking your example so literally, though maybe it would better to use one that's not simply a rephrasing of an existing feature?

However, to restate my question, (the second part of my post) why bother mucking with Rails internals if you don't have to? Is it really necessary to add complexity to an existing feature when adding something beside it would do? This is like complaining that HTTP doesn't have a SITEMAP method or something. It's my opinion that core functionality should be kept as spare as possible, I guess.

10:14 PM, November 13, 2006

 
Blogger Lucas Carlson said...

why bother mucking with Rails internals if you don't have to?

Because I am a hacker and I want to. I have ideas that don't fit into a box, I look at what I am given and wonder how I can do more with it. For example, how would you build an entire multi-and-disparate-model website with a single database table? This would allow you to create new data types as data at any point. How might you associate disparate-table models with single-table models? What are the benefits and pitfalls of these types of systems... especially with regards to creating wikis.

I have not only thought about that problem but solved it with ActiveRecord and it took a lot of hacking. It would have been good clean and maintainable hacking too if it weren't for opinionated software.

But really, essentially, the answer to that question is the same as the answer to the more general question: why bother much with anything's internals if you don't have to? There are some people that are happy to play inside sandboxes and some that aren't. Some things like Unix encourage playing outside the sandbox, other things like Windows do not.

10:32 PM, November 13, 2006

 
Anonymous Anonymous said...

Because I am a hacker and I want to. I have ideas that don't fit into a box, I look at what I am given and wonder how I can do more with it. For example, how would you build an entire multi-and-disparate-model website with a single database table?

Then maybe the "here's a solution to a problem, but not every problem" approach in Rails means it definately isn't the platform for you.

build an entire multi-and-disparate-model website with a single database table. Hmmmm.... :)

10:47 PM, November 13, 2006

 
Blogger Michael said...

I guess I'd say I'm a hacker too, but I like my put my ideas in my own box so I know who to blame when something goes wrong. I'm referencing your original example to death, but the fact that it's difficult and error-prone to hack something seems like a clue that another approach is necessary, which could be as simple as using a different name. (Um, I'm gonna quote DHH here, but "if something isn't easy, you're not cheating enough.")

Maybe here's a question: why bother using ActiveRecord? If you have a need that it doesn't satisfy, maybe there's another ORM that can, or maybe you can write your models yourself. Rails doesn't force you to use ActiveRecord for your models.

My web-store, if it were not a static HTML page generated by Camping, could be a Rails app, but the model I use to represent products is a simple class that loads data from a single YAML file. Using ActiveRecord would be overkill in this case, since I don't need an interface for editing products, I just edit the YAML file.

When compared with the "multi-and-disparate-model" example you mention, that's the other end of the spectrum, I guess! It seems like there's a need out there for greater flexibility w/ models and such, but I don't think that's the aim of ActiveRecord.

11:14 PM, November 13, 2006

 
Blogger Lucas Carlson said...

michael, as I said, I have implemented it in ActiveRecord, and it has worked very well. Moreover, it could have been maintainable if it weren't for the syntactic vinegar in my way. If DHH hadn't deliberately made it harder to hack than necessary, for no other reason that because he didn't think there was a good use, I could have easily abstracted my work into a ActiveRecord plugin.

It seems like there's a need out there for greater flexibility w/ models and such, but I don't think that's the aim of ActiveRecord.

Of course it is not the aim of ActiveRecord, but I am telling you that if DHH's software wasn't opinionated, it would be a simple change that would not need to be maintained.

11:54 PM, November 13, 2006

 
Anonymous Gabor Farkas said...

> David is treating me like a child or a criminal

:)

as it's said in the python community:

"we're all consenting adults"

12:57 AM, November 14, 2006

 
Blogger Brandon Corfman said...

The main question I have is, how are you supposed to identify syntactic vinegar over lousy design? Notice that you had to have DHH *tell you* that it was syntactic vinegar, because you (as a uninformed hacker) couldn't identify it yourself.

6:42 AM, November 14, 2006

 
Anonymous Anonymous said...

Not to mentioned that the "opinionated" Rails framework is oriented to produce pre-IPO web applications, rather than "web sites". Any framework which requires a server per app has some serious myopia.

7:16 AM, November 14, 2006

 
Anonymous Anonymous said...

Your argument is fatally flawed. You refer to a disincentive as a "punishment", claim that punishment is only appropriate for criminals and children, and therefore conclude that you're being treated as a criminal or child.

The fact is disincentives between non-criminal adults occur all the time -- within a household, at the workplace, etc. Incentives and disincentives are part of the social fabric.

Now you may very well have a point about DHH and his opinions. But there's no need to play word games and detract from your point.

8:22 AM, November 14, 2006

 
Blogger Lucas Carlson said...

Notice that you had to have DHH *tell you* that it was syntactic vinegar, because you (as a uninformed hacker) couldn't identify it yourself

I thought that it was just poorly written code, a mistake. A mistake like that only becomes syntactic vinegar with intention and without any comments in the code, there is no way to glean intention until I try to fix it and the fix is refused.

9:02 AM, November 14, 2006

 
Blogger Lucas Carlson said...

Disincentives and punishment are cut from the same tree, the line is most certainly more vague and subjective than you describe it.

9:19 AM, November 14, 2006

 
Anonymous Anonymous said...

Have you tried Nitro? It's another Ruby web programming framework that seems to be philosophically different from Rails.

10:47 AM, November 14, 2006

 
Blogger Lucas Carlson said...

Nitro is too much like Rails, and not enough like Rails to hold my interest. It is too much like Rails in design and everyday use and not enough like Rails with regards to the featureset and community support. Nitro's offering is not compelling to me.

10:58 AM, November 14, 2006

 
Blogger zzzeek said...

hey lucas -

people have mentioned here other frameworks and languages disparate from rails and/or ruby, all of which would love to have new people on their project contributing new ideas, but you seem disinterested in them. You'd like to explore your own ideas about architecture and web development, and are coming up against the brick wall that is "ruby has only one viable framework, which is totally owned by DHH, who generally doesn't care what you think" (at least thats the impression I get every time i read a discussion thread with DHH...im sure hes a nicer guy in person).

I cant help but think about the sidebar on your blog, "I found Rails in September of 2004 and fell in love"...because this sounds like pre-breakup angst.

3:00 PM, November 14, 2006

 
Blogger Lucas Carlson said...

I have loved Macintosh for over a decade now, but I certainly have a list of things that piss me off. Macintosh is great but some parts make me very angry. I disdain the dock, I don't know why the GUI ftp support is read-only, etc. On a more abstract level I am pissed at Steve for deciding to close the source of Intel-based Darwin. All that said, you couldn't rip my Macbook Pro + OS X from my cold dead hands.

Regarding web frameworks, I am constantly on the lookout for the next best thing, the next set of tools to make my life easier. I am constantly reviewing web frameworks in search of something better for me and my purposes. On that level I have always, even in September of 2004, had pre-breakup angst. I am not going to defend Rails tooth and nail blindly, I am always ready to jump ship.

This article has less to do with my angst and more to do with my anger. Rails is really great, but some parts make me very angry.

3:15 PM, November 14, 2006

 
Anonymous Anonymous said...

Disincentives and punishment are cut from the same tree, the line is most certainly more vague and subjective than you describe it.

Uh, where did I describe it?

If DHH gives you a time out, spanks you, grounds you, says you can't watch TV or use the Internet, incarcerates you, makes you pick up trash on the side of the highway, fines you, etc., then you can claim to be punished.

But all that happened here is that you want things to be one way, DHH wants them to be another way, and you mistakenly think you've enhanced your argument by claiming to have been punished.

8:41 PM, November 14, 2006

 
Blogger Lucas Carlson said...

Punishment can be thought of as going out of ones way to cause harm to others in order to teach them they are wrong.

One way of punishing a child is by taking away their allowance, making sure that they do not receive as much money as they would otherwise. I work for a living and when it takes me longer than necessary to do my job, time is money. Since I am paid a salary, this means that my company has paid for me to spend more of my time than necessary to do my job. Since I have stock in my company, that means that by taking my time, it devalues my stock.

David takes his time and energy to knowingly program worse than he would otherwise in order to make people like me spend more time writing uglier code and more time maintaining that code than, thus causing me harm.

Knowingly writing bad code and refusing to accept patches to clean it up on various occasions by various community members, not based on time constraints but based on the philosophy that it should stay ugly to their my work harder than it need be is certainly a form of punishment in my book.

8:58 PM, November 14, 2006

 
Anonymous Zach Baker said...

This is a matter of feelings and taste, is it not? Surely I knew before that DHH is unafraid of hurting feelings and a fellow of very particular taste that people do not necessarily agree with. If his code and projects honestly reflect just that, I find it hard to consider it punishment or condescension. That implies a motive not in evidence here and so is perhaps being speculated upon unfairly.

1:51 PM, November 17, 2006

 
Blogger Lucas Carlson said...

The motive can be found both in DHH's own writings and my personal contact with him that re-enforce his writings.

1:57 PM, November 17, 2006

 
Anonymous Alex said...

Lucas, If you have an issue with Rails then write your own framework. I did four months ago for similar reasons as you mention, and I haven't looked back since.

I can hook you up with a guy that has built a framework container if you like, to make life a little easier. Also you may want to consider Og for the db layer. It's immature but highly hackable.

All the above in Ruby.

4:26 PM, November 20, 2006

 
Blogger Rob said...

Lucas, out of curiousity did you find the changeset where the change actually made it in?

11:19 AM, November 30, 2006

 
Blogger Lucas Carlson said...

I never did track it down, but svn blame should help for anyone curious.

4:53 PM, November 30, 2006

 
Anonymous carmen said...

the flaw you mention isn't fatal - the point of an Apple or rails-style vertically-integrated stack is so you dont need or want to change the internals..'Experts' have decided it all for you, and youre left to ogle your $2000 slab of chinese parts or write a few lines in TextMate.

opinionated defaults and easy customization/overrides aren't mutually exclusive, but as in the Apple case (how do you change the window-manager again? you mean the 3 checkboxes they decided to put in the GUI arent the ones you want and you have to drop down to a cmdline netinfo tool?), the main reason i switched off rails was i didnt agree with its opinions on the defaults, and replacing them was more trouble that it was worth.

take ERB. since markaby was 10x preferable to me, i figured it would be a straight mixin/include via plugins.

well, no. since rail's view rendering has J2EE levels of gatekeeping and abstraction, it was impossible to do things like pass a block to a template, without rewriting parts of ActionView. that, and calling a template recursively (to treeize some graph data into DOM nodeS) was causing bizarre errors that i couldn't diagnose. pasting the nonworking rails code into camping solved both these problems at once.

or take the opinion that Prototype is the way to go for JavaScript. you have all sorts of methods for generating dom nodes, that dont even correspond to the element names (eg link_to, instead of 'a', and weird argument order that you constantly have to refer to the docs to figure out), and the same is true for the javascript. or take the fact that generating javascript programaticaly from ruby at request time is unnecessary and a waste of resources, and RJS specifies a very specific design style (shuttling over ruby-generated scripts to be executed client-side) along with the inlining of unreadable generated javascript on element 'onclick' attributes and similar, requires you to seek out 3rd party unobtrusive plugins where theres a chance they will break any time, and even sooner if youre using something besides ERB, or the way the new CRUD/REST magic specifies as very specific way of structuring your URLs (and even that you shouldnt use accept-headers and instead changing the URI itself with a non-query-string format extension) and if youre writing javascript and SQL in ruby, why not HTML and CSS?. and what about the dichotomy of having to specify the model in 2 places - your model code, and your migration code..

overall it was this kind of lack of loose coupling and layers of assumption that led me away from rails. by the time i had replaced with ActiveRecord with my own RDF ORM, ERB with Markaby, Prototype with JQuery, and their REST routes with my own (which incidentally updates to their routes code broke, and my bug report was closed saying i should rewrite my routes), and struggled to fix obscure scoping bugs with already-fragile include/alias nonsense, it seemed the only 'opinion' of rails left affecting me was the fact that i had to have said hoop-jumping in the first place to get it how i want.

for the record, i do believe the framework i built my 'no-code' app-development framework in benefited from the fact that i can read its entire source code without even hitting the pageup/pagedown key..in terms of developer grief and refactoring simplicify.

2:11 PM, February 06, 2007

 
Blogger micko said...

his post provides the light in which we can observe the reality. That is very nice one and provides in-depth information.sizegenetics discount

11:09 PM, March 14, 2014

 
Blogger lina123 Chen said...

chenlina20150626
chenlina20150626
coach outlet store online
cheap oakley sunglasses
burberry sale
coach outlet
abercrombie fitch
ray ban uk
michael kors outlet online
kids lebron shoes
lv outlet
true religion sale
louis vuitton outlet
cheap ran bans
tory burch outlet
abercrombie and fitch
hollister clothing
ghd straighteners
prada
air max 90
fendi handbags
michael kors outlet
jordan 11 columbia
louis vuitton outlet
louis vuitton outlet
cheap jerseys
gucci belt
coach factory outlet
louis vuitton outlet
ralph lauren uk
hermes birkin
michael kors outlet online
true religion sale
p90x
louis vuitton
tod's outlet
kobe bryant shoes
pandora bracelets
michael kors outlet
michael kors outlet online
jordan 4 toro
michael kors

6:19 PM, June 25, 2015

 
Blogger Đức Tiến said...


2.
You will easily connect with investors, real estate agencies, brokers, customers, .... when using the communication channels leading Real Estate Vietnam

Kênh thông tin chung cư hà nội | Giá bán goldmark city 136 hồ tùng mậu | Thông tin goldsilk complex vạn phúc | Mở bán chung cư Eco Green City Nguyễn Xiển  | Bán chung cư Chung cư Eco Green City | Thông tin chung cư Hải Đăng City Mỹ Đình | Giá bán chung cư vinafor 48 vạn phúc | Mở bán chung cư Goldsilk complex vạn phúc | Dự án mai trang tower phạm hùng | Tin tức Chung cư MBLand Central Point 219 Trung Kính Cầu Giấy
APARTMENT INFORMATION - Information channel No. 1 Hanoi apartment!!!

11:54 AM, July 07, 2015

 
Blogger Chung cư giá rẻ said...

chung cu duong noi
chung cu goldsilk van phuc
chung cu goldmark city
goldmark
chung cu park view residence
chung cu quan ha dong
chung cu quan cau giay
chung cu ha noi
chung cu vp7 linh dam
chung cu hai dang city
chung cu vinafor van phuc
chung cu 60b nguyen huy tuong
chung cu vinhomes tran duy hung
chung cu thong tan xa
ban sen mini

7:10 PM, July 10, 2015

 
Blogger giao đỗ said...

Mua bán chung cư Goldsilk complex
Kênh thông tin chung cư park view residence
Lễ mở bán Dự án goldsilk complex
Thông tin Chi tiết chung cư flc complex
Căn hộ mẫu chung cư Đặng Xá

11:30 PM, July 12, 2015

 
Blogger Vietnam Travel said...

biệt thự vinhomes riverside

5:31 AM, July 15, 2015

 
Blogger Vietnam Travel said...

Bán biệt thự hoa anh đào
Bán nhanh chóng biệt thự bằng lăng

Bán gấp biệt thự hoa lan

Bán gấp chung cu royal city giá gốc
cho thuê chung cư tại royal city
Mở bán biet thu hoa sua
bán nhanh biệt thự hoa phượng

8:01 PM, July 15, 2015

 
Blogger bao ngoc said...

Bán 500 căn hộ Chung cư Vp7 Linh Đàm
nhận kí gửi căn hộ Vp7 Linh Đàm

12:49 AM, July 22, 2015

 
Blogger Nam Harry said...

chung cư 265 cầu giấy

goldsilk complex

chung cư 203 nguyễn huy tưởng

chung cư eco green city

hateco hoàng mai

chung cư hải đăng city

chung cư n02 yên hòa

chung cư c37 bộ công an

chung cư mipec riverside

chung cư goldmark city

chung cư vinafor plaza

chung cư artemis

vinhomes trần duy hưng

chung cư ngoại giao đoàn

FLC Star Tower

Chung Cư Đồng Phát

Chung cư ct15 việt hưng

Chung cư 75 tam trinh

9:27 PM, August 13, 2015

 
Blogger Văn Nam said...

http://tintucchungcu.vn/
http://tintucchungcu.vn/chung-cu-ellipse-tower.html
http://tintucchungcu.vn/chung-cu-the-sparks-duong-noi.html
http://tintucchungcu.vn/chung-cu-gamuda.html
http://tintucchungcu.vn/chung-cu-dong-phat.html
http://tintucchungcu.vn/chung-cu-ct2-kim-van-kim-lu.html
http://tintucchungcu.vn/chung-cu-87-linh-nam-horizon-city.html
http://tintucchungcu.vn/chung-cu-hateco-hoang-mai.html
http://tintucchungcu.vn/chung-cu-136-ho-tung-mau.html
http://tintucchungcu.vn/chung-cu-dong-do.html
http://tintucchungcu.vn/ban-chung-cu-99-tran-binh-cau-giay-ha-noi.html
http://tintucchungcu.vn/ban-chung-cu-125-hoang-ngan-cac-can-goc-dep.html
http://tintucchungcu.vn/chung-cu-imperia-garden.html
http://tintucchungcu.vn/chung-cu-ct36-dinh-cong.html
http://tintucchungcu.vn/mo-ban-dot-cuoi-chung-cu-109-nguyen-tuan.html
http://tintucchungcu.vn/ban-chung-cu-60b-nguyen-huy-tuong.html
http://tintucchungcu.vn/ban-chung-cu-203-nguyen-huy-tuong.html
http://tintucchungcu.vn/chung-cu-my-son-tower.html
http://tintucchungcu.vn/chung-cu-hongkong-tower-de-la-thanh.html
http://tintucchungcu.vn/chung-cu-ct4-hoang-minh-giam-trung-hoa.html
http://tintucchungcu.vn/chung-cu-thanh-an-tower-21-le-van-luong.html
http://tintucchungcu.vn/ban-chung-cu-n04-hoang-dao-thuy.html
http://tintucchungcu.vn/chung-cu-trung-yen-plaza-tran-duy-hung.html
http://tintucchungcu.vn/chung-cu-golden-palace.html
http://tintucchungcu.vn/du-an-chung-cu-ngoai-giao-doan.html

11:45 AM, August 14, 2015

 
Blogger Văn Nam said...

Chung cư Hà Nội

Chung cư elipse tower

Chung cư sparks dương noi

Chung cu park view risidence

Chung cư gamuda

Chung cư đồng phát

Chung cư Ct2 kim van kim lu

Chung cư 87 linh nam

Chung cư hateco

Chung cư 136 ho tung mau

Chung cu dong do

Chung cu 99 tran binh

Chung cư 125 hoang ngan

Chung cu Imperia garden

Chung cu Ct36 dinh cong

Chung cu 109 nguyen tuan

Chung cu 60b nguyen huy tuong

Chung cu 203 nguyen huy tương

Chung cu my son tower

Chung cu hong kong tower

Chung cu Ct4 hoàng ngân

Chung cu thanh an tower

Chung cu n04 hoang dao thuy

Chung cu trung yen plaza

chung cu golden palace

Chung cu ngoại giao đoàn

Chung cu phu thuong ho tay

11:46 AM, August 14, 2015

 
Blogger Văn Nam said...

Chung cư Hà Nội

Chung cư elipse tower

Chung cư sparks dương noi

Chung cu park view risidence

Chung cư gamuda

Chung cư đồng phát

Chung cư Ct2 kim van kim lu

Chung cư 87 linh nam

Chung cư hateco

Chung cư 136 ho tung mau

Chung cu dong do

Chung cu 99 tran binh

Chung cư 125 hoang ngan

Chung cu Imperia garden

Chung cu Ct36 dinh cong

Chung cu 109 nguyen tuan

Chung cu 60b nguyen huy tuong

Chung cu 203 nguyen huy tương

Chung cu my son tower

Chung cu hong kong tower

Chung cu Ct4 hoàng ngân

Chung cu thanh an tower

Chung cu n04 hoang dao thuy

Chung cu trung yen plaza

chung cu golden palace

Chung cu ngoại giao đoàn

Chung cu phu thuong ho tay

 

 

11:47 AM, August 14, 2015

 
Blogger Văn Nam said...

Chung cu Ha Noi

chung-cu-star-city-le-van-luong

chung-cu-diamond-flower-tower

chung-cu-283-khuong-trung-thanh-xuan

chung-cu-ha-dinh-tower-thanh-xuan

chung-cu-mini-thuat-phat

chung-cu-21-le-van-luong

chung-cu-vien-103-van-quan

chung-cu-diamond-blue

chung-cu-ellipse-tower-ha-dong

chung-cu-ct12-van-phu-ha-dong

chung-cu-mulberry-lane

chung-cu-sails-tower-ha-dong

chung-cu-vinafor-van-phuc

chung-cu-ctm-complex

mo-ban-chung-cu-265-cau-giay

chung-cu-discovery-complex

chung-cu-sky-view

chung-cu-vinhomes-green-city

chung-cu-bac-ha

chung-cu-intracom-trung-van

chung-cu-resco-co-nhue

chung-cu-ct-number-one

chung-cu-dolphin-plaza-my-dinh

chung-cu-tan-tay-do-ct2b

chung-cu-136-ho-tung-mau

chung-cu-hai-dang-city

chung-cu-ct2a-co-nhue

chung-cu-21-le-duc-tho

chung-cu-102-truong-chinh

chung-cu-187-tay-son

chung-cu-watermark-ho-tay

chung-cu-ngoai-giao-doan

chung-cu-mini-kim-cuong-xuan-dinh

chung-cu-lotus-lake-view

chung-cu-mipec-riverside

10:14 PM, August 14, 2015

 
Blogger giao đỗ said...

got talent
Goldsilk complex
parkview residence
Dự án goldsilk complex
Chung cư FLC Twin Towers
chung cư Vinafor Vạn Phúc
chung cư Hanoi Landmark 51
chung cư Yên hòa Condominium
chung cư park view residence
chung cư Đặng Xá
Chung cư Hà Nội

11:13 PM, August 14, 2015

 
Blogger Văn Nam said...

Chungcu Hà Nội

ban-chung-cu-new-skyline

chung-cu-89-phung-hung-ha-dong

ban-chung-cu-hud-3-tower

mo-ban-chung-cu-unimax-ha-dong

chung-cu-golden-land

du-an-the-manor-central-park

chung-cu-d1-ct2-linh-dam

chung-cu-ct3-linh-dam

mo-ban-chung-cu-d2-ct2-linh-dam

mo-ban-chung-cu-a1-ct2-linh-dam

dang-ky-mua-chung-cu-122-vinh-tuy

dang-ky-mua-chung-cu-b1-b2-linh-dam

chung-cu-283-khuong-trung-thanh-xuan

chung-cu-so-2-kim-giang

ban-chung-cu-my-son

chung-cu-comatce-tower

chung-cu-164-khuat-duy-tien

ban-chung-cu-oct2-xuan-phuong

chung-cu-home-city-trung-kinh

dang-ky-mua-chung-cu-e2-yen-hoa

chung-cu-trung-yen-plaza-trung-hoa-cau-giay

chung-cu-e4-yen-hoa-mo-ban

mo-ban-flc-265-cau-giay

chung-cu-g3ab-yen-hoa-cau-giay

ban-chung-cu-phuc-thinh-tower

ban-chung-cu-mekong-plaza

chung-cu-thang-long-number-one

mo-ban-chung-cu-viwaseen-tower

chung-cu-n04-hoang-dao-thuy

chung-cu-can-bo-cong-chuc-quan-tay-ho

chinh-thuc-mo-ban-chung-cu-ngoai-giao-doan

chung-cu-ct04-nam-thang-long

áo dota 2

12:23 AM, August 17, 2015

 
Blogger Văn Nam said...

[URL=http://chungcumoi.biz/]Chung cu Ha Noi[/URL]
[URL=http://chungcumoi.biz/ban-chung-cu-helios-tower.html]Ban chung cu Helios Tower[/URL]
[URL=http://chungcumoi.biz/vinhomes-times-city-park-hill.html]Vinhomes Times City[/URL]
[URL=http://chungcumoi.biz/chung-cu-87-linh-nam.html]Chung cu 87 Linh Nam[/URL]
[URL=http://chungcumoi.biz/chung-cu-hoa-binh-green-city.html]Chung cu Hoa Binh Green City[/URL]
[URL=http://chungcumoi.biz/chung-cu-helios-tower.html]Chung cu Helios Tower[/URL]
[URL=http://chungcumoi.biz/chung-cu-gamuda.html]Chung cu Gamuda[/URL]
[URL=http://chungcumoi.biz/ban-chung-cu-ho-guom-plaza.html]Ban chung cu Ho guom Plaza[/URL]
[URL=http://chungcumoi.biz/ban-chung-cu-pcc1-complex.html]Ban chung cu Pcc1 Complex[/URL]
[URL=http://chungcumoi.biz/ban-chung-cu-van-phu-victoria.html]Ban chung cu Van Phu Victoria[/URL]
[URL=http://chungcumoi.biz/chung-cu-89-phung-hung.html]Chung cu 89 Phung Hung[/URL]
[URL=http://chungcumoi.biz/chung-cu-ellipse-tower.html]Chung cu ellipse[/URL]
[URL=http://chungcumoi.biz/chung-cu-park-view-residence.html]Chung cu Park View Residence[/URL]
[URL=http://chungcumoi.biz/chung-cu-hp-landmark-tower.html]Chung cu HP Landmark[/URL]
[URL=http://chungcumoi.biz/chung-cu-hh2-abc-duong-noi.html]Chung cu HH2 ABC Duong Noi[/URL]
[URL=http://chungcumoi.biz/chung-cu-goldsilk-complex.html]Chung cu Goldsilk Complex[/URL]
[URL=http://chungcumoi.biz/chung-cu-unimax-ha-dong.html]Chung cu Unimax[/URL]
[URL=http://chungcumoi.biz/ban-chung-cu-star-city.html]Ban chung cu Star City[/URL]
[URL=http://chungcumoi.biz/chung-cu-102-truong-chinh.html]Chung cu 102 Truong Chinh[/URL]
[URL=http://chungcumoi.biz/chung-cu-eco-green-city.html]Chung cu Eco Green City[/URL]
[URL=http://chungcumoi.biz/chung-cu-203-nguyen-huy-tuong.html]Chung cu 203 Nguyen Huy Tuong[/URL]
[URL=http://chungcumoi.biz/chung-cu-five-star.html]Chung cu Five Star[/URL]
[URL=http://chungcumoi.biz/chung-cu-60b-nguyen-huy-tuong.html]Chung cu 60b Nguyen Huy Tuong [/URL]
[URL=http://chungcumoi.biz/chung-cu-golden-central-tower.html]Chung cu Golden Central[/URL]
[URL=http://chungcumoi.biz/chung-cu-trang-an-complex.html]Chung cu Trang An[/URL]
[URL=http://chungcumoi.biz/ban-chung-cu-trang-an-complex.html]Ban chung cu Trang An Complex[/URL]
[URL=http://chungcumoi.biz/chung-cu-ct1a-ct1b-nghia-do.html]Chung cu CT1a,CT1b Nghia Do[/URL]
[URL=http://chungcumoi.biz/chung-cu-219-trung-kinh.html]Chung cu 219 Trung Kinh[/URL]
[URL=http://chungcumoi.biz/ban-chung-cu-dream-town.html]Ban chung cu Dream Town[/URL]
[URL=http://chungcumoi.biz/chung-cu-gemek-tower.html]Chung cu Gemek Tower[/URL]
[URL=http://chungcumoi.biz/chung-cu-ct-number-one.html]Chung cu Ct Number One[/URL]
[URL=http://chungcumoi.biz/chung-cu-ct36-dinh-cong.html]Chung cu CT36 Dinh Cong[/URL]
[URL=http://chungcumoi.biz/chung-cu-mipec-riverside.html]Chung cu Mipec[/URL]
[URL=http://chungcumoi.biz/chung-cu-36-hoang-cau.html]Chung cu 36 hoang Cau[/URL]
[URL=http://chungcumoi.biz/chung-cu-vinhomes-nguyen-chi-thanh.html]Chung cu Vinhomes Nguyen Chi Thanh[/URL]
[URL=http://chungcumoi.biz/chung-cu-sunrise-tower.html]Chung cu Sunrise Tower[/URL]

11:05 PM, August 19, 2015

 
Blogger Văn Nam said...

Chung cu Ha Noi

Ban chung cu Helios Tower

Vinhomes Times City

Chung cu 87 Linh Nam

Chung cu Hoa Binh Green City

Chung cu Helios Tower

Chung cu Gamuda

Ban chung cu Ho guom Plaza

Ban chung cu Pcc1 Complex

Ban chung cu Van Phu Victoria

Chung cu 89 Phung Hung

Chung cu ellipse

Chung cu Park View Residence

Chung cu HP Landmark

Chung cu HH2 ABC Duong Noi

Chung cu Goldsilk Complex

Chung cu Unimax

Ban chung cu Star City

Chung cu 102 Truong Chinh

Chung cu Eco Green City

Chung cu 203 Nguyen Huy Tuong

Chung cu Five Star

Chung cu 60b Nguyen Huy Tuong

Chung cu Golden Central

Chung cu Trang An

Ban chung cu Trang An Complex

Chung cu CT1a,CT1b Nghia Do

Chung cu 219 Trung Kinh

Ban chung cu Dream Town

Chung cu Gemek Tower

Chung cu Ct Number One

Chung cu CT36 Dinh Cong

Chung cu Mipec

Chung cu 36 hoang Cau

Chung cu Vinhomes Nguyen Chi Thanh

Chung cu Sunrise Tower

11:06 PM, August 19, 2015

 
Blogger Văn Nam said...

Chung cu Ho Guom Plaza

Chung cu New Skyline

Chung cu 89 Phung Hung

Chung cu Van Phu Victoria

Chung cu Hyundai Hillstate

Chung cu Mulberry Lane

Park View Residence

FLC Star Tower

Chung cu Vinafor Plaza

Ha Noi Garden City

CT36 Dream Home

Chung cu Golden Silk

Chung cu Helios Tower

Chung cu Hapulico Complex

Chung cu My Son Tower

Chung cu Sapphire Palace

Chung cu 283 Khuong Trung

FLC Complex

Goldmark City 136 Hồ Tùng Mậu

Chung cu 265 Cau giay

Chung cu Home City

Chung cu Green Stars

Lien ke 378 minh Khai

Chung cu Sun Square

Thang Long Number One

Chung cu Bac Ha Tower

Chung cu CT1 Trung Van

Hai Dang City

Chung cu Hong Kong

Chung cu ngoai giao doan

 

8:13 AM, August 21, 2015

 
Blogger Văn Nam said...

Chung cu Goldsilk Complex

Goldsilk Complex

Mat bang chung cu Goldsilk Complex

Gia ban chung cu Goldsilk Complex

Lien he

 

7:59 AM, August 23, 2015

 
Blogger Văn Nam said...

http://chungcuecolife.net/
http://chungcuecolife.net/mat-bang-chung-cu-ecolife-capitol
http://chungcuecolife.net/gia-ban-chung-cu-ecolife-capitol
http://chungcuecolife.net/lien-he-mua-can-ho-ecolife-capitol
http://chungcuecolife.net/mot-so-mau-thiet-ke-can-ho-ecolife-capitol.html
http://chungcuecolife.net/tien-do-chung-cu-ecolife-capitol-ngay-24-8-2015.html

8:32 AM, August 25, 2015

 
Blogger Văn Nam said...

Chung cư Ecolife

Ecolife Capitol

Chung cư Ecolife Capitol

Dự án Ecolife Capitol

Mặt bằng Ecolife Capitol

Giá bán Ecolife Capitol

Thiết kế Ecolife Capitol

Tiến độ Ecolife Capitol

8:32 AM, August 25, 2015

 
Blogger Văn Nam said...

Chung cư Ecolife

Ecolife Capitol

Chung cư Ecolife Capitol

Dự án Ecolife Capitol

Mặt bằng Ecolife Capitol

Giá bán Ecolife Capitol

Thiết kế Ecolife Capitol

Tiến độ Ecolife Capitol

8:33 AM, August 25, 2015

 
Blogger Văn Nam said...

Chung cu Goldmark City

Goldmark City

Mat bang chung cu Goldmark City

Gia ban chung cu Goldmark City

Tien do du an chung cu Goldmark City

Nha mau chung cu Goldmark City

Lien he mua chung cu Goldmark City

Tin tuc du an chung cu Goldmark City

8:46 AM, August 27, 2015

 

Post a Comment

Subscribe to Post Comments [Atom]

<< Home

 

If you like this blog, you might also like top photography schools.