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!

73 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 Quanhkhai Quangkhai said...

Thông tin vị trí chung cư Tháp Doanh Nhân Hà Đông mở bán đợt 1 | Tiện ích chung cư Tháp Doanh Nhân Hà Đông được cập nhật mới nhất tại website Thapdoanhnhan.ifo | Tổng thể dự án chung cư Tháp Doanh Nhân Hà đông tọa lạc số 1 đường Thanh Bình | cập nhật thông tin giá bán chung cư Tháp Doanh Nhân Hà Đông mới nhất | chung cư Tháp Doanh Nhân Hà Đông mở bán 150 căn hộ cao cấp | Chung cư Tháp Doanh Nhân đã bán được 50 căn hộ trong 1 tuần | Dự án Tháp Doanh nhân do Anh Quân Strong làm chủ đầu tư | Tháp Doanh Nhân Hà Đông tòa nhà cao 45 tầng | căn hộ Tháp Doanh Nhân ra mắt thị trường Hà Nội

7:37 PM, May 17, 2016

 
Blogger Tuấn Hoàng said...

Imperia Sky Garden?ở đâu?
chung cư Imperia Sky Gardenđã có thể mua r?i
chung cư Imperia Sky Garden Minh Khaikhông g? tuy?t hơn
Imperia Minh Khaiv?i ti?n ích n?i khu n?i b?t
Imperia 423 Minh Khaiđ? có nhà m?u
Imperia Sky Garden Minh Khai xây g?n xong
Imperia Sky Garden 423 Minh Khai đ? m? bán
Imperia Garden Minh Khai vô cùng đ?p
Imperia Garden 423 Minh Khai v?i nhi?u ưu đ?i kh?ng

ch? đ?u tư uy tín c?a Chung cư Imperia Sky Garden 423 Minh Khai
v? trí Bán chung cư Imperia Sky Garden
ti?n ích Dự án Imperia Sky Garden
t?ng quan Dự án chung cư Imperia Sky Garden
b?ng giá chung cư 423 Minh Khai
ti?n đ? chung cư Imperia Garden Minh Khai
đ?t mua Tổngng quan chung cư Imperia Sky Garden
bánThông tin chung cư Imperia Sky Garden
n?i th?t Tổngng quan dự án Imperia Sky Garden

8:21 PM, May 17, 2016

 
Blogger Lai Weizhou said...

chung cư tháp doanh nhân
tháp doanh nhân / tháp doanh nhân hà đông / dự án tháp doanh nhân hà đông / chung cư the legend / chung cư the legend 109 nguyễn tuân
chung cư 360 giải phóng / dự án 360 giải phóng / chung cư vietracimex / chung cư 201 minh khai / chung cư thanh xuân tower / chung cư 35 lê văn thiêm
chung cư eco green city / chung cu eco green city / chung cư eco green city nguyễn xiển / chung cu eco green city nguyen xien / eco green city / eco green city nguyễn xiển / dự án eco green city / toà ct4 eco green city / toà ct3 eco green city / toà ct1 eco green city

9:51 PM, May 17, 2016

 
Blogger Dương Phạm said...

Chung cư gamuda
Biệt thự gamuda
Liền kề gamuda


Biệt thự gamuda
Biệt thự đơn lập Gamuda
Biệt thự song lập gamuda
Chung cư gamuda
Liền kề gamda
Biet thu gamuda
Biệt thự Gamuda Gardens
Giá biệt thự gamuda
Biet thu mau Gamuda Gardens
Biệt thự gamuda city
Biệt thự gamuda gardens
Gamuda Garden
Biệt thự gamuda
Biet thu gamuda
Bán biệt thự gamuda
Biệt thự Gamuda Gardens
Giá biệt thự gamuda
Biet thu mau Gamuda Gardens
Biệt thự gamuda city
Biệt thự gamuda gardens
Gamuda Garden
Bán biệt thự đơn lập gamuda
Bán biệt thự đơn lập gamuda
Bán biệt thự đơn lập gamuda
Bán biệt thự song lập gamuda
Biệt thự song lập gamuda
Giá biệt thự song lập gamuda
Chung cư gamuda city the one
Chung cư gamuda city the two
Liền kề gamuda
Lien ke gamuda
Nhà liền kề gamuda
Nhà liền kề gamuda gardens
Liền kề gamuda giai đoạn 2

