On Fri, 2005-01-14 at 10:07 -0500, Phillip J. Eby wrote: > Maybe I'm missing something, but for those interfaces, isn't it okay to > keep the state in the *adapted* object here? In other words, if PointPen > just added some private attributes to store the extra data?
I have been following this discussion with quite a lot of interest, and I have to confess that a lot of what's being discussed is confusing me. I use stateful adapters quite a bit - Twisted has long had a concept of "sticky" adapters (they are called "persistent" in Twisted, but I think I prefer "sticky"). Sometimes my persistent adapters are sticky, sometimes not. Just's example of iter() as an adaptation is a good example of a non-sticky stateful adaptation, but this example I found interesting, because it seems that the value-judgement of stateless adapters as "good" is distorting design practices to make other mistakes, just to remove state from adapters. I can't understand why PJE thinks - and why there seems to be a general consensus emerging - that stateless adapters are intrinsically better. For the sake of argument, let's say that SegmentPen is a C type, which does not have a __dict__, and that PointPen is a Python adapter for it, in a different project. Now, we have nowhere to hide PointPen's state on SegmentPen - and why were we trying to in the first place? It's a horrible breach of encapsulation. The whole *point* of adapters is to convert between *different* interfaces, not merely to rename methods on the same interface, or to add extra methods that work on the same data. To me, "different interfaces" means that the actual meaning of the operations is different - sometimes subtly, sometimes dramatically. There has to be enough information in one interface to get started on the implementation of another, but the fact that such information is necessary doesn't mean it is sufficient. It doesn't mean that there is enough information in the original object to provide a complete implementation of a different interface. If there were enough information, why not just implement all of your interfaces on the original class? In the case of our hypothetical cSegmentPen, we *already* have to modify the implementation of the original class to satisfy the needs of a "stateless" adapter. When you're modifying cSegmentPen, why not just add the methods that you wanted in the first place? Here's another example: I have a business logic class which lives in an object database, typically used for a web application. I convert this into a desktop application. Now, I want to adapt IBusinessThunk to IGtkUIPlug. In the process of doing so, I have to create a GTK widget, loaded out of some sort of resource file, and put it on the screen. I have to register event handlers which are associated with that adapter. The IBusinessThunk interface doesn't specify a __dict__ attribute as part of the interface, or the ability to set arbitrary attributes. And nor should it! It is stored in an indexed database where every attribute has to be declared, maybe, or perhaps it uses Pickle and sticking a GTK widget into its representation would make it un-pickleable. Maybe it's using an O/R mapper which loses state that is not explicitly declared or explicitly touch()ed. There are a variety of problems which using it in this unsupported way might create, but as the implementor of a IGtkUIPlug, I should be concerned *only* with what IBusinessThunk provides, which is .embezzle() and .checkFundsAvailable(). I am not writing an adapter from DBBusinessThunkImpl, after all, and perhaps I am receiving a test implementation that works entirely differently. This example gets to the heart of what makes interfaces useful to me - model/view separation. Although one might be hard pressed to call some of the things I use adaptation for "views", the idea of mediated access from a user, or from network protocol, or from some internal code acting on behalf of a user is the overwhelming majority of my use-cases. Most of the other use-cases I can think of are like the one James mentions, where we really are using adaptation to shuffle around some method names and provide simple glossing over totally isomorphic functionality to provide backwards (or sideways, in the case of almost-identical libraries provided on different platforms or environments) compatibility. For these reasons I would vastly prefer it if transitivity were declared as a property of the *adaptation*, not of the adapter or the registry or to be inferred from various vaguely-defined properties like "losslessness" or "statelessness". I am also concerned about any proposal which introduces transitivity-based errors at adaptation time rather than at registration time, because by then it is definitely too late to do anything about it. I wish I had a better suggestion, but I'm still struggling through the rest of the thread :). _______________________________________________ Python-Dev mailing list Python-Dev@python.org http://mail.python.org/mailman/listinfo/python-dev Unsubscribe: http://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com