The Rails/Django parable

By Richard Crowley

This is a parable about adopting and outgrowing software frameworks, starring Ruby on Rails and Django. I have recited this dozens of times over the years but never took the time to write it down. I’m writing it down in its original form, though I’m certain I could tell it in more timely terms, too.

First impressions matter in software. New users need to feel more capable and powerful than they were without it. New users need to feel like the possibilities are endless. And new users need to get that impression quickly because they’re human beings and are easily distracted. It’s little wonder, then, that companies and communities put a lot of effort into their “hello, world” experience.

In its early days, Ruby on Rails evangelized convention over configuration and the Ruby programming language as “web development that doesn’t hurt.” The official Rails tutorial (circa 2005) included the following code snippet, surely the shortest CRUD web application I’ve ever seen:

class RecipeController < ApplicationController
  scaffold :recipe
end

I remember this demo. My classmate Ray showed it to me in a basement lab in college while we were surely meant to be doing something else. I remember feeling mad at PHP. I remember it so well that I typed every character of that code snippet from memory.

Now, to be completely fair, I should acknowledge that the Rails tutorial always did include more than just those three lines of code. It always was surrounded by important concerns like how to install Ruby and MySQL.

A short time later, Django burst out of Lawrence, Kansas offering “the web framework for perfectionists with deadlines.” It had a lot in common with Ruby on Rails. (It still does.) There was one glaring difference, though (and I’m not talking about it being written in Python): The Django tutorial. Yes, it covered how to install dependencies but it also tutored the reader line by line through creating a toy web application. I did the Django tutorial again in 2022 because I needed just such a toy web application. I ended up with 288 lines of code.

Imagine you had just done both tutorials and needed to change some of the HTML your applications render. The patch against the toy Rails application will remove one line, scaffold :recipe, and add dozens or hundreds more to recreate all that functionality and incorporate your HTML changes. You’d be furious. In contrast, the patch against the toy Django application is likely to remove one line and add one line. Easy peasy.

But this is not a head-to-head comparison of Ruby on Rails and Django. It’s 17 years too late for that. This is a parable.

I began by claiming that first impressions matter in software. I believe second impressions matter, too. Users need to be able to come back and change their software without rewriting it. Users need to be able to maintain their software as environments and requirements change.

Maintainable software exists in a delicate balance between the application and the framework(s) it’s built upon. Frameworks that feature tight coupling and big abstractions result in tiny applications that feel magical and are difficult to change. Frameworks that feature loose coupling and many smaller abstractions result in larger applications that are easier to change. Maintainable software allows you to change one thing without changing another.

The Django tutorial left me with 288 footholds for changing my toy web application. I knew where to add new URL patterns, where to add new data models, where to add fancy custom form fields, and more. These “extra” lines of code made the application maintainable.

Many of those 288 footholds bridged abstractions provided by the framework: Associating URL patterns with views, querying data models from views, rendering HTML forms representing those data models, and so on. These lines made the various abstractions provided by the framework severable, which made the application more maintainable.

All these severable abstractions make it possible for me to maintain my way to outgrowing the framework entirely. Perhaps one day I outgrow simplistic relational data models and change to something that caches or is distributed or whatever but I continue using the same URL patterns, views, and so on. Perhaps another day I give up on HTML and embrace a BFF-style architecture to power my mobile application. Piece by piece, my toy Django application ceases to be a toy and also ceases to be a Django application. It’s mine, maintained into the form best fit for its purpose.

I like frameworks that provide many small abstractions and help me compose them to build my application. I’m happy to have that “extra” code under my control because it gives me plenty of footholds that I can use to change my application. And if those changes eventually amount to outgrowing the framework, then it’s done a great job.

Coda

By 2009, the official Rails tutorial had added a caveat to the section about scaffolding:

While scaffolding will get you up and running quickly, the “one size fits all” code that it generates is unlikely to be a perfect fit for your application. In most cases, you’ll need to customize the generated code. Many experienced Rails developers avoid scaffolding entirely, preferring to write all or most of their source code from scratch.

Today, the official Rails tutorial actually looks remarkably like the Django tutorial. There’s no mention of scaffolding anywhere. In its place, there’s a thoughtful walkthrough of creating a CRUD application (now a blog instead of a recipe organizer). Credit to the Rails team for adopting this style and putting their new users in an ideal position to evolve their applications gracefully.