1:26 AM, May 18, 2016

 
Blogger Dương Phạm said...

Biệt thự Gamuda
Biet thu Gamuda
Biet thu Gamuda Gardens
Biệt thự Gamuda Gardens
Biet thu Gamuda City
Biệt thự Gamuda City
Giá bán Biệt thự Gamuda
Biệt thự liền kề Gamuda
Biệt thự Gamuda Garden
Biệt thự mẫu Gamuda
Biet thu mau Gamuda Gardens


Don lap Gamuda
Đơn lập Gamuda
Biệt thự đơn lập Gamuda
Biet thu don lap Gamuda
Ban biet thu don lap Gamuda
đơn lập Gamua Gardens
don lap Gamuda Gardens
Mặt bằng biệt thự đơn lập Gamuda
Mat bang biet thu don lap Gamuda

Song lap Gamuda
Song lập Gamuda
Biệt thự song lập Gamuda
Biet thu song lap Gamuda
Ban biet thu song lap Gamuda
Song lập Gamua Gardens
Song lap Gamuda Gardens
Mặt bằng biệt thự song lập Gamuda
Mat bang biet thu song lap Gamuda

1:26 AM, May 18, 2016

 
Blogger Dương Phạm said...

Gold Season Nguyễn Tuân
Chung cư Gold Season 47 Nguyễn Tuân
Chung cư Gold Season Nguyễn Tuân
Chung cư Nguyễn Tuân
Chung cư Gold season
Chung cư 47 Nguyễn Tuân
Gold Season 47 Nguyễn Tuân
Gold Season
Chung cư goldseason 47 nguyễn tuân
Goldseason Nguyễn Tuân
chung cư goldseason nguyễn tuân
Chung cư goldseason
Goldseason 47 Nguyễn Tuân
Goldseason
Chung cu Gold Season Nguyen Tuan
Chung cu Nguyen Tuan
Chung cu 47 Nguyen Tuan
Gold Season 47 Nguyen Tuan
Chung cu goldseason 47 Nguyen tuan
Goldseason Nguyen Tuan
Chung cu goldseason Nguyen tuan
Chung cu goldseason
Goldseason 47 Nguyen Tuan
Gold season hà nội
47 nguyễn tuân
Bán chung cư Nguyễn Tuân
Bán chung cư 47 Nguyễn Tuân
Dự án Goldseason

1:26 AM, May 18, 2016

 
Blogger Lai Weizhou said...

chung cư tháp doanh nhân
tháp doanh nhân / tháp doanh nhân hà đông / dự án tháp doanh nhân hà đông / chung cư the legend / chung cư the legend 109 nguyễn tuân
chung cư 360 giải phóng / dự án 360 giải phóng / chung cư vietracimex / chung cư 201 minh khai / chung cư thanh xuân tower / chung cư 35 lê văn thiêm
chung cư eco green city / chung cu eco green city / chung cư eco green city nguyễn xiển / chung cu eco green city nguyen xien / eco green city / eco green city nguyễn xiển / dự án eco green city / toà ct4 eco green city / toà ct3 eco green city / toà ct1 eco green city

11:06 AM, May 21, 2016

 
Blogger youncy said...

obat diabetes alami
obat kolesterol alami
obat asam urat alami

obat diabetes alami
obat kolesterol alami
obat asam urat alami

manfaat minyak lintah
minyak lintah asli
khasiat minyak lintah

Agen Domino
Agen Poker
Agen Domino QQ

7:56 AM, May 22, 2016

 
Blogger Abraham Ngoc said...

Chung cư Gamuda City
chung cu gamuda city
chung cư gamuda


SOng lập Gamuda
Biệt thự song lập Gamuda
Liền kề Gamuda
lien ke gamuda
Biệt thự Gamuda
Biệt thự liền kề gamuda

nhà liền kề gamuda
biệt thự nhà vườn gamuda
Biệt thự đơn lập gamuda

