Last year I briefly flirted with Ruby. I once infamously described Python as "Perl for grown-ups," and if that's true, then Ruby is the hot 20-something firecracker chick of your programming mid-life crisis. You've got nothing in common but damn the interfacing is great. Maturity is getting over it and coming back to the stable reliability and maintainability of Python once more
But if Python is the language of the mature developer, than Django is that stage of midlife where life becomes way too complicated. (Studies indicate that 44 is "the worst year of life" for most people: kids, family, career, finances, professional, social and romantic obligations all pile on hard around this time, leaving most people too little time to think or plan for happiness.)
I've been spending the day trying to port narrator, the program suite that runs my story site, from Ruby to Python. Ought to be easy, right? I decided to make it harder by porting it to Django instead. I have the data models, and they're great for Python. Easy to port. But I had to make it harder on myself, by trying to create containerized subsystems for my stuff: stories belong to authors, but authors might have series, series might have novels as well as stories, but there might be standalone novels, and you might have series so short and standalone that they go in your short story collection with an ident or something. This immediately suggested to me a database trick I know called modified preorder tree traversal, a technique in which allows you to store hierarchical information in a meaningful manner. There's even a pre-build MPTT script for Django unmysteriously named django-mptt.
And that's where I wandered off into the weeds. I tried to understand how the mptt worked and how to incorporate it into the models I was building, and eventually my head started to explode. It involved something called "generics," which are a contributed library for Django's ORM that uses metaprogramming to create one or more model classes with a many-to-many relationships to many objects in many different models. It's very cool. It's very esoteric. It's very hard to understand. The layers between implementation and concrete realization are many and intertwined.
One of the differences between Rails and Django is that Django is "just" a bunch of Python libraries loosely assembled. But Python encourages reading the source; that's the idea, it's supposed to be a readable, self-documenting language. And sure enough, it is, if the problem domain is small enough. It's when you start to layer domain on top of domain, solution on top of solution, that the system become unwieldy. The headaround for some Django applications is beyond the average programmer (and believe me, I am an average programmer). Assaf Arkin encapsulated this idea perfectly in a recent post about object-oriented programming, quoting Travis Jensen:
"My point is that the architectural complexity of these applications inhibit a person’s understanding of the code. … Without actually doing anything, applications are becoming too complex to understand, build, and maintain." Every layer makes perfect sense in isolation. The cracks start showing when you pile them up into a mega-architecture.
This seems to be the problem even with small Django applications. By presenting the four components of Django-- the ORM, the Templating language, the Route/View library, and the Administrative envelope-- as four separate components-- The Django Project has greatly increased the cognitive load on the programmer. Django becomes_ _harder to learn than Rails because of the extra mental effort needed to grasp all the intricacies.
There is a perfect irony here: Django is loosely coupled enough that you can do whatever you want with it and it will probably work. But understanding what crosses that loose coupling is difficult, and when you've got all the layers, plus contribs and plugins going, you need to pull out pencil and paper for even the smallest of efforts. Rails, in contrast, is a hodge-podge of different technologies all thrown together into a pot, but because the average web developer is actively discouraged from being curious about more than what he needs to get the job done, Rails is easier to grasp from the very start.
It's probably worth it. The payoff is a Deep Understanding of the joys of Python metaprogramming. Done right, I'll probably have an even better grasp of the abstractive power of it all. But it's a long, slow slog.