Howdy everyone --

I think I was the driving force behind rejecting this ticket -- Adrian's still 50/50 as far as I know -- so let me explain why I don't like it.

Actually, before I do, I should say that in the end it's really Adrian's decision in that I'll defer to his judgement should he decide to change his mind. So, don't bother trying to change my mind (unless you want to); if you feel strongly about this, work on changing his.

The first problem I have with the new syntax for models is that it makes it unclear what's a field and what's metadata::

    class Model(meta.Model)
        field1 = meta.CharField(...)
        admin = meta.Admin(...)
        field2 = meta.IntegerField(...)

Did you notice that I snuck an admin declaration in there? Yes, I really "shouldn't do that", but if we allow it people will. Because there's no requirement to keep all the fields together in the model definition, there will be mixing up and that decreases readability which -- for me -- is the primary reason to code in Python.

Second, what if I want a field named "admin"? Yes, there's an alternate syntax for that... but if I wanted alternate syntaxes for the same thing, I'd use Perl. "There should be only one way to do things, and that way should be obvious." Again, I choose to program in Python because I can *read* it better, not because I can *write* it better; when I come back to my models in a year or two I want them to be instantly obvious.

Third, from a semantic point of view it's just wrong.  Consider::

    class RegularOldPythonClass:
        classVar = 14

        def __init__(self):
            self.instanceVar = 77

In the above example, ``classVar`` is, obviously, a class member and ``instanceVar`` is a member of *an instance* of the class. There's an important semantic distinction between instance variables and class variables that I don't think I need to point out to everyone.

Unfortunately, the proposed model syntax subverts this. In the example above, ``field1`` is not a member of the Model class (try it -- ``Model.field1`` will raise an ``AttributeError``); it's a member of an *instance* of the ``Model`` class. So why are we defining it as if it were a class variable? On the other hand, ``fields`` *is* a class variable, so it makes sense to define it at the class level.

Finally, there's the "magic" aspects of dealing with something like::

    class Model(meta.Model):
        field = meta.CharField(...)
        meta.ForeignKey(...)

The "unadorned" ``ForeignKey`` simply doesn't make sense if you don't understand the magic going on underneath, whereas a list of fields makes perfect sense. I'm honestly less concerned with the crazyness of the code than I am with the weird and non-standard syntax. Nowhere else in Python does a non-assignment in a class result in a class member being created.

In Python there's always a tension between clarity and the conciseness you can achieve by doing cool tricks with metaclasses. I'm all for getting rid of as much boilerplate code as possible -- that's why Django exists in the first place -- but not at the expense of clarity. I'd rather be more verbose and more clear than concise and confusing (again, if I wanted concise I'd use Perl).

So that's where I stand, and those are the arguments I gave Adrian when we decided not to change the syntax. Again, I'm pretty sure he's still not convinced either way, and if he decides to accept the patch, I'm not going to complain (although I'll continue to think it's wrong).

Jacob

Reply via email to