(If you don't care about Zope, you can probably skip this entire
post.)
There was a small bit of controversy in the Zope community a while
back when Nuxeo announced they were
switching from Zope and Python to Java. Nuxeo has been using Zope for
a long time, and has been an active part of that community, so this
was a fairly major defection. Jean-Marc Orliaguet from Nuxeo wrote a
critique of Zope
which is notable because of how familiar he is with Zope from a
technical view, and because as an active member of the community he is somewhat invested in the choices Zope
has made. It doesn't read like a condemnation to me, just a critique,
though I think some people felt otherwise.
I don't know Zope that well, though Plone is core to TOPP and so I've been getting a lot more exposure
to that environment. I've also been at least aware of many of the
techniques they're using, though not how those work in practice
(having not practiced them), so Jean-Marc's critique was very
interesting to me. And it echos some of what I've been thinking.
This is a tricky one. Every project has to deal with this, and many
projects deal with it poorly. Part of Jean-Marc's argument here is
that Java makes it very clear what is public and what is not, and what
is allowed for and what is not, and so at least it makes it very clear
what should be stable and what doesn't need to be stable. I think
this is a valid criticism.
But Zope 3 is actually really good here because of their use of
interfaces. They are pretty clear about what methods are required,
what methods are public. I wish Python had some better conventions
around this in general (mostly in terms of documentation), but
interfaces are pretty decent.
I'm not a fan of adaptation (more about that later), but I'd like to
use interfaces more. I use them here and there, but just in the
abstract as documentation. Unfortunately, documentation tools don't
understand my interfaces. I don't have a way to declare what
interfaces something implements. All sorts of other things. I wish
zope.interfaces was a bit lighter, though maybe it is light
enough. I actually want language-level support, so everyone could
agree on the contentions and build tools around that.
That said, using Five I find the
stream of deprecation warnings over the top.
Here Jean-Marc argues that there's lots of code under the zope
namespace that doesn't belong there. It's not stable enough, or its
APIs aren't stable enough, or its design or architecture is not widely
enough applicable or agreed upon.
I personally don't care much about namespaces. Is zope.formlib
any more "right" than zope_formlib? Is it any more hierarchical?
I don't think so. I have one namespace package, but it's
kind of a historical accident. I wouldn't (and don't) put any more
libraries under that namespace. Each library should stand on its own,
so why create these hierarchies? People read too much into those namespaces,
which is happening right here.
As for standards, I agree this is important. In some way adaptation
(uh, still more on that later) is a way of sidestepping standards. I
think in general Python needs more standard building. Maybe that's
true for Zope too, or maybe those standards should be inclusive of the
wider Python world that includes Zope.
In the abstract, this is about patterns being unnecessarily built into
the environment. Relatedly: this post argues they should be in the
language while
this reaction says the opposite
-- I actually agree with the first post, but in this case agree with
Jean-Marc and the second post. I guess I am inconsistent.
But what Jean-Marc actually talks about is specifically adapters and
the Zope component architecture.
Adaptation is a useful pattern for dealing with API changes. When you
have two isomorphic but
incompatible objects, adaptation works great. This happens when
there's little API differences (e.g., mixedCase vs
underscore_seperated). It starts to become a bit of a stretch at
other times. And Zope 3 goes absolutely nuts with this, implementing
all sorts of other patterns phrased as adaptation. This is complex
and powerful, but in the bad way.
From this, I've seen one-off interfaces that define no methods;
interfaces that are just names; adaptation that works on multiple
objects; adaptation that works on no object at all (adapting the
ether); adaptation in place of attributes... it takes a nice but small
idea and just keeps using it and using it until it's worn out and
confused.
I could go into specifics, but it might not mean much to lots of you,
and I'd probably get the specifics wrong. If it quacks like a duck
it's probably a duck. Lots of uses of adaptation don't quack; I don't
know what they all are, but they aren't ducks.
This is kind about plugins. A lot of the Zope component architecture
is about plugins. It's fairly fine-grained; moreso than I think it
needs to be. It's declarative, but with too many declarations.
I think Setuptools' entry points
solve a number of similar goals, but in a simpler way. There's still
some issues that aren't well solved in either system (actually some of
the exact same issues, like plugin activation), but I think
Setuptools at least doesn't solve those problems in a simpler way.
To correct Jean-Marc: ZCML is XML. Maybe his real problem is that
ZCML is fairly flat (maybe a bit too much like rdf).
It's neither a nice syntax (it is after all XML), nor is it a compact
XML language.
But the Zope people know about this problem already. I don't think
they are entirely sure how to fix it (maybe entry points will help),
but I think everyone agrees it needs fixing.
I guess the larger issue is that it's nice to declare things in Python code,
but that only works if you import the Python code. So if you have something
like an adapter sitting in some code, the system won't know that an adapter
could be available if only it imported that code. An entry point version of this
might be like:
[zope.interface.adapters]
package 1 = mypackage.adapter1
package 2 = mypackage.adapter2
(In this case package 1 doesn't actually mean anything, though maybe some use
for that name could be found)
Zope views are confusing to me. I think I don't like them. I think
this is probably my biggest issue with Zope 3 development.
Zope seems unwilling to commit to being a web application environment.
Everytime I see tutorials or descriptions about development in Zope 3,
it always seems to begin with the model. "View", from what I can
tell, is both "View" and "Controller" (when you are trying to be MVC
about it), i.e., the Python controller and the template view. (This
is just an explanation, I don't care about the terminology.)
While I respect the distinction between view and model, what bothers
me is that the view is an adaptation of the model. I think design should start at the ends, not the means. The model is
just a "means". The "ends" is what the user sees -- the HTML, the
template, the forms, the functionality. That's where application
design should start.
Admittedly, an experienced programmer can bang out a quick model
pretty easily, and will do so quite quickly regardless of what the
underlying architecture dictates. But I'd rather see a sloppy model
that is refined later than a rigid UI built magically by some
framework. I think Zope does a bit too much of the second. Perhaps
because a number of Zope developers don't actually like HTML, and so
want to avoid it through frameworks. I think they just need to get
over it.
- The "pythonic" trip:
Jean-Marc doesn't explain much here. I think he is talking about
getting things done vs. doing things right, and thinks there's
too much doing things right.
- Balkanization:
We're not working enough together. Sure, I think that's true. But
then working together can often get in the way of getting things
done, so it's a hard thing to figure out.
- Self-criticism:
Considering Zope 3 is largely a response to the criticisms of Zope
2, I think it's unfair to say Zope 3 doesn't repond to criticism or
isn't reflective. I think the problem is that Zope 3 doesn't know
what it wants to be. Does it want to be fundamental infrastructure?
I think they are tackling far too much at once if they want to do
that. Do they want to be a web app development platform? I don't
think their architectural choices work that well there; they certainly aren't as expedient or conventional as other frameworks for banging out web apps. Do they
want to be a content management framework? Then people should get
to work on an actual CMS implementation.