Wednesday, November 19, 2008

Uncoupled code is good, but doesn't exist

Code should try to be as decoupled from the code it depends as possible, I want me C++ to work with any compiler, I want my web framework to work with any ORM, I want my ORM to work with any database. While all of these are achievable goals, some of the decoupling people are searching for is simply not possible. At DjangoCon 2008 Mark Ramm made the argument that the Django community was too segregated from the Python community, both in terms of the community itself, and the code, Django for example doesn't take enough advantage of WSGI level middlewear, and has and ORM unto itself. I believe some of these claims to be true, but I ultiamtely thing the level of uncoupling some people want is simply impossible.

One of Django's biggest selling features has always been it's automatically generated admin. The admin requires you to be using Django's models. Some people would like it to be decoupled. To them I ask, how? It's not as if Django's admin has a big if not isinstance(obj, models.Model): raise Exception, it simply expects whatever is passed to it to define the same API as it uses. And this larger conecern, the Django admin is simply an application, it has no hooks within Django itself, it just happens to live in that namespace, the moment any application does Model.objects.all(), it's no longer ORM agnostic, it's already assumed the usage of a Django ORM. However, all this means is that applications themselves are inextricably tied to a given ORM, templating language, and any other module they import, you quite simply can't write resonably code that works just as well with two different modules unless they both define the same API.

Eric Florenzano wrote a great blog post yesterday about how Django could take better advantage of WSGI middleware, and he's absolutely correct. It makes no sense for a Django project to have it's own special middlewear for using Python's profiling modules, when it can be done more generic a level up, all the code is in Python afterall. However, there are also things that you can't abstract out like that, because they require a knowledge of what components you are using, SQLAlchemy has one transation model, Django has another.

The fact that an application is tied to the modules it uses is not an argument against it. A Django application is no tightly coupled to Django's ORM and template system is than a Turbo Gears application that uses SQL Alchemy and Mako, which is to say of course they're tied to it, they import those modules, they use them, and unless the other implements the same API you can't just swap them out. And that's not a bad thing.

4 comments:

  1. I think you're slightly muddling up API and implementation in the above paragraphs. For example, when an application writes mymodel.objects.all(), they're tied to (a portion of) Django's ORM API, not to the implementation. It's quite possible (and has been done) to replace the entire database interfacing layer with something else, providing that they queryset replacement responds to the same API. So RDF or Hadoop or Google App Engine replacements are all possible and not necessarily of interest to the person writing mymodel.objects.all() -- modulo coding to the lowest common denominator of all the options you want to run against. That's why we make such a big deal about public vs internal API and not exposing the former without careful thought about extension possibilities.

    -- Malcolm

    ReplyDelete
  2. Malcolm, that was the idea I was trying to get at, if something has the same API, it will work, regardless of how it's implemented, that's the idea of the Django-SQLAlchemy idea, map call from the Django DB-API to SQLAlchemy.

    ReplyDelete
  3. "Uncoupled code is good, but doesn't exist"

    Yeah right. You should stay in your cave if you dislike
    sunlight that much.

    ReplyDelete
  4. """
    So RDF or Hadoop or Google App Engine replacements are all possible and not necessarily of interest to the person writing mymodel.objects.all() -- modulo coding to the lowest common denominator of all the options you want to run against
    """
    So I had to look up what "modulo" meant in the context above:
    http://en.wikipedia.org/wiki/Modulo_(jargon)

    Ah, jargon, why do you torment me so?

    ReplyDelete

Note: Only a member of this blog may post a comment.