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