Bán liền kề Gamuda
bán nhà liền kề gamuda
Biet thu song lap gamuda
dự án gamuda city
khu đô thị gamuda gardens
Gamuda gardens
Gamuda city
Gamuda yên sở
Chung cư yên sở
Chung cư Pháp Vân
Chung cư the wings
The wings gamuda
Chung cư the wings gamuda

9:30 PM, May 22, 2016

 
Blogger Hà la said...

Giới thiệu dự án Chung cư An Bình city
Cập nhật mới nhất về Tiến độ chung cư An Bình city Hãy xem chi tiết Mặt bằng căn hộ An Bình city xem kiểu Thiết kế căn hộ Chung cư An Bình city Vui lòng hãy xem Bảng giá Chung cư An Bình city. dự án An Bình city , liên hệ An Bình city, Dự án An Bình city phạm văn đồng.

7:17 AM, May 24, 2016

 
Blogger Hà la said...


Xem thêm: chung cư rivera park hà nội.

7:17 AM, May 24, 2016

 
Blogger Ổn áp Standa said...

I simply could not depart your website before suggesting that I extremely loved the usual info an individual supply on your visitors? Is going to be again frequently to check up on new posts
on ap lioa|on ap standa

12:22 AM, May 25, 2016

 
Blogger Lê Hùng said...

Nội thất cao cấp
Nội thất chung cư
Thi công tủ bếp gỗ óc chó
Thi công bàn ghế gỗ óc chó
Thi công bàn ăn gỗ óc chó
Chung cư thanh hà cienco 5  
Liền kề thanh hà cienco 5
Biệt thự thanh hà cienco 5
Đất nền thanh hà cienco 5
Bàn trà cao cấp
Kệ tivi cao cấp 
sofa cao cấp
Giường ngủ cao cấp
Tủ áo cao cấp
Bàn phấn cao cấp
Tủ bếp cao cấp
Bàn ăn cao cấp
Dự án Vinh Plaza 
Chung cư thanh hà cienco 5
Chung cư Vinh Plaza
Chung cư xuân mai riverside
xem báo mạng
Ẩm thực Việt Nam

11:40 PM, May 27, 2016

 
Blogger chi nguyen said...

Những bài thuốc thoát vị đĩa đệm bằng đông y , những cách bệnh viêm khớp bằng thuốc dân gian , chữa bệnh thoái hóa khớp bằng cách gì , viêm khớp dạng thấp làm sao chữa được ? chữa thoái hóa cột sống như thế nào , viêm đại tràng

bệnh phong tê thấp ,chữa gai cột sống cùng tìm hiểu sâu hơn về benh dau xuong khop cách chữa rối loạn kinh nguyệt bằng thuốc đông y rối loạn kinh nguyệt sau phá thai ,rối loạn kinh nguyệt sau quan hệ , cách chữa bệnh thoái hóa đốt sống cổ bằng đông y trào ngược dạ dày
, benh thoai hoa khop goi ,
đau dạ dày

2:25 AM, May 30, 2016

 
Blogger chi nguyen said...

điều trị đau dạ dày
điều trị bệnh trào ngược dạ dày
chữa viêm loét dạ dày
bệnh viêm đại tràng


2:25 AM, May 30, 2016

 
Blogger Zhenhong Bao said...

hollister shirts
burberry outlet sale
ralph lauren polo
ralph lauren outlet
nba jerseys
ralph lauren uk
louis vuitton bags cheap
cheap soccer jerseys
mbt shoes outlet
ray ban sunglasses
michael kors outlet
michael kors outlet
swarovski outlet
michael kors outlet
louboutin pas cher
fitflops shoes
true religion outlet
rolex watches
air jordan shoes
snapbacks wholesale
fitflop sale
calvin klein outlet
michael kors outlet
michael kors handbags
swarovski crystal
fitflops sale clearance
michael kors outlet
coach outlet
fitflops sale
longchamp solde
true religion outlet
mulberry outlet
longchamp outlet online
michael kors outlet online
tiffany outlet
20160531zhenhong

