I should probably run with it and try to get everybody super offended, to the point where you have no idea what my point is because all you can see is red. I guess I'll have to leave that for a future milestone...
Because, yeah, I'm not really serious. Rails has a place at the office. And no, this isn't going to be one of those "Is Rails ready for the Enterprise?" posts. Rails is perfectly ready for use in the Enterprise, but that's the wrong question. As usual, the right question is much more complicated.
To start with, let me point out that this conversation has nothing to do with Ruby vs. C#. It doesn't really have anything to do with Rails vs ASP.NET MVC either. Instead I'm going to be talking about Active Record vs. Data Mapper, and View-Models vs. no View-Models, and this general concept of "the straight and narrow" vs. explicit abstraction and control. These are design patterns which apply to any language and appear in many different frameworks.
Rob Conery recently wrote a blog post in which he said,
For a lot of .NET/Java devs this will look "messy" - you shouldn't elevate "data concerns" into your model. This argument makes good sense for a large, complex site - that you're building in C# or Java. Typically Ruby focuses on the straight, narrow path and with that comes a dramatic turn towards "doing what you need to do... and no more". This resonates with me...The part about Ruby/Rails focusing on "the straight and narrow path" really struck a chord for me. Ruby, being a dynamic language, is very much on the "straight and narrow." It dispenses with all kinds of things found in strongly typed languages like private, internal, protected, interfaces, etc. These are things that are usually considered very important in a strongly typed language, and practices like DDD, but Ruby doesn't really bother with them. Ruby favors documentation and convention over strict control.
Rails has a similar story. It uses the Active Record pattern for its data access, which requires a 1-1 correspondence with your database. Further, the models don't even really exist! They're built dynamically from the schema of the database tables.
If you compare ASP.NET MVC to Rails one of the differences you'll quickly discover is this concept of a "View-Model". ASP.NET peeps seem to like these, whereas I haven't found a Rails sample anywhere that uses these. Both Active Record and this lack of a View-Model are accomplishing the same thing: removing abstraction in favor of directness and simplicity.
Now lets step back from this for a second and ask a question. Who in there right mind would want to have to deal with things like class and method visibility and extra layers of abstraction, which more often than not appear to be just duplication? No one! No one would want to deal with these things! It's extra work! I _hate_ extra work!
So why do we do it? Why does DDD make a big deal out of private constructors and Factories? Why does Fowler recommend the Data Mapper pattern over Active Record? Why do we create View-Models to separate our Views from our Models? Why do we do all these things that seem to just make life more complicated? Why don't we all take the straight and narrow path on all of our projects all of the time?
Certainly it's not as simple as the language we're using. Just because you're writing in C# and Java doesn't mean you can't use Active Record. And it doesn't mean you can't pass your Model straight to your View. There is also nothing about C# or Java that forces you to use interfaces, or follow the Dependency Inversion Principle. That said, there's also no reason why you couldn't use the Data Mapper pattern in Ruby, or create View-Models. The language certainly HELPS with some of these issues, but it's not the real difference. These are just patterns, and they apply equally well to any language.
The reason why we introduce this complexity and divert from the straight and narrow path in our technical approach is actually due primarily to non-technical reasons. Here are some of the reasons I think lead us to adopt these "enterprise" patterns:
- There are more than two or three developers on the project
- You have more than 6 entities in the domain
- The project has a timeline longer than 3 months
- The developers aren't intimately familiar with the domain
- The project is likely to grow in fits and starts
- The team members are more likely to come and go
These are not technical issues but they have technical IMPLICATIONS!
The practices prescribed by DDD are a big deal if you're working with a large complicated domain with lots of potential for change. If you're not, then you don't need DDD. Fowler's enterprise patterns are a big deal for the same reasons. If you know things are complicated, likely to change, and not possible for everyone on the team to grok completely, then you need to build abstraction into your code. And you need to try to be as explicit as you possibly can about what the code does and how it works. And you need to look for opportunities to prevent error and misunderstanding before it happens. These things will allow you to keep things clean, organized, and ultimately make your project successful when you're faced with "enterprise" challenges.
This is obvious. I'm sure you're sitting there (or standing) thinking, "duh!" or "when is this dude going to get to the point?" or "does this moron really think this is revolutionary?!"
My point is as simple as this. Rails is awesome. Simplicity is awesome. But as I sit here in my ivory tower looking out over the landscape I see lots of quiet subtle backlash from people against the "enterprise-y" patterns in favor of the simplicity of Rails. This makes a lot of sense to me because, as we pointed out, who would WANT to deal with the complexity of enterprise problems and patterns? But it is easy to be tempted by the appeal of simple solutions to simple projects. And certainly we should always strive to find the simplest solution that could possibly work. But we can not close our eyes to the complexities of the problem or the environment in which we are solving the problem. And we cannot allow ourselves to be boiled alive either.
So by all means, choose the right tool for the right job, but make sure you understand the job as well as you understand the tool.
The thing that trips this up for me is that a lot of people think their domain is way more complex then it really is. Now, i'm not saying thats the situation in your world, I'm just saying when you have a large enterprise and you pay people who have a job title like "Software architect" there tends to be a kind of unintentional exaggeration as to the true complexity in their domain.
ReplyDeleteIt's been 5 years now I've done business apps, and I've done them for something like 10 companies both full time and as a consultant, and over engineering is a rule of our profession. Some of the projects I've worked on have had abstraction upon abstraction because everyone wants to think their world is super complex and unique and special. To paraphrase "You're app is not a beautiful or unique snowflake."
I guess my point is I wouldn't want an enterprise to write off a really awesome platform like Ruby (on rails) because of a perception that their domain is more complex then it really is.
Yeah, I agree. Its a classic pendulum swing thing: In response to people making things too complicated people make things too simple.
ReplyDeleteThis is why the refactor step of TDD and DDD is both the most important and most misunderstood.
Great post, I was looking forward to being offended but you didn't do it :).
ReplyDeleteWhat Josh said is very much in tune with what I was going to mention. I think as programmers we get geeked up about solving complex problems. I think sometimes that causes us to fabricate complexity that isn't really needed to deliver value to the software. Sometimes "enterprise" just means big (lots of features) but not necessarily complex. I think as easy as it is to close our eyes to the complexity of our problems, its even easier to close them to how simple the solutions can be to those problems.
I also think that just because a framework like Rails encourages a "straight and narrow" mentality doesn't mean it can't solve complex problems just as well if not better at times.
I agree 100% with the "right tool for the job" mentality. I just hate to see companies and projects overlook it when I think it could be of great value to them in the long run.
Lee: I agree. But the complexity of the problem isn't the only factor in the architecture of the solution.
ReplyDeleteFor example, if your app is "big" but has some overlap (ex: different views using the same entities) you're going to want to protect yourself from changes for one thing breaking other things.
In a case like this where most things are simple, but some have overlap, you might want to go the standard Rails approach by default and add View-Models when needed.
So maybe you don't have to throw out Rails, you just need to apply some "enterprise-y" patterns to it. Unfortunately, due to the Rails "mindset", it *might* fight you in some of those areas.
Is what you outlined your *real* concern, or is it the fact that they just had three releases of Rails within about a week?
ReplyDelete