Re: [Zope-dev] summary of discussion was: adapter vs factory Re: implementing zope.component 4.0
Martijn Faassen wrote: > Chris McDonough wrote: >> Personally I think that it's a fantasy to believe that the difference >> between >> an object created via a factory on-demand and an object simply returned >> should >> *never* matter to a caller. You may not want the caller to need to care, >> and >> it may be inconvenient to take into account circumstances where the caller >> needs to care. But because this is Python, the caller still often does need >> to >> care. > >> The only circumstance where a caller would *never* need to care would be >> when >> the object returned could be guaranteed to *never ever* have any methods >> called >> on it that weren't part of the interface defined by the interface being >> looked >> up. If we want this, we should probably just be using Java. > > I think it's okay for us to say: if you call a method on something that > you retrieved by interface that isn't actually specified to be on that > interface, you're on your own. It may work, but it's not specified to > work by the system you're using. Let's use an analogy here. You are a member of a club. This club is very inclusive, but it has a fairly rigid set of protocols that members are expected to follow. For example, when you enter the front door, you are expected to touch a statue next the the door. When a bell rings, you are expected to sing the club song. At precisely 1pm, everyone must kneel in place. A number of other arbitrary actions are required of a new member, and new ones are added every so often. This club is slightly superstitious, so it is believed that *not* performing the required actions is bad luck, and any member who does not perform them "to the letter" will bring a pox upon the club and all its other members. In fact, the club members have incontrovertable evidence that this is so. The club currently has a membership in the hundreds. They want to be inclusive, so they welcome anybody, and they're glad to get new members. But those who come in are expected to read a slightly tattered printout of a PowerPoint presentation hanging from a string on the inside of the front door. This printout contains all the known actions that a member must perform in response to cues to be a member in good standing. New members can also ask existing members for help, of course, and they can go visit the printout any time. If everyone follows the set of instructions in the powerpoint document to the letter, everything runs swimmingly. But the powerpoint document is missing some pages, (some new cues were added recently) and even if it wasn't, new members would almost always have a hard time getting it *all* right on the first try because there are a lot of cues these days. The bell rings, they kneel. They sing the song at the wrong time. Sometimes they just don't know what to do, so they do nothing. The club also has a wait staff. Currently the wait staff is not expected to enforce any of the rules; they simply keep things running. They are severely underworked at the moment. Currently the club interpersonals are a little broken: when a new member has the wrong response to a cue, the existing club members might try to help that new member, but often they just complain to each other about the offending new member. Some members just claim "I've already paid my dues to be a member here, he should too." Other members try to write more little sticky notes and hang them up as cues to new members, but nobody is really "responsible" for teaching new members the rules. It's sink or swim, and often new members sink. If the the "club" is the "ZCA community", the "cues" are the worldview that says that the ZCA is by god a way to convert one interface to another and that utility and adapter lookups are no different than each other, the wait staff is the ZCA itself, new members are new developers, and the mistakes they make when not following the cues using methods of the adapted objects that aren't defined by the adapter interface: 1) Put the wait staff in charge of helping new members. This is analogous to making the ZCA throw (or at least warn) about errors that new developers make by using attributes and methods of an object not defined by the interface returned by an adapter or utility lookup. 2) Get rid of most of the cues. This is analogous to "unifying" adapter lookup and utility lookup by making the *caller* responsible for doing "adaptation" by calling the result of the lookup himself. Or do nothing. Doing nothing is wrong because at some point *we* become maintainers of code written by folks that "didn't get the jokes" of the ZCA worldview. So we can either take the joke out or make the joke impossible to miss. > I'm not sure why lifetime issues are considered so important here. Of > course they sometimes matter. But we use ORMs all the time. We create > traversal hierarchies on the fly all the time. Wha
Re: [Zope-dev] summary of discussion was: adapter vs factory Re: implementing zope.component 4.0
-BEGIN PGP SIGNED MESSAGE- Hash: SHA1 Martijn Faassen wrote: > Hi there, > > I'd like to summarize the options I've seen appear in the discussion so far. > > We have the following options: > > 1) introduce a new method, such as "instance()" or "lookup()" on > instance. It unifies utilities with adapters. We can make it do whatever > we want without worrying about backwards compatibility. > > 2) introduce several new methods that distinguish between utility and > adapter lookup. We can make them do whatever we want without worrying > about backwards compatibility. > > 3) call the interface, which unifies adapter and utility lookups. Use > tuples for multi adaptation. We think could make this work without *too* > much backwards compatibility issues (pending research on how prevalent > tuple adaptation really is). In the long term we can even map out a > deprecation strategy that can smoothly migrate us to a "multi argument" > approach. > > 4) call the interface, which unifies adapter and utility lookups. Use > multiple arguments for multi adaptation. The backwards compatibility > obstacles are largest here as we already have the "default" argument. > We'd need to introduce multiple "modes" to selectively upgrade. > > I'm in favor of calling the interface. I'm also in favor of unifying > adapter and utility lookup. +1 to both. I think #3 is the best overall compromise, perhaps eventually migrating to #4 after all use of positional default has faded away. Making tuple adapter lookup use the non-sugar spelling seems a pretty low cost. > On the back end, I'm also in favor of allowing utility creation by > factory (or "null adaptation") and allowing instance lookup for > instances ("contextual utility lookup" or "adaptation to an instance"). > I think four ways to retrieve an object of the right interface > (combining factory/registered instance and lookup globally/lookup for an > instance) is a good argument *against* distinguishing between creation > strategies or "connection to adapted object or not" in the API. One easy way to handle this seamlessly is to check the registered object: if it implements (rather than provides) the interface, then call it, otherwise just return it. Folks who use factories which don't declare what they implement would need to adjust if we adopt this approach. Tres. - -- === Tres Seaver +1 540-429-0999 tsea...@palladion.com Palladion Software "Excellence by Design"http://palladion.com -BEGIN PGP SIGNATURE- Version: GnuPG v1.4.9 (GNU/Linux) Comment: Using GnuPG with Mozilla - http://enigmail.mozdev.org iEYEARECAAYFAksVSGwACgkQ+gerLs4ltQ53awCff+U4Pf836NucmWnLCCrvrwul kC0An3UG6NT51numMPPh78DCqSK9HrJy =tq4A -END PGP SIGNATURE- ___ 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 )
Re: [Zope-dev] summary of discussion was: adapter vs factory Re: implementing zope.component 4.0
Gary Poster wrote: > You are leaving out the variants of 3 and 4 that allow calling the > interface to support multiadaptation, but do not unify utilities. True, my mistake. Lennart pointed that out too just now. > My impression is that I am not the only one who is not pleased with > the proposed unification of utilities and adaptation. I've tried to analyze why that might be so elsewhere. There are three perspectives that I can see: * everything registered is really a factory. Returning a utility just requires registering a special factory. * everything registered is really an instance. Calling an adapter is just looking up an instance and then calling it. * we have two kinds of things registered, instances and factories. zope.component does that today. > My impression is that we are nearing consensus on the variation of 3 > that does not include utilities. I could live with that, as long as we had a way to look up utilities on the interface too. 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 )
Re: [Zope-dev] summary of discussion was: adapter vs factory Re: implementing zope.component 4.0
On Tue, Dec 1, 2009 at 16:28, Martijn Faassen wrote: > * abstract factory not called on an object ("utility factory", > "null-adaptation") > > In: the requested interface > > Process: look up factory. Call factory. > > Out: a new instance that provides the requested interface When would you need this? As I understand it, the only difference from the normal utility lookup is that you don't get singletons. IMO that breaks the concept of what a utility is, so null-adaption is a better name for that, but that still means you adapt nothing, so it's not an adapter either. :-) > * abstract instance retrieval for an object ("utility associated with an > instance", "adapting to an existing instance") > > In: the requested interface, one or more instances. > > Process: look up instance with input instances as "context". > > Out: a previously registered instance that provides > the requested interface Hmm. Singleton adapters, in other words. I can see that as useful, sure. -- Lennart Regebro: Python, Zope, Plone, Grok http://regebro.wordpress.com/ +33 661 58 14 64 ___ 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 )
Re: [Zope-dev] summary of discussion was: adapter vs factory Re: implementing zope.component 4.0
Am 01.12.2009, 17:08 Uhr, schrieb Lennart Regebro : > I'm +1 for 5. "wot he said" x 10 :-) The video + audio to scart example struck me last night and providing expressive(?) examples of this to match so that one is less easily caught by tuples as arguments is a doddle. cables = (audio, video) connector = IScart.adapt(cables, "HDTV") Assuming I haven't got totally the wrong end of the stick this shouldn't confuse anyone. Now, do we have any similar simple but expressive analogy for utilities? Soap dispensers? ISoapDispenser.utility().dispense() # agained, spelled out for clarity seeing as that's all the utility does. I hope my analogies aren't too far off the mark. Helps me a lot not to think about what's really going on. Charlie -- Charlie Clark Managing Director Clark Consulting & Research German Office Helmholtzstr. 20 Düsseldorf D- 40215 Tel: +49-211-600-3657 Mobile: +49-178-782-6226 ___ 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 )
Re: [Zope-dev] summary of discussion was: adapter vs factory Re: implementing zope.component 4.0
Hey, Chris McDonough wrote: [snip] > If you want to create a world where callers never need to care about the > lifetime of any object returned by a component lookup, you could also return > a > proxy wrapper around the returned object that only allows for the invocation > of > the methods defined in the interface looked up. Any other access or > invocation > would raise an exception. > > This would make this worldview 100% consistent, completely documentable, and > would cause no confusion during use. It would thus remove any logical > argument > I have against it. I wouldn't be eager to use such a system, but it's > totally > consistent. In the Python world interfaces aren't enforced on the language level. But we all know that the programmer better beware and follow the implicit API anyway. With zope.interface, we have a tool to make that implicit interface explicit. Static type advocates argue that if you actually shouldn't cheat anyway, you should have the language help you in verifying that what you're doing is correct. Dynamic type advocates argue that the developer overhead of typical statically typed languages is so big that we'd rather have a bit more danger. And sometimes being able to cheat and get away with it is darn convenient. We happen to be using a dynamically typed language. I don't understand why this particular situation is so unique that this would require a proxy that raises exceptions. If you follow that reasoning, you could just as well say the only sane way to use methods in Python is to require proxies that raise exceptions around method arguments if the input doesn't provide the right interface. 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 )
Re: [Zope-dev] summary of discussion was: adapter vs factory Re: implementing zope.component 4.0
Chris McDonough wrote: > I am more or less somewhere between -0 and +0 That is a high degree of precision. Maybe we need to start thinking of our voting system as a Decimal instead of an int? Martin -- Author of `Professional Plone Development`, a book for developers who want to work with Plone. See http://martinaspeli.net/plone-book ___ 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 )
Re: [Zope-dev] summary of discussion was: adapter vs factory Re: implementing zope.component 4.0
Chris McDonough wrote: > Personally I think that it's a fantasy to believe that the difference between > an object created via a factory on-demand and an object simply returned > should > *never* matter to a caller. You may not want the caller to need to care, and > it may be inconvenient to take into account circumstances where the caller > needs to care. But because this is Python, the caller still often does need > to > care. > The only circumstance where a caller would *never* need to care would be when > the object returned could be guaranteed to *never ever* have any methods > called > on it that weren't part of the interface defined by the interface being > looked > up. If we want this, we should probably just be using Java. I think it's okay for us to say: if you call a method on something that you retrieved by interface that isn't actually specified to be on that interface, you're on your own. It may work, but it's not specified to work by the system you're using. I'm not sure why lifetime issues are considered so important here. Of course they sometimes matter. But we use ORMs all the time. We create traversal hierarchies on the fly all the time. What's different in this case? If I want to index an object, do I care whether the catalog was just created on the fly and it's talking to a relational database? I think you're arguing that because abstractions are sometimes leaky (lifetime issues) we shouldn't have this abstraction at all. Why is the leakiness so important here? [snip] > The current global API has a modicum "kindness" for maintenance > developers because we *haven't* unified adapter and utility lookup in > such a way. They stand a shot at understanding that the result of > getUtility usually has "lifetime A" and the result of > getAdapter/getMultiAdapter has "lifetime B". If we take out this > safety belt, I'd lean towards more explicitness rather than less: let > the caller call the result of the lookup. I think there are two centers of attraction for unification: * everything is a factory. If I want to look up an instance, I look up a factory that returns me the same instance all the time. I.e. IFoo() and IFoo(a) * everything is an instance. If I want to call a factory, I look up an instance that is a factory, and call it. I.e. IFoo.lookup() and IFoo.lookup(a)(a) zope.component presents a compromise between those positions. The advantage I see of unifying towards factories is a less verbose API for common operations than an explicit API would have. If you take the utilities come from a factory approach, this would suggest an API like this (on Interface): def __call__(self, arg=()): if not isinstance(arg, tuple): arg = (arg,) return self.factory(arg)(*arg) # low level def factory(self, arg=()): return registry.lookup(from_=arg, to=self) The drawback is that while you *can* register utilities as non-factories and look them up, you'd do it through 'factory', as the real way to look up utilities would be to call a factory. If you take the utilities are registered instances, that would suggest an API like this: # convenience def __call__(self, arg=()): if not isinstance(arg, tuple): arg = (arg,) return self.lookup(arg)(*arg) def lookup(self, arg=()): return registry.lookup(from_=arg, to=self) You'd register utilities as instances directly and look them up using lookup(). The convenience method still works for adapters. The drawback is that IFoo() would result in IFoo.lookup()(), and calling the utility would make no sense. The implementations are the same, but the semantics are quite different. :) 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 )
Re: [Zope-dev] summary of discussion was: adapter vs factory Re: implementing zope.component 4.0
Martijn Faassen wrote: > First a statement about the goal of this discussion. The goal of this > discussion is to convince people to unify the lookup API. I wouldn't > want to make lookup API improvements depend on improvements to > zope.component inspired by the discussion below. I'm in favor of > exploring that in a separate project, however. +1 > * abstract factory called on an object (adaptation) > > In: the requested interface, one ore more instances > > Process: look up factory. Call factory with input instances. > > Out: a new instance that provides requested interface > > * abstract instance retrieval (utility lookup) > > In: the requested interface > > Process: look up instance. > > Out: a previously registered instance that provides requested interface. > > * abstract factory not called on an object ("utility factory", > "null-adaptation") > > In: the requested interface > > Process: look up factory. Call factory. > > Out: a new instance that provides the requested interface > > * abstract instance retrieval for an object ("utility associated with an > instance", "adapting to an existing instance") > > In: the requested interface, one or more instances. > > Process: look up instance with input instances as "context". > > Out: a previously registered instance that provides > the requested interface > > The two latter patterns aren't fully supported. All of them could in > principle be emulated using the "look up factory/call factory" pattern. I think the last pattern can be implemented with a custom adapter factory. You'll need custom "retrieval" code anyway, so there's probably not much more room for abstraction. > There are two perspectives on distinguishing adapters from utilities. > One perspective is: > > * newly created instance (adapter) versus previously registered instance > (utility). > > This perspective informs the "singleton" discussion. I'd say a better > way to distinguish adapters from utilities (should we wish to do so) is: > > * arguments into the factory (adapter) versus no arguments into the > factory (utility) > > That's inspired by the notion that adapters tend to have some form of > abstract "connection" to what they adapt, while utilities do not. This is certainly true, but does that really inform how we use these things? To me, I use unnamed utilities for: * singletons (as in, one implementation) * strategies (as in, I look up some configuration for an algorithm by asking the CA for an object providing a particular interface) I use named utilities for: * registries of homogeneous objects (to avoid implementing my own registry) I use adapters for: * the adapter pattern (my code expects an IFoo; the client code can write an adapter factory to get me one from whatever context it passes in) * customisation/specialisation (I look up an adapter to fulfil some policy, allowing it to be overridden with more specific adapters) And a few other variations (such as the "retrieve object" use case, but that's very rare and has largely been an implementation detail). I don't think of these in terms of "how many arguments" the component needs. I think of them in terms of various software patterns. And to me, an adapter provides the ability to work with different "aspects" of an object (adapting it to different interfaces) whilst utilities provides a way to get the "current" implementation of a particular service or policy. I'm very much for consistent APIs, and if we can simplify the registry implementation with more shared code, that'd be great. I'm just really worried that we try to "simplify" by replacing two concepts we've spent ages teaching people, with a single concept that is even more abstract and used in even more different ways for even more purposes. You start having to use lots of words to disambiguate ("named multi argument factory component" == a view). I don't think we win there. Martin -- Author of `Professional Plone Development`, a book for developers who want to work with Plone. See http://martinaspeli.net/plone-book ___ 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 )
Re: [Zope-dev] summary of discussion was: adapter vs factory Re: implementing zope.component 4.0
On Dec 1, 2009, at 8:21 AM, Martijn Faassen wrote: > Hi there, > > I'd like to summarize the options I've seen appear in the discussion so far. > > We have the following options: > > 1) introduce a new method, such as "instance()" or "lookup()" on > instance. It unifies utilities with adapters. We can make it do whatever > we want without worrying about backwards compatibility. > > 2) introduce several new methods that distinguish between utility and > adapter lookup. We can make them do whatever we want without worrying > about backwards compatibility. > > 3) call the interface, which unifies adapter and utility lookups. Use > tuples for multi adaptation. We think could make this work without *too* > much backwards compatibility issues (pending research on how prevalent > tuple adaptation really is). In the long term we can even map out a > deprecation strategy that can smoothly migrate us to a "multi argument" > approach. > > 4) call the interface, which unifies adapter and utility lookups. Use > multiple arguments for multi adaptation. The backwards compatibility > obstacles are largest here as we already have the "default" argument. > We'd need to introduce multiple "modes" to selectively upgrade. You are leaving out the variants of 3 and 4 that allow calling the interface to support multiadaptation, but do not unify utilities. My impression is that I am not the only one who is not pleased with the proposed unification of utilities and adaptation. My impression is that we are nearing consensus on the variation of 3 that does not include utilities. Gary ___ 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 )
Re: [Zope-dev] summary of discussion was: adapter vs factory Re: implementing zope.component 4.0
On Tue, Dec 1, 2009 at 14:21, Martijn Faassen wrote: > Hi there, > > I'd like to summarize the options I've seen appear in the discussion so far. > > We have the following options: > > 1) introduce a new method, such as "instance()" or "lookup()" on > instance. It unifies utilities with adapters. We can make it do whatever > we want without worrying about backwards compatibility. > > 2) introduce several new methods that distinguish between utility and > adapter lookup. We can make them do whatever we want without worrying > about backwards compatibility. > > 3) call the interface, which unifies adapter and utility lookups. Use > tuples for multi adaptation. We think could make this work without *too* > much backwards compatibility issues (pending research on how prevalent > tuple adaptation really is). In the long term we can even map out a > deprecation strategy that can smoothly migrate us to a "multi argument" > approach. > > 4) call the interface, which unifies adapter and utility lookups. Use > multiple arguments for multi adaptation. The backwards compatibility > obstacles are largest here as we already have the "default" argument. > We'd need to introduce multiple "modes" to selectively upgrade. You missed: 5) Call the interface for adaption, and something else for utility lookup, with tuples for multi-adaptation. 6) Call the interface for adaption, and something else for utility lookup, with multiple arguments for multi-adaptation. 7) Do nothing. ;) I'm minus lots for any unification of adapters and utilities. Since a utility does not adapt anything, and adapters do, all they have in common is that they implement an interface. Since in some sense, all objects implement an interface, we have reinvented the object. That's going to confuse the heck out of everyone. It's a very bad idea. If tuple adaption is common, which I doubt, I'm +1 for 2. If tuple adaption is uncommon, I'm +1 for 5. I'm also: -0 for 6 -1 for 7 -lots for the rest > If I look up a utility I wouldn't want to care whether it happened to be > a previously registered instance or a factory created one. If I look up > an adapter I wouldn't care whether it happened to be a previously > registered instance either. In fact, returning a previously registered > instance can be very well implemented using a factory. (In fact, this > suggests to me we should actually explore implementing instance > registration in terms of special factories.) Making it less common to have to keep track on when you need factories and not would be a definite benefit. -- Lennart Regebro: Python, Zope, Plone, Grok http://regebro.wordpress.com/ +33 661 58 14 64 ___ 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 )
Re: [Zope-dev] summary of discussion was: adapter vs factory Re: implementing zope.component 4.0
Chris McDonough wrote: > On the semantics of the change: > > Personally I think that it's a fantasy to believe that the difference between > an object created via a factory on-demand and an object simply returned > should > *never* matter to a caller. You may not want the caller to need to care, and > it may be inconvenient to take into account circumstances where the caller > needs to care. But because this is Python, the caller still often does need > to > care. > > The only circumstance where a caller would *never* need to care would be when > the object returned could be guaranteed to *never ever* have any methods > called > on it that weren't part of the interface defined by the interface being > looked > up. If we want this, we should probably just be using Java. I'll retract this. If you want to create a world where callers never need to care about the lifetime of any object returned by a component lookup, you could also return a proxy wrapper around the returned object that only allows for the invocation of the methods defined in the interface looked up. Any other access or invocation would raise an exception. This would make this worldview 100% consistent, completely documentable, and would cause no confusion during use. It would thus remove any logical argument I have against it. I wouldn't be eager to use such a system, but it's totally consistent. - C ___ 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 )
Re: [Zope-dev] summary of discussion was: adapter vs factory Re: implementing zope.component 4.0
Martin Aspeli wrote: > Can you summarise what you mean by this? The thread is so long... [snip] > My brain hurts... examples? [snip] > I'm afraid you've lost me. Four ways sounds bad, though. ;-) I've edited down and clarified what I posted earlier. First a statement about the goal of this discussion. The goal of this discussion is to convince people to unify the lookup API. I wouldn't want to make lookup API improvements depend on improvements to zope.component inspired by the discussion below. I'm in favor of exploring that in a separate project, however. * abstract factory called on an object (adaptation) In: the requested interface, one ore more instances Process: look up factory. Call factory with input instances. Out: a new instance that provides requested interface * abstract instance retrieval (utility lookup) In: the requested interface Process: look up instance. Out: a previously registered instance that provides requested interface. * abstract factory not called on an object ("utility factory", "null-adaptation") In: the requested interface Process: look up factory. Call factory. Out: a new instance that provides the requested interface * abstract instance retrieval for an object ("utility associated with an instance", "adapting to an existing instance") In: the requested interface, one or more instances. Process: look up instance with input instances as "context". Out: a previously registered instance that provides the requested interface The two latter patterns aren't fully supported. All of them could in principle be emulated using the "look up factory/call factory" pattern. There are two perspectives on distinguishing adapters from utilities. One perspective is: * newly created instance (adapter) versus previously registered instance (utility). This perspective informs the "singleton" discussion. I'd say a better way to distinguish adapters from utilities (should we wish to do so) is: * arguments into the factory (adapter) versus no arguments into the factory (utility) That's inspired by the notion that adapters tend to have some form of abstract "connection" to what they adapt, while utilities do not. 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 )
Re: [Zope-dev] summary of discussion was: adapter vs factory Re: implementing zope.component 4.0
On Dec 1, 2009, at 9:54 AM, Chris McDonough wrote: > Martijn Faassen wrote: >> ... > I am also in favor of unifying adapter and utility lookup. Or at least > creating a more normalized API. I guess it is no surprise that I am in favor of a normalized API but against the unification. > On the syntax of the change: [...] I followed vaguely. This was about unification, correct? > On the semantics of the change: > > Personally I think that it's a fantasy to believe that the difference between > an object created via a factory on-demand and an object simply returned > should > *never* matter to a caller. You may not want the caller to need to care, and > it may be inconvenient to take into account circumstances where the caller > needs to care. But because this is Python, the caller still often does need > to > care. Again, no surprise that I agree with this and following. Gary ___ 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 )
Re: [Zope-dev] summary of discussion was: adapter vs factory Re: implementing zope.component 4.0
Martijn Faassen wrote: > Hi there, > > I'd like to summarize the options I've seen appear in the discussion so far. > > We have the following options: > > 1) introduce a new method, such as "instance()" or "lookup()" on > instance. It unifies utilities with adapters. We can make it do whatever > we want without worrying about backwards compatibility. > > 2) introduce several new methods that distinguish between utility and > adapter lookup. We can make them do whatever we want without worrying > about backwards compatibility. > > 3) call the interface, which unifies adapter and utility lookups. Use > tuples for multi adaptation. We think could make this work without *too* > much backwards compatibility issues (pending research on how prevalent > tuple adaptation really is). In the long term we can even map out a > deprecation strategy that can smoothly migrate us to a "multi argument" > approach. > > 4) call the interface, which unifies adapter and utility lookups. Use > multiple arguments for multi adaptation. The backwards compatibility > obstacles are largest here as we already have the "default" argument. > We'd need to introduce multiple "modes" to selectively upgrade. > > I'm in favor of calling the interface. I'm also in favor of unifying > adapter and utility lookup. > > On the back end, I'm also in favor of allowing utility creation by > factory (or "null adaptation") and allowing instance lookup for > instances ("contextual utility lookup" or "adaptation to an instance"). > I think four ways to retrieve an object of the right interface > (combining factory/registered instance and lookup globally/lookup for an > instance) is a good argument *against* distinguishing between creation > strategies or "connection to adapted object or not" in the API. > > If I look up a utility I wouldn't want to care whether it happened to be > a previously registered instance or a factory created one. If I look up > an adapter I wouldn't care whether it happened to be a previously > registered instance either. In fact, returning a previously registered > instance can be very well implemented using a factory. (In fact, this > suggests to me we should actually explore implementing instance > registration in terms of special factories.) I am also in favor of unifying adapter and utility lookup. Or at least creating a more normalized API. On the syntax of the change: I am more or less somewhere between -0 and +0 on the idea of presenting a unified API as methods of interfaces (call or non-call). While I don't think this idea is the worst idea in the world and it might be better than the current global API, I don't think we should *only* do this; similar changes should be made to the registry itself. Code that uses the global API needs to do a registry lookup for each usage, so it's slower than code which doesn't. If interface methods become available to unify adapter and utility lookup, the same sorts of methods should be added to the registry itself for performance-sensitive code. I also believe that code that locates a registry explicitly and calls lookup methods on it is easier to understand for the maintenance programmer than is an equivalent global API. On the semantics of the change: Personally I think that it's a fantasy to believe that the difference between an object created via a factory on-demand and an object simply returned should *never* matter to a caller. You may not want the caller to need to care, and it may be inconvenient to take into account circumstances where the caller needs to care. But because this is Python, the caller still often does need to care. The only circumstance where a caller would *never* need to care would be when the object returned could be guaranteed to *never ever* have any methods called on it that weren't part of the interface defined by the interface being looked up. If we want this, we should probably just be using Java. I am extremely uncomfortable with any situation where: class IFoo(Interface): pass IFoo() ... does not result in any factory invocation. I hope it's obvious why this is the case. The current global API has a modicum "kindness" for maintenance developers because we *haven't* unified adapter and utility lookup in such a way. They stand a shot at understanding that the result of getUtility usually has "lifetime A" and the result of getAdapter/getMultiAdapter has "lifetime B". If we take out this safety belt, I'd lean towards more explicitness rather than less: let the caller call the result of the lookup. - C ___ 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 )
Re: [Zope-dev] summary of discussion was: adapter vs factory Re: implementing zope.component 4.0
Martijn Faassen wrote: > Hi there, Thanks for doing the summarise-and-move-it-on job so well, Martijn. It's really important. > I'd like to summarize the options I've seen appear in the discussion so far. > > We have the following options: > > 1) introduce a new method, such as "instance()" or "lookup()" on > instance. It unifies utilities with adapters. We can make it do whatever > we want without worrying about backwards compatibility. I find the idea of trying to conceptually reconcile adapters and utilities pretty weird. They are quite different concepts. Searching for one over-arching metaphor will probably land us in an even more conceptual "applies-to-everything" situation. I've spent the past few years explaining adapters and utilities to people as two fundamental types of components. I'd really rather not try to bring it "up" one level to explain something more generic (and thus less specific/example-friendly). I could be convinced otherwise, I'm just saying that I don't see why trying to "unify" these two things is important. > 2) introduce several new methods that distinguish between utility and > adapter lookup. We can make them do whatever we want without worrying > about backwards compatibility. > > 3) call the interface, which unifies adapter and utility lookups. If all you mean by "unify" is "more consistent API", then +1. I saw other things in the thread related to trying to treat the two as different types of the same fundamental thing, which I think we want to avoid. > Use > tuples for multi adaptation. We think could make this work without *too* > much backwards compatibility issues (pending research on how prevalent > tuple adaptation really is). In the long term we can even map out a > deprecation strategy that can smoothly migrate us to a "multi argument" > approach. +1, though I think the multi-argument thing is still going to be wrong in the future, and won't bring enough benefit for the pain it will cause. Even if by then there's no BBB to be concerned about, it's still a change, and it still breaks documentation. > 4) call the interface, which unifies adapter and utility lookups. Use > multiple arguments for multi adaptation. The backwards compatibility > obstacles are largest here as we already have the "default" argument. > We'd need to introduce multiple "modes" to selectively upgrade. -1 (aka "minus a lot"), as I've said before. > I'm in favor of calling the interface. I'm also in favor of unifying > adapter and utility lookup. > > On the back end, I'm also in favor of allowing utility creation by > factory (or "null adaptation") Can you summarise what you mean by this? The thread is so long... > and allowing instance lookup for > instances ("contextual utility lookup" or "adaptation to an instance"). My brain hurts... examples? > I think four ways to retrieve an object of the right interface > (combining factory/registered instance and lookup globally/lookup for an > instance) is a good argument *against* distinguishing between creation > strategies or "connection to adapted object or not" in the API. I'm afraid you've lost me. Four ways sounds bad, though. ;-) > If I look up a utility I wouldn't want to care whether it happened to be > a previously registered instance or a factory created one. If I look up > an adapter I wouldn't care whether it happened to be a previously > registered instance either. In fact, returning a previously registered > instance can be very well implemented using a factory. (In fact, this > suggests to me we should actually explore implementing instance > registration in terms of special factories.) Heh, I used the "shared adapter implementation" as an example of custom factories in http://plone.org/products/dexterity/documentation/manual/five.grok/core-components/adapters Martin -- Author of `Professional Plone Development`, a book for developers who want to work with Plone. See http://martinaspeli.net/plone-book ___ 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 )