6:24 PM, May 30, 2016

 
Blogger Mai Văn Học said...

nấm lim xanh
nam lim xanh
công dụng của nấm lim xanh
cách sử dụng nấm lim xanh
http://namlimxanhtienphuoc.com/

1:18 AM, May 31, 2016

 
Anonymous Agen judi bola said...

Agen Judi Bola
Casino Online Terpercaya
Agen Bola Terpercaya

8:33 AM, June 02, 2016

 
Anonymous Taruhan Bola Online said...

Agen Bola
Judi Bola
Taruhan Bola Online

8:32 AM, June 06, 2016

 
Blogger Bột yến mạch said...

bơ đậu phộng
bơ đậu phộng
bơ đậu phộng
bùn khoáng nha trang
bùn khoáng nha trang
bùn khoáng nha trang
đèn pha led

10:00 AM, June 07, 2016

 
Blogger FarmDeamon said...

thanks for pointing out they loop hole.
Slither.io
Slither.io
Supersnake.io
SHAREit for PC
Android Apk
Slither.io for pc
Diep.io
Angry Birds Games
facebook full site
whatsapp download for laptop
Apps for pc
Android Apps for PC

1:59 PM, June 11, 2016

 
Anonymous Anonymous said...

Cocobay Resort Đà Nẵng

Cocobay Resort

Dự án Coco Bay Đà Nẵng

Cocobay Đà Nẵng

Cocobay ocean resort đà nẵng

Căn Hộ CocoBay Đà Nẵng

Condotel CocoBay Ocean Resort Đà Nẵng

SOLEIL ĐÀ NẴNG

ConDoTel SOLEIL ĐÀ NẴNG

Dự án ánh dương đà nẵng

Ánh Dương Soleil Đà Nẵng

dự án Soleil Đà Nẵng

Chung Cư Việt Đức Complex

Chung Cư MBLand Central Point Mỹ Đình

Chung Cư MBLand Mỹ Đình

Dự án MBLand Mỹ Đình

MBLand Mỹ Đình

MBLand Central Point Mỹ Đình

Chung cư The Garden Hill

Chung cư 99 Trần Bình

Dự án 99 Trần Bình

Chung Cư Xuân Mai Riverside

Chung Cư 150 Thanh Bình

10:25 AM, June 13, 2016

 
Anonymous Anonymous said...

Chung Cư Golden Field
Dự án Golden field mỹ đình
Golden field mỹ đình
Golden field
Chung Cư Golden field mỹ đình
Cocobay Resort Đà Nẵng
Cocobay Resort
Dự án Coco Bay Đà Nẵng
Cocobay Đà Nẵng
Cocobay ocean resort đà nẵng
Căn Hộ CocoBay Đà Nẵng
Condotel CocoBay Ocean Resort Đà Nẵng
SOLEIL ĐÀ NẴNG
ConDoTel SOLEIL ĐÀ NẴNG
Dự án ánh dương đà nẵng
Ánh Dương Soleil Đà Nẵng
dự án Soleil Đà Nẵng
Chung Cư Việt Đức Complex
Chung Cư MBLand Central Point Mỹ Đình
Chung Cư MBLand Mỹ Đình
Dự án MBLand Mỹ Đình
MBLand Mỹ Đình
MBLand Central Point Mỹ Đình
Chung cư The Garden Hill
Chung cư 99 Trần Bình
Dự án 99 Trần Bình
Chung Cư Xuân Mai Riverside
Chung Cư 150 Thanh Bình
Bán Suất ngoại giao biệt thự xuân phương
Biệt Thự Liền Kề Xuân Phương Tasco
Biệt Thự xuân Phương
Biệt Thự Xuân Phương Tasco
KHU LIỀN KỀ XUÂN PHƯƠNG TASCO
Khu Nhà Mặt Phố Xuân Phương Tasco
Liền Kề Xuân Phương Tasco

8:53 PM, June 15, 2016

 
Blogger chungcuhanoi said...

