Re: [Zope3-Users] Re: zope.intid and UUIDs
I really like Gary's suggestions here, which I'll paraphrase: First create interfaces that content can be adapted to to get a UUID, so other people can provide different implementations and those can interoperate. Then, create default implementations that work however you like. Then if you, or one of your users want to use a different, or second implementation, the migration will be much easier. -- Benji York Senior Software Engineer Zope Corporation ___ Zope3-users mailing list Zope3-users@zope.org http://mail.zope.org/mailman/listinfo/zope3-users
Re: [Zope3-Users] Re: zope.intid and UUIDs
On Friday 20 April 2007 10:01, Benji York wrote: First create interfaces that content can be adapted to to get a UUID, so other people can provide different implementations and those can interoperate. Then, create default implementations that work however you like. This is actually a pattern that we use all over the place. One example is lovely.tag. You have a utility providing some functionality, such as a UUID generator and then use an object adapter to access it more conveniently. What *I* like about about the proposed solutions is to reuse the intid utility. Regards, Stephan -- Stephan Richter CBU Physics Chemistry (B.S.) / Tufts Physics (Ph.D. student) Web2k - Web Software Design, Development and Training ___ Zope3-users mailing list Zope3-users@zope.org http://mail.zope.org/mailman/listinfo/zope3-users
Re: [Zope3-Users] Re: zope.intid and UUIDs
On Apr 19, 2007, at 12:56 PM, Derek Richardson wrote: We've talked a lot about the composition alternative to my idea, but we haven't talked about my idea much. What is suboptimal with the way I'm proposing, other than that it requires changing zope core? Martin Aspeli had some concrete things to say about why subclassing, your proposal, is suboptimal in comparison to composition. He cast it as why composition would be better, which is simply the mirror image. His first point is particularly interesting: the composition approach might let Plone users leverage your code, which introduces it to a large community of users. They (or Zope 2 core? not sure) have their own intid utility. Composition will be simpler, both in the short and long term; or, if you prefer, to relate it to your proposal, the subclassing approach is suboptimal in comparison. Some more thoughts, FWIW: - I suggest that the implementation should be hidden away. One should be able to adapt an object to something like IUUID or IUUIDProvider. That way we can implement a variety of solutions, including a direct key-reference-to-UUID mapping, a intid-to-UUID mapping, a simple annotation, or other approaches. In other words, IMO, the main feature of your package should be an interface (or two, see below). - I imagine you also want to be able to find objects for a given UUID. I'd suggest an interface for that, which is used to look up a utility. Again, the implementation may vary. - In terms of your default implementation, the integer-based approach is interesting as a building block because there may be different integer sources for a given object, not just intids. For instance, I have an app in which I have integer identifiers for virtual objects, which may be fulfilled with different real objects based on current state. One app might want UUIDs to be generated for the virtual object, while another might want UUIDs for the real objects (so intids based on the standard persistent object key references would be appropriate). Or is that a good enough reason to not do it? No, but that certainly raises the bar, as you'd expect. Gary ___ Zope3-users mailing list Zope3-users@zope.org http://mail.zope.org/mailman/listinfo/zope3-users
[Zope3-Users] Re: zope.intid and UUIDs
Derek Richardson wrote: Philipp von Weitershausen wrote: Derek Richardson wrote: I sense that I'm missing the point here. Perhaps you can elaborate on what you mean when you say use and collaboration. I usually know what those terms mean, but I'm not sure I am getting it in this context. The paragraph definitely seems to miss the point, so let me speak code:: class UUIDUtility(Contained, Persistent): def __init__(self): self.uuids = IOBTree.IOBTree() self.intids = OIBTree.OIBTree() def getObject(self, uuid): intid = self.intids[uuid] return getUtility(IIntIds).getObject(intid) def getUUID(self, object): intid = getUtility(IIntIds).getId(object) return self.uuids[intid] I'm omitting several seatbelts and various functions to add/remove objects from the UUID utility, but I hope you'll get the idea. With the composition approach, the actual utility class may be a little shorter than simply copying the whole thing, but I'll still have to copy and just change the names on a bunch of stuff in interfaces.py (IIntIds - IUUIDs, IIntIdsQuery - UUIDSQuery, etc). Perhaps. You could also come up with a shorter/easier/... API, though I see how it is compelling to model after the IIntIds API. And I'll have to copy most of the tests. You better have good test coverage for your utility anyway. That argument doesn't count :). Martin and Gary pointed out other good reasons why not to go with subclassing: the standard intid utility doesn't work in all environments. Apparently in Zope 2 you'll need a slightly differnet implementation. If you just defer to it via utility lookup, your UUID utility might actually work on both platforms, as long as there's an intid utility. It makes things more flexible. The subclasses are pretty much complete as written here and the BaseIdUtility is just a minor abridgment of IntIds. This allows all the interfaces (other than the two empty markers and the events) to be reused between intids and UUIDs and most of the tests can be performed for both, as well. We've talked a lot about the composition alternative to my idea, but we haven't talked about my idea much. What is suboptimal with the way I'm proposing, other than that it requires changing zope core? Or is that a good enough reason to not do it? Your subclassing idea has a lot of appeal to it. To answer your question what's suboptimal about it: you'll have to wait till the next Zope 3 release cycle to actually make use those modifications. Also, like I said above, the composition approach allows you to be more flexible. -- http://worldcookery.com -- Professional Zope documentation and training ___ Zope3-users mailing list Zope3-users@zope.org http://mail.zope.org/mailman/listinfo/zope3-users
[Zope3-Users] Re: zope.intid and UUIDs
Philipp von Weitershausen wrote: Martin and Gary pointed out other good reasons why not to go with subclassing: the standard intid utility doesn't work in all environments. Apparently in Zope 2 you'll need a slightly differnet implementation. If you just defer to it via utility lookup, your UUID utility might actually work on both platforms, as long as there's an intid utility. It makes things more flexible. Hmmm. I've looked in Zope 2.10.3 final (the earliest release I may target) and zope.app.intid is the same between Zope 2.10.3 and Zope 3.3.1, except for the presence in 2.10.3 of zope.app.intid-configure.zcml, which is just a slug. Am I looking in the wrong place? Your subclassing idea has a lot of appeal to it. To answer your question what's suboptimal about it: you'll have to wait till the next Zope 3 release cycle to actually make use those modifications. Also, like I said above, the composition approach allows you to be more flexible. OK, yes, this is a problem. I'm targeting on Plone 3.5 (for the final product, not the uuid utility alone), but I'd like to be backwards-compatible with Zope 2.10.x. So, yes, I'll have to provide a complete backwards-compatible package. I've thought about it and decided that these two proposals (subclassing and composition) are partially orthogonal. Half of subclassing is simply genericizing the interfaces; composition is a matter of implementation. For proof, consider that we could have a UUIDs that implements IIDs and defers to an IntIds for implementation, which also implements IIDs. This might reduce the benefits of code reuse, but would still gain the benefit of one set of interfaces (aside from the IntIds and UUIDs markers). So, my plan. I am going to copy IntIds, genericize the interfaces, and split the superclass from the subclass as mentioned. I'm going to do this in my package. I will provide a UUID implementation but not an IntId implementation. That way if, in the future, y'all decide to move towards this in the core, there will be a pre-existing implementation and I'll be ready. You could include just the interfaces, the interfaces and the utility superclass with a new IntIds subclass without the UUID implementation, or you could include everything - it's up to you. And, if you don't, then I haven't lost anything but 15 minutes of time. As for implementation, I'm going to have to think through whether composition is appropriate for my use. Another advantage of genericizing the interfaces is that this is an implementation detail - I may provide two uuid implementations, one that is composed by intid and one that is not. I may also rethink the implementation of the base utility class to see if I can maximize reuse between these two cases. And, having this flexibility will help me later if I run into trouble backporting to Zope 2.10.x. A fun project! The code will be in the Vice project in the Plone collective, for now, in the packages collective.id and collective.uuid. Thanks, Derek ___ Zope3-users mailing list Zope3-users@zope.org http://mail.zope.org/mailman/listinfo/zope3-users
[Zope3-Users] Re: zope.intid and UUIDs
Derek Richardson wrote: Philipp von Weitershausen wrote: Martin and Gary pointed out other good reasons why not to go with subclassing: the standard intid utility doesn't work in all environments. Apparently in Zope 2 you'll need a slightly differnet implementation. If you just defer to it via utility lookup, your UUID utility might actually work on both platforms, as long as there's an intid utility. It makes things more flexible. Hmmm. I've looked in Zope 2.10.3 final (the earliest release I may target) and zope.app.intid is the same between Zope 2.10.3 and Zope 3.3.1, except for the presence in 2.10.3 of zope.app.intid-configure.zcml, which is just a slug. Am I looking in the wrong place? Yes, it's there, but that doesn't mean it *works* in Zope 2. You should look at five.intid, which is an attempt to make it work in Zope 2. Martin ___ Zope3-users mailing list Zope3-users@zope.org http://mail.zope.org/mailman/listinfo/zope3-users
[Zope3-Users] Re: zope.intid and UUIDs
Derek Richardson wrote: All, I've decided to go ahead and write an RFC 4122 UUID utility based on zope.intid (this is for a Plone SoC project, but this bit is pure Zope 3). I wrote most of it today and there is more code shared between the two than is different. The main differences are: * OOBTrees, instead of an IOBTree and an OIBTree * Different events are fired when an object is registered and unregistered (they could be merged, but this is easy backwards-compatibility) * _generateId() is, of course, different The rest is pretty much copied and pasted, even most of the tests. My question is: should the common parts be abstracted out into a framework for id utilities, of which intid and uuid will be two instantiations? I know this is a small amount of code but: * I hate copy and paste * I hate the idea of bugs in two places (implicit coupling, from a bug fixer's perspective) * Larger codebases mean more to read to understand what is going on for newbies, like me Of course, the duplication rule is If you do it three times, you're doing it wrong and I've only done it the second time. So, part of this question is whether anyone can see a future need for any id utilities other than intid and uuid. If so, I think this would definitely be a good move. Otherwise, I'm up in the air. Of course, this would be a change to zope core, which is the main reason I'm leery. I will be sending in my contributor agreement tomorrow. So, I'm really wondering whether this is worth changing in the core or whether we shouldn't bother. In the spirit of Benji's suggestion, why don't you try to make the UUID utility *use* the intid utility? Basically, the UUID utility would simply keep a mapping of intid - UUID and defer to the intid utility for retrieving the object from the intid and viceversa. Speed might be an issue here, though BTrees are pretty fast and memory efficient, especially with integers... -- http://worldcookery.com -- Professional Zope documentation and training ___ Zope3-users mailing list Zope3-users@zope.org http://mail.zope.org/mailman/listinfo/zope3-users
[Zope3-Users] Re: zope.intid and UUIDs
Benji York wrote: Derek Richardson wrote: I wrote most of it today and there is more code shared between the two than is different. The main differences are: * OOBTrees, instead of an IOBTree and an OIBTree * Different events are fired when an object is registered and unregistered (they could be merged, but this is easy backwards-compatibility) * _generateId() is, of course, different The rest is pretty much copied and pasted, even most of the tests. This suggests to me that you instead want to /use/ an int ID utility, not /be/ (a mutated) one. Unless there's a very compelling reason to copy all that functionality composition would be much cleaner. I definitely don't want to be an *int* id utility. I may want to be, however, a uuid variety of an *id* utility, of which another variety would be int, and perhaps others, as well. I see no compelling reason to copy all that functionality, which is why I'm exploring alternatives. *Using* an int id utility, though, doesn't seem to cleanly solve the problem, which makes me wonder if I'm understanding you. If you mean use the intid utility to map keyrefs to int ids and then map int ids to uuids, this has a few problems. What I want to vary is the implementation - I want to keep the same interface. This would be keeping, and adding another layer to, the implementation and I'll still have to re-implement the interface on top of it. That's more work than just copying and doesn't reduce the copying at all, as I see it. Plus, it'll be (perhaps marginally) slower. If you mean use the intid utility by instantiating one and then changing the data structures and _generateId() and the events at runtime, this would indeed solve the need to copy and paste. However, this seems like an obfuscating solution - who would guess that what is masquerading as an intid utility is really a uuid utility? Perhaps that's my static-typing background speaking, but it seems cleaner to have an abstract id utility and then write 10 lines of code to subclass and turn it into an int id utility and then another 10 lines for uuids. I sense that I'm missing the point here. Perhaps you can elaborate on what you mean when you say use and collaboration. I usually know what those terms mean, but I'm not sure I am getting it in this context. Derek ___ Zope3-users mailing list Zope3-users@zope.org http://mail.zope.org/mailman/listinfo/zope3-users
[Zope3-Users] Re: zope.intid and UUIDs
Derek Richardson wrote: *Using* an int id utility, though, doesn't seem to cleanly solve the problem, Why? which makes me wonder if I'm understanding you. If you mean use the intid utility to map keyrefs to int ids and then map int ids to uuids, this has a few problems. Which ones? What I want to vary is the implementation - I want to keep the same interface. Your UUID utility should be able to keep the same interface. But instead of doing a keyref - UUID mapping, it refers to the intid utility for keyref - intid and itself only does intid - UUID. This would be completely transparent to the outsider. This would be keeping, and adding another layer to, the implementation and I'll still have to re-implement the interface on top of it. That's more work than just copying and doesn't reduce the copying at all, as I see it. Plus, it'll be (perhaps marginally) slower. Perhaps. That's something to profile. If you mean use the intid utility by instantiating one and then changing the data structures and _generateId() and the events at runtime, this would indeed solve the need to copy and paste. However, this seems like an obfuscating solution - who would guess that what is masquerading as an intid utility is really a uuid utility? Perhaps that's my static-typing background speaking, but it seems cleaner to have an abstract id utility and then write 10 lines of code to subclass and turn it into an int id utility and then another 10 lines for uuids. I sense that I'm missing the point here. Perhaps you can elaborate on what you mean when you say use and collaboration. I usually know what those terms mean, but I'm not sure I am getting it in this context. The paragraph definitely seems to miss the point, so let me speak code:: class UUIDUtility(Contained, Persistent): def __init__(self): self.uuids = IOBTree.IOBTree() self.intids = OIBTree.OIBTree() def getObject(self, uuid): intid = self.intids[uuid] return getUtility(IIntIds).getObject(intid) def getUUID(self, object): intid = getUtility(IIntIds).getId(object) return self.uuids[intid] I'm omitting several seatbelts and various functions to add/remove objects from the UUID utility, but I hope you'll get the idea. -- http://worldcookery.com -- Professional Zope documentation and training ___ Zope3-users mailing list Zope3-users@zope.org http://mail.zope.org/mailman/listinfo/zope3-users
[Zope3-Users] Re: zope.intid and UUIDs
I have no principled objection to a ZPL license. And I would like the code to make it into the core, if appropriate. So, the answer is, a ZPL license is likely. David Pratt wrote: I like this idea of abstracting the code for ids myself. It will be interesting to hear what others have to say. Can you advise whether the UUID utility will be ZPL licensed since this is important if you are talking about something with generic functionality for z3. Many thanks. Regards, David Derek Richardson wrote: All, I've decided to go ahead and write an RFC 4122 UUID utility based on zope.intid (this is for a Plone SoC project, but this bit is pure Zope 3). I wrote most of it today and there is more code shared between the two than is different. The main differences are: * OOBTrees, instead of an IOBTree and an OIBTree * Different events are fired when an object is registered and unregistered (they could be merged, but this is easy backwards-compatibility) * _generateId() is, of course, different The rest is pretty much copied and pasted, even most of the tests. My question is: should the common parts be abstracted out into a framework for id utilities, of which intid and uuid will be two instantiations? I know this is a small amount of code but: * I hate copy and paste * I hate the idea of bugs in two places (implicit coupling, from a bug fixer's perspective) * Larger codebases mean more to read to understand what is going on for newbies, like me Of course, the duplication rule is If you do it three times, you're doing it wrong and I've only done it the second time. So, part of this question is whether anyone can see a future need for any id utilities other than intid and uuid. If so, I think this would definitely be a good move. Otherwise, I'm up in the air. Of course, this would be a change to zope core, which is the main reason I'm leery. I will be sending in my contributor agreement tomorrow. So, I'm really wondering whether this is worth changing in the core or whether we shouldn't bother. Thanks, Derek ___ Zope3-users mailing list Zope3-users@zope.org http://mail.zope.org/mailman/listinfo/zope3-users ___ Zope3-users mailing list Zope3-users@zope.org http://mail.zope.org/mailman/listinfo/zope3-users