Coupling Django Style

I wrote the first draft of this a long time ago, and I skipped it because tempers seemed high in some places. It seems like things have calmed down, and I think the points are still 100% relevant.

For those reading this remember, I’ve used Django to build things like and I have done enough Django surgery to know what I’m talking about.

Django Developers have said, over and over again:

Django is tightly integrated and loosely coupled.

On the face of it, this statement is paradoxical (more techncally, it sounds like an antinomy to me) coupling and integration are generally seen as ends on a spectrum. Perhaps the Django catchphrase is more than just marketing speak, and actually means something.

If so perhaps they are thinking that they are more loosely coupled than some, and more tightly integrated than others. I suppose you could put opinionated frameworks like Ruby on Rails on one end, and free-form frameworks like Pylons on the other, and Django sits somewhere in between.

But even that seems an oversimplification, Rails is a huge community and Rails users have lots of options, there are alternative template engines galore, and many other components have plugins which replace or seriously modify their behavior.

Lest you think I’m manufacturing this from the air, here’s a quote from a django proponent discussing the idea of loose coupling in Django:

Developers coming from Ruby on Rails or other extremely opinionated frameworks may be used to following their framework’s best practices to avoid fighting against a framework which feels that it knows your project better than you do, but with Django you’ll be back in the driver’s seat.

– Will Larson on “loose coupling” in django

I think this is only true, if it’s true, by degree. It’s easier to do radical surgery to the framework in Django than it is in Struts, though I’m not all that convinced that Rails is harder to change than Django. But really, that’s beside the point. The fact of the matter is that framework surgery is much harder to do in Django than Pylons, and I think that’s not a wild claim, but a verifiable fact.

I wouldn’t recommend decoupling from the Django ORM without an extremely compelling reason. It is the most coupled of all the subparts of Django, and certainly not trivial to replace.

Will Larson on using SQLAlchemy with Django (emphasis added)

Using SQLAlchemy in Django is not really hard (but at the same time it’s not all that easy either). But, it’s the kind of thing you wouldn’t want to do unless you really had a good reason.

Why? Because there are an awful lot of Django components that are “tightly integrated” with the django ORM.

But before everybody gets too mad at me, let me turn it around, and say that I think:

  • it is not a bad thing to value integration above coupling.

Another Quote from Will’s blog, shows that he’s aware that loose coupling isn’t the single core value of Django:

Django places value on loose coupling, but it isn’t the sole design principle either.

– Will Larson (in a comment here)

I would say that even more strongly:

Django should not place loose coupling above developer productivity.

Adrian made a good point after my talk by suggesting that developers need to get things done, and to make sites that work now — not create software that is perfect by some abstract standard of design.

And I do think that some of the helpers that depend on the Django ORM are significant productivity wins. And, removing the django ORM dependency in all of them would be both very hard, and totally not worth it.

“Tightly Integrated” has value, and sometimes that value trumps “Loosely Coupled.” Zope is pretty tightly integrated into the ZODB. Many TurboGears 2 plugins are going to be pretty tightly integrated into SQLALchemy. Others will not, and I have encouraged some folks to rewrite their TG2 plugins to make them into pure WSGI apps that don’t depend on TG2 at all. Determining what exactly you will depend on, and how tightly you will be coupled to that dependency requires thought, and ultimately has consequences.

I’m hard on the Django folks here because I think the “tightly integrated/loosely coupled” buzz phrase is actually detrimental to understanding how the trade-off’s work.

And there are trade-offs and those trade-offs mean that there isn’t and will never be one perfect web-framework which somehow magically isn’t subject to the down-side of any of the constraints and design trade-offs that we all have to deal with every day.

Which brings me to the other major point I tried to make in my talk about django. Encapsulation, orthogality, or loose coupling is to some extent enforced by package boundaries. It’s not so much that you can’t be tightly coupled to the internals of an outside package, but that it feels wrong. And it feels wrong because when you start making libraries you start defining public interfaces, and making decisions about what’s internal and what’s external. And that makes monkeying with the internals feel icky. But if everything is all in one package, it’s a lot easier and less ‘icky” feeling to just grab some internal bit and do what you need to, since less thought has been given to what’s public and what’s private.

2 Responses to “Coupling Django Style”

  1. Hi Mark,

    Nice write up, although I cringed reading my first sentence you quoted, remembering what my writing looks like when I lack the foresight to edit.

    Coupling/integration can be difficult to discuss, as it hinges pretty heavily on definition. Identically to your example about turbogears 2 plugins relying on SQLAlchemy, the vast majority of Django applications rely on the Django ORM. It is trivial to use Django without the Django ORM, if and only if you’re willing to sacrifice using those Django applications.

    I’ve done projects with Django and CouchDB, where the ORM is entirely unused. For these projects I wasn’t able to use some apps (unless I wanted to run both CouchDB and postgres), but the Django core didn’t raise any complaints.

    More concisely, I’d suggest that the core is loosely coupled, but the application ecosystem is tightly coupled. But now I’m starting to draw a possibly artificial distinction between the core and the ecosystem.

  2. If you want truly loose coupling and replaceable components, don’t use Django. Use Werkzeug or something. You are completely right that there are costs and benefits on both sides.

    However, I think something is missing from the discussion: You don’t have to go all or nothing with any of the components you choose to use.

    We use SQLAlchemy, Django’s ORM, and an in house CouchDB library at WWU Housing. We can still use django pluggable applications, we have the power of SQLAlchemy for mapping objects to the atrocious tables in Banner, and we have the flexibility of a schema free document database with CouchDB. Why should we limit ourselves to one?

    Its ridiculous; use the tool for the job.

Comments are currently closed.