Real Estate in VietNam
chung cư sun square giá rẻ
chung cư pvv vinapharm tower
chung cư 60b nguyễn huy tưởng
chung cư 317 trường chinh
chung cư e4 yên hòa
e4 vũ phạm hàm
e4 yên hòa
chung cư e4 trung yên
chung cư e4 tower yên hòa
chung cư e4
dự án e4 vũ phạm hàm
chung cư e4 vũ phạm hàm
chung cư e4 yên hoà
e4 yên hoà
chung cư e4 yên hòa
chung cư sun square 21 lê đức thọ
chung cư pvv vinapharm
chung cư hongkong tower
chung cư hong kong tower
chung cư hongkong tower 243a đê la thành
chung cư hongkong tower
chung cư udic riverside
chung cư udic riverside 122 vĩnh tuy
chung cư 122 vĩnh tuy

2:15 AM, June 19, 2016

 
Blogger chungcuhanoi said...

chung cư imperial plaza
hong kong tower
chung cư 122 vĩnh tuy
chung cư sun square 21 lê đức thọ
chung cư 21 lê đức thọ
chung cư sun square
chung cư ngoại giao đoàn
chung cư hacinco complex
chung cư 122 vĩnh tuy
chung cư 122 vĩnh tuy
hà nội center point
chung cư hà nội center point
chung cư hà nội center point lê văn lương
chung cư vinata tower
chung cư 69b thụy khuê
chung cư 69 thụy khuê
chung cư sun legacy 69b thụy khê
chung cư 31 láng hạ
chung cư 97 99 láng hạ
chung cư an bình city suất ngoại giao
chung cư an bình city giá gốc chủ đầu tư
chung cư an bình city giá rẻ nhất thị trường
chung cư e4 yên hòa
bán chung cư e4 yên hòa
bán chung cư an bình

2:16 AM, June 19, 2016

 
Blogger chungcuhanoi said...

chung cư the legend tower
chung cư park view city yên hòa
chung cư park view city yên hòa
chung cư park view yên hòa
chung cư park view city yên hòa giá rẻ nhất thị trường
chung cư park view yên hòa suất ngoại giao
chung cư park view city giá gốc chủ đầu tư udic
chung cư park view city giá siêu rẻ
chung cư kim văn kim lũ tòa b
chung cư 440 vĩnh hưng giá gốc chủ đầu tư
chung cư t&t riverside 440 vĩnh hưng bán suất ngoại giao
chung cư t&t riverside giá rẻ nhất thị trường
chung cư rivera park hà nội chủ đầu tư long giang
chung cư rivera park hà nội giá rẻ
chung cư 69 vũ trọng phụng suất ngoại giao
chung cư an bình city phạm văn đồng suất ngoại giao
chung cư an bình city 234 phạm văn đồng
an bình city phạm văn đồng
an bình city 234 phạm văn đồng
Chung cư An Bình City
chung cu an binh city
an bình city thành phố giao lưu
an bình city geleximco
an binh city
chung cư an bình geleximco

2:16 AM, June 19, 2016

 
Blogger chungcuhanoi said...

chung cư an bình
chung cư an bình city thành phố giao lưu giá gốc chủ đầu tư
chung cư an bình city phạm văn đồng giá rẻ nhất thị trường
chung cư an bình city suất ngoại giao
an bình city giá gốc chủ đầu tư
chung cư an bình city thành phố giao lưu giá rẻ nhất thị trường
chung cư phú mỹ complex giá gốc chủ đầu tư
chung cư phú mỹ complex n01 t4 ngoại giao đoàn gía rẻ
chung cư n01 t4 ngoại giao đoàn giá gốc chủ đầu tư phú mỹ
phú mỹ complex ngoại giao đoàn suất ngoại giao
chung cư rivera park hà nội
chung cư e2 yên hòa
chung cư brg park residence
chung cư brg park residence lê văn lương
chung cư sunrise city lê văn lương
chung cư sunrise city
sunrise city lê văn lương
chung cư sunrise city lê văn lương hdi
liền kề 96 nguyễn huy tưởng
biệt thự 203 nguyễn huy tưởng
biệt thự imperia garden 203 nguyễn huy tưởng
biệt thự imperia garden
chung cư kim văn kim lũ tòa b
tòa b kim văn kim lũ tòa
chung cư the golden palm

