How to ruin a Rails project
Posted by Clifford Heath on October 18, 2007 at 10:37 PM
There are lots of ways to ruin any project. I’ve seen most of them over the last few decades, but this year I’ve been called in to salvage a series of Rails projects that were, well, off the rails, in some ways that maybe special to Rails. So I’ll try to steer clear of the ordinary foul-ups, and focus on the ones that Rails seems to attract.
We have four months before the website is needed, and Rails is so productive that we don’t need to get started yet. We can deliver the specifications in a couple of months or so, and everyone will be ready to knock out the website in two weeks. Right. Let me know how that goes, ok?
Databases suck, no-one wants to write SQL, and I can’t do all my validations in it anyhow, so why should I do any? We’ll do things the Rails Way and put all that stuff in the code where it’s easy. After all, who needs a uniqueness constraint if the code always checks for an existing record before inserting a new one, right? Nothing can go wrong with that can it?
Indexes? Add them after users complain that the site is too slow - even if it was obvious after a moment’s thought that they were always going to be needed. MySQL is so bad at optimizing queries that it might as well be forced to do full table scans it was probably going to do anyway. And besides, it worked just fine with the 5 test records I put in the test fixtures manually.
Performance doesn’t matter, so if the site is too slow, well, at least it was quick to develop. And when the client urgently needs a report that should take five seconds to produce, but because it’s a five-way join and you didn’t add any indexes it times out in Apache’s mod_proxy after the regulation five minutes, well, that’s why you turn your mobile phone off at night and ensure you can never be found online, right? That way you can get a good night’s sleep while the client is tearing out his hair and losing his business.
Foreign keys. You don’t need the database to enforce them if you get the code right. No need to actually take a look at the database from time to time to see whether the invariants your code is supposed to enforce are actually held. So when you later make administrative changes and delete records that other ones refer to, well, ActiveRecord is good about providing a nil that should do nothing, and if not, well, there’s always an exception catcher to tell you your mistake.
Oh, yes, exceptions. The Rails log is full of them, but they’re mostly from Chinese hackers trying to find hidden features, or irrelevant little deadlocks or races that made some user redo their work. No big deal, it only happens occasionally. No need to deploy one of the nice plugins that send you email when you get an exception, of course. That would just mean you’d have to go and find out why it happened, and Rails exists to reduce boring work.
If it works for one user, it’ll work for hundreds, won’t it? Transactions and locks are for banks, not for websites. And two-phase commit, that’s engagement & marriage isn’t it, not something you’d use in a payment protocol? Oh, and I sprinkled a few magic Model.transaction {} blocks around the place, and they must work, because people who should understand such things said they work.
Release management is for wimps. Just use the SVN trunk, and when you check in code, check it out on the test server, let the client look it over, then deploy it to production. No need even to log in to do that, just cap deploy - you can do it without getting out of your pyjamas. All your developers are demigods who never make mistakes anyhow, so if one on one side of the city deploys the other one’s code into production without even Skyping or picking up the phone, there won’t be any unforeseen interactions, will there now?
It was so easy to write, any fool can see it’s correct. TDD is fine for some slow thinkers, and we’re glad Rails makes it easy for them, but seriously, do you expect me to write 100 lines of code to test 50, when I can see perfectly well that there aren’t any errors in it? And besides, if there is an error, it’ll be a one-line fix. Barely even need to finish my latte first, it’ll be fixed in a moment. Not necessarily the moment before it makes the site melt down, but that’s what backups are for, right?
Hmm, backups. That would have been a good idea. That would have helped when, after discovering we hadn’t planned far enough ahead to see the one feature that was going to make all the difference on the big day, we let folk type data directly into the database using an unvalidated, unlogged administration feature. Pity they deleted the entire contents of a critical table… And even then, we might have been able to cobble together a script to reconstruct the transactions that were lost, except that the Rails log only lists the form parameters, not the saved session variables that form the context in which those parameters were relevant.
Discipline? Who needs discipline or forethought when you’re agile?
Comments
There are 19 comments on this post. Post yours →
I really enjoyed your article since, aside from the language and platform differences, I could have written the same thing about Visual Basic. We’ve had this kind of seat-of-your-pants programming in the VB world since 1991 and VB 1.0. At least .NET seems to have raised the bar a little bit.
The thing about an easy-to-use, but powerful, development framework, whether it’s VB, Ruby or something else, is that it can breed this kind of mental laziness. Individual programmers and organizations have to guard against this attitude developing or else they damage their own programming skills and perhaps even the reputation of their chosen development tool.
Great article! Otherwise I agree with Frank C.
Of course, most of the Rails users are hardly professional programmers anyways.
What would they know about proper software architecture?
“Of course, most of the Rails users are hardly professional programmers anyways.”
Mmmm that statement seems pretty tough to deny. After all, you cite solid, well proved statistics of scientific rigour…
Frank, I spent half the 80’s and all the 90’s developing high-productivity development environment products, and I couldn’t get over how utterly perverse our customers were. I mean, these people were running nuclear power stations, top-ten banks, even major US stock exchanges, yet the more we offered simple and straight-forward ways to do things, the harder they tried to find an utterly wrong way to do everything. Sigh. Lead a horse to water…
Anyhow, thanks for the boost. I have a whole article series coming entitled “Out of Vietnam” that I hope you’ll find valuable, so please subscribe (either at feedburner or here) and keep reading!
This is totally wrong. It had nothing specific with rails projects.
You can always have unprofessional and lazy developers and / or management. Developers and managers can be neglecting about their work no meter what programming language, framework or technology they use.
Why should lack of general specification, database design, referential integrity, indexes, unit tests, general testing, performance measurements, exception handling or any other thing you mentioned be specific about Rails but not to Php, ASP, Java or …
For the same reason most the desktop application project will collapse. And to be truthful any kind of project in any domain will collapse if everybody involved do not perform as professionally and competent as they should be.
Beside the bombastic title, emptiness.
Sorry you thought I was complaining about Rails. I wasn’t, the problem is always people, of course. My premise was that some facets of the Rails culture seem to me to engender bad practices. Things like not adding indexes until they’re needed, and not enforcing FKs… these things are definitely part of Rails culture and recommended in the Agile Web Development book. And then there’s still the problem that the Rails log doesn’t usually include enough to reconstruct an event stream… and model.Transaction not reliably doing what transactions should… and… still think there’s no content?
Clifford Comment above:
Sentence #1:
“Sorry you thought I was complaining about Rails. I wasn’t, the problem is always people, of course.”
Sentence #2:
“My premise was that some facets of the Rails culture seem to me to engender bad practices.”
The Rest:
“Rails sucks”
You may want to edit sentence #1 to be more accurate:
“Sorry you thought I was complaining about Rails. I was, the problem is rails, and the people around it.”
I like Rails, but there are valid points in this article. In this community, you often see demos like “watch as I build this blog platform in five minutes.” I just saw such a demo last night at a Rails meetup. I think that’s really the wrong message to send. It encourages laziness and ridiculous expectations, and it’s annoying bragging.
The cool thing about Rails though is that if you use it carefully, and the apply same care and precautions you always have to apply with any technology, it can save you a huge amount of time.
What about enforcement of business logic that is more complicated than fk or unique constraints?
You can do a lot with CHECK constraints and triggers, but the big problem with business rule enforcement is that the same rule needs to be enforced at the UI, logic and data tiers, or in Rails, the browser JS, the controller, the model, and the database - and synchronizing all the enforcement code with the original rule requires great discipline.
Ah, I thought so. Seems like a lot of nasty duplication doesn’t it? :( But I guess that’s the price you pay for a really robust system.
Unless you like, generate code from say, fact based modelling, right? :)
I’ve read somewhere you can write triggers and whatnot in PostgreSQL in Ruby, I wonder what that is like!
Hey, c’mon people! Laziness and unprofessional attitude isn’t Rails specific, but Clifford made a valid point when saying that some parts of Rails culture ends up encouraging some mistakes. For instance: foreign keys, indexes and some checks and defaults are really a good measure, even more when your database will be shared with other applications/services. Some very important people of the Rails world are against this measures and encourages people to be against too. That’s the point, it’s not about Rails itself.
Wow! So much boring bullshit. A more proper title would be “How to ruin a blog post”.
The author’s point is exactly that: some people find these concerns boring, then sites melt down.
I’d definitely had to agree with many of these.
It’s clear, though, that you come from a very DB-centric worldview.
Linking to a tutorial on Foreign Keys in MySQL 5.0, for example, might be a nice touch.
Re: indexes - if there’s a 99% chance you’ll need them, then of course you might as well add them when creating the app. I’ve taken to doing this. The thin line between overoptimizing can be a tricky one though… =)
Most of the rest are, as you said, “people problems” endemic of many teams, not just those using Rails.
All in all, even taking over a poorly written Rails app is still much less painful (to me) than when I used to do the same with PHP, ASP, etc.
(Circa 2003 php/asp/etc - Model View Controller??? HAHAHAHAH good one… ;))
It seems like the majority of rails developers are in the code and fix mentality which is exactly the problem I have with rails: it supports bad behavior.
I remember watching a podcast interviewing the founder of Twitter (which is written in rails). This was a couple weeks after twitter came out, and when asked about the scalability of rails he merely replied, “we have an aggressive caching policy.” I’m sure everyone has heard of the uptime problems with Twitter since the release…
Excellent Article.
I believe it would have been even better if you linked to articles which discussed such things, especially #8 (since it slightly confused me)
You:
“Things like not adding indexes until they’re needed, and not enforcing FKs… these things are definitely part of Rails culture and recommended in the Agile Web Development book.”
Agile Web Development with Rails, 2nd Edition:
“It’s worth noting that this migration doesn’t define any foreign key constraints. The intertable relationships are set up simply because the developer will populate the columns productid and orderid with key values from the products and orders tables. You can also choose to establish these constraints in your migrations (and I personally recommend that you do), but the foreign key support in Rails doesn’t need them.”
“Migrations can (and probably should) define indices for tables.”
Post a comment
Required fields in bold.