Chris McDonough wrote: > Tres Seaver wrote: [snip] >> The root of the disagreement here is that you seem to want the *caller* >> to care about something which is important only to the person who >> *registers* the thing being looked up. From the caller's perspective, >> the call site needs an object implementing IFoo, looked up using some >> number N of context arguments, where N could be 0 (no context required >> to find the object). The fact that, under the hood, an adapter lookup >> happens to call a factory, passing the context args, is not relevant *to >> the caller*. > > I understand that the idea explained above is conceptually integral to a lot > of > people, and basically unquestionable. But as devil's advocate sort of thing > can we put this traditional worldview aside for a minute, and just sort of > take this from ground zero? > > In "normal Python", callers often do need to understand whether the function > they're calling is a factory which constructs a new object, or a function > which > returns a "global", because the caller needs to know what the impact of > mutating the result is.
I think this more often has to do with knowing whether an object should be treated as if it's immutable or not. Often you construct objects and when they're done you only consult them and don't manipulate them anymore. The "traditional world view" works best for objects treated as immutable - you can apply the flyweight pattern (caching) more easily for instance. > We call non-factories utilities and we call factories adapters. So the > caller > *already* needs to make a distinction between the two. That's a good point. Let me generalize a bit here below. Adaptation in ZCA is a combination of Design Pattern's abstract factory pattern and the adapter pattern. A utility is something you get back by calling a similar abstract function, but you get back an instance that was already registered previously. Marius and Gary discussed introducing more symmetry. Here is the symmetrical picture as I see it: * abstract factory called on an object (adaptation) In: one ore more instances providing some interfaces, the requested interface Out: a new instance created by a factory that provides the requested interface * abstract instance retrieval (utility lookup) In: the requested interface Out: a previously registered instance that provides the requested interface. * abstract factory not called on an object ("utility factory", "null-adaptation") In: the requested interface Out: a new instance created by a factory that provides the requested interface * abstract instance retrieval for an object ("utility associated with an instance", "adapting to an existing instance") In: one or more instances providing some interfaces, the requested interface Out: a previously registered instance for that object that provides the requested interface There is also the issue of connections: * an adapter typically has a connection to the adapted object. It's not required, however. This is possible because it gets instantiated with the adapted objects as arguments. * a utility never has a connection. That's because it already got instantiated long before the lookup takes place. Whether you see the existence of a connection as essential probably influences whether you prefer the term "adapter" or "utility" in the two latter cases. Here I've looked at the inside of adapters and utilities, and I've also looked at how these things get created. Now back to the "traditional perspective", which I think while not incontrovertible is still extremely valuable. I like the pattern where the caller shouldn't need to know *how* the returned object is created. This suggests unifying utility and adapter lookup. So: IFoo.instance() IFoo.instance(a) IFoo.instance(a, b) "Give me an instance of IFoo (given these objects)". Underneath it could go instantiate IFoo right then and there, possibly passing the arguments to the factory, or it could retrieve an existing IFoo from some registry somewhere. In design patterns terms, a factory could *always* be called. It's just that sometimes it turns around and returns a previously registered instance. (if we are going for a method on an interface, it's clear that "instance" is better than "new", as new implies a new instance while "instance" doesn't imply this. Given it's just one method I'd still be inclined to just call the interface directly) Regards, Martijn _______________________________________________ Zope-Dev maillist - Zope-Dev@zope.org https://mail.zope.org/mailman/listinfo/zope-dev ** No cross posts or HTML encoding! ** (Related lists - https://mail.zope.org/mailman/listinfo/zope-announce https://mail.zope.org/mailman/listinfo/zope )