2:17 AM, June 19, 2016

 
Blogger chungcuhanoi said...

the golden palm
chung cư the golden palm lê văn lương
the golden palm lê văn lương
liền kề tasco
xuân phương tasco liền kề
liền kề xuân phương tasco
liền kề tasco xuân phương
liền kề biệt thự xuân phương tasco
biệt thự xuân phương tasco
liền kề xuân phương
biệt thự xuân phương
biệt thự đơn lập xuân phương tasco
biệt thự song lập xuân phương tasco
nhà phố xuân phương tasco
shop house xuân phương tasco
chung cư central field
central field
chung cư central field 219 trung kính
central field 219 trung kính
chung cư 219 trung kính
chung cư golden field
golden field
chung cư golden field mỹ đình

2:17 AM, June 19, 2016

 
Blogger Xemnha Di said...

'Dự án Golden Field Mỹ Đình'
'Bán penthouse golden field mỹ đình'
'golden field mỹ đình'
'golden field'
'Chung Cư golden field'
'Dự án golden field'
'Dự án golden field Mỹ Đình'
'Dự án golden field'
' Chung Cư The Golden Palm'
' Chung Cư The Golden Palm Lê Văn Lương'
' Dự án ánh dương đà nẵng '
' Dự án soleil đà nẵng'
' Dự án soleil'
' Căn Hộ soleil Đà Nẵng'
' Condotel soleil Đà Nẵng'
'Chung Cư 150 Thanh Bình '
'Chung Cư Xuân Mai Riverside'
'Chung Cư Xuân Mai Hà Đông'
'Dự Án Xuân Mai Riverside'
'Chung cư 99 Trần Bình''
'Chung cư Trần Bình''
' Chung cư The Garden Hill''
' Dự án 99 Trần bình''
' Chung Cư Việt Đức Complex''
' Chung Cư Sô Đà Việt Đức Complex''
' Dự án Việt Đức Complex''
' Chung Cư 164 Khuất Duy Tiến''
' Biệt Thự Liền Kề Xuân Phương Tasco''
' Biệt Thự xuân Phương''
' Liền Kề Xuân Phương Tasco''
' Chung Cư Vinhomes Sky Lake Phạm Hùng''
' Vinhomes Sky Lake Phạm Hùng''
' dự án Vinhomes Sky Lake Phạm Hùng''
' Chung Cư Phạm Hùng''




9:09 AM, June 19, 2016

 
Blogger Manh Tung said...

Dự án Vinhomes Long Biên biệt thự
fhome đà nẵng nằm tại trung tâm đà nẵng.
chung cư udic riverside nằm tại 122 vĩnh tuy
dự án chung cư garden hill không
dự án chung cu garden hill vui
chung cư thăng long victory
chung cư hà nội năm 2016em
chung cư valencia gardenkhông
chung cư hd mon citybuồn
chung cư garden hill 99 trần bình
chung cư 259 yên hòaem
chung cư fhome đà nẵngkhông
chung cư 136 hồ tùng mậunhìn
chung cư five star kim giangthấy
chung cư ecogreen cityem
chung cư imperia gardenbên
chung cư thang long victory nam an khánhđẹp nhất hoài đức
biệt thự flamingo đại lảikhác
biệt thự vinpearl phú quốcphải
khu do thi sinh thai ecoparklàm
liền kề lotus residences hạ longsao
chung cư tabudec plaza đẹp nhất hà đông.
chung cư tabudec trung tâm Hà Đông.
chung cư tứ hiệp thanh trì
chung cư ecolife capitols to huu keo dai
chung cư thanh xuân Tower nằm tại quận Thanh Xuân.
Chung cư Fhome Đà Nẵng nằm tại quận Thanh Xuân.
Coco bay Hội An nằm tại thành phố Đà Nẵng.
Chung cư ecocity nằm tại quận Long Biên.
Chung cư Golden Palm Lê Văn Lương nằm tại đường Lê Văn Lương.
Chung cư Golden Field nằm
Chung cư Golden Field sở hữu vị trí vàng tại lê văn lương.
Chung cư Golden Palm tọa

8:17 PM, June 26, 2016

 
Blogger Lai Weizhou said...

chung cư 29 láng hạ / chung cư hải đăng tower / chung cư hải đăng 29 láng hạ / chung cư the artemis / chung cư artemis lê trọng tấn / chung cư the artemis số 3 lê trọng tấn

1:15 AM, June 29, 2016

 
Blogger PhuTaiLand Admin said...

Chung cư Artemis Lê Trọng Tấn
Artemis Lê Trọng Tấn
chung cư số 3 Lê Trọng Tấn
căn hộ cao cấp Artemis
căn hộ cao cấp Artemis Lê Trọng Tấn
dự án Artemis Lê Trọng Tấn
Artemis số 3 Lê Trọng Tấn
artemis le trong tan
chung cu artemis le trong tan
can ho cao cap artemis le trong tan
can ho cao cap artemis
du an artemis le trong tan
artemis so 3 le trong tan
mặt bằng căn hộ Artemis
chung cu so 3 le trong tan
vị trí chung cư artemis
vị trí chung cư Artemis lê trọng tấn
tiện ích chung cư artemis
giá bán căn hộ artemis

8:10 PM, June 30, 2016

 
Blogger xjd7410@gmail.com said...

coach outlet store online
true religion outlet
cheap jordans
beats wireless headphones
michael kors purses
ray-ban sunglasses
gucci bags
christian louboutin outlet
michael kors outlet
fitflops
tory burch outlet
adidas nmd
insanity workout
rolex watches
nike trainers
oakley sunglasses
coach outlet store online
ray ban sunglasses
hollister clothing
ray bans
coach outlet
oakley sunglasses
jeremy scott shoes
giuseppe zanotti sandals
air max 90
cheap oakleys
louis vuitton
celine bags
coach factory outlet
kevin durant shoes
nike sb shoes
instyler curling iron
coach outlet
lebron james shoes 13
coach outlet
oakley sunglasses
louis vuitton handbags
coach outlet online
adidas trainers
jordan retro
2016.7.7haungqin

9:32 PM, July 06, 2016

 
Anonymous Anonymous said...

Check here to download Prisma for Android free.

3:47 AM, July 13, 2016

 
Blogger kanna said...

For new latest updated features in single app,download allo application.
Allo for PC

7:48 AM, July 13, 2016

 
Blogger محمد الخطيب said...



شركة كشف تسربات المياه بالرياض
كشف تسربات المياه بالرياض
شركة عزل اسطح بالرياض
شركة عزل خزانات المياه بالرياض
شركه عزل مائى بالرياض
شركة عزل حرارى بالرياض
شركة ترميم منازل بالرياض
شركة مكافحة حشرات بالرياض
شركة رش مبيدات بالرياض
شركة تسليك مجارى بالرياض





شركة كشف تسربات المياه بالخبر
كشف تسربات المياه بالخبر
شركة عزل اسطح بالخبر
شركة عزل خزانات المياه بالخبر
شركه عزل مائى بالخبر
شركة عزل حرارى بالخبر
شركة ترميم منازل بالخبر
شركة مكافحة حشرات بالخبر
شركة رش مبيدات بالخبر
شركة تسليك مجارى بالخبر

4:21 PM, July 16, 2016

 
Blogger Long nhãn hưng yên said...

liền kề nam 32
bán liền kề nam 32
giá chung cư green star
green star phạm văn đồng
liền kề nam 32
green star 234 phạm văn đồng
bán liền kề tasco xuân phương
bán liền kề ao sào
liền kề thành phố giao lưu
chung cư hanoi landmark 51
chung cư 99 trần bình
chung cư 317 trường chinh
chung cư ct3 cổ nhuế
chung cư cán bộ công chức quận tây hồ
long nhãn hưng yên
chung cư handiresco lê văn lương
chung cư an bình city
bán chung cư an bình city
suất ngoại giao an bình city
nhà mẫu an bình city
giá chung cư an bình city

2:54 AM, July 19, 2016

 

Post a Comment

Subscribe to Post Comments [Atom]

<< Home

 

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