Hi folks, I've been looking at the DropZone example Phillip Eby provided on the ZPatterns Wiki. http://www.zope.org/Members/pje/Wikis/ZPatterns/DropZoneExample I've decided to start implementing it, so as to give myself an educational experience in using ZPatterns. I have an open question: The suggested specialists in the Accounting framework are: Invoices Orders Customers Products What I'm finding is that these are just the White-box specialists. A clean design would seem to want all the specialists above, plus at least one Black-box specialist to do the "heavy lifting. Let's call it the "AccountingProcessor" specialist. Now, if I had a third-party accounts package (something by Sage perhaps), I could make the AccountingProcessor specialist expose various functions to the four other White-box specialists. It would implement these by making equivalent calls on the underlying accounting package. I could also swap the heavy-lifting portion of my framework by swapping the black-box AccountingProcessor specialist for one that talks to some software by Quicken, or perhaps some software that is written in Python as a conventional Zope product. The same goes for the Resource Scheduling framework. We have some White-box specialists, ripe for customisation: Resources Reservations ResourceUsers And then for the heavy-lifting we have the black-box ResourceScheduler specialist. Again, this might be a Zope Python Product, or it might be an interface to some application written on top of Microsoft Exchange. Are specialists intended to be placed inside other specialists, as "contents"? So in this case, would the white-box specialists live inside the black-box specialist -- so they become the customisable aspects of the overall framework? Or would both black-box and white-box specialists live inside an uber-specialist? Or is this just down to taste? -- Steve Alexander Software Engineer Cat-Box limited http://www.cat-box.net
At 05:26 PM 6/28/00 +0100, Steve Alexander wrote:
The suggested specialists in the Accounting framework are:
Invoices Orders Customers Products
What I'm finding is that these are just the White-box specialists. A clean design would seem to want all the specialists above, plus at least one Black-box specialist to do the "heavy lifting. Let's call it the "AccountingProcessor" specialist.
Keep in mind that a Specialist doesn't just "store" a bunch of objects, it also provides *methods for dealing with sets of objects*. So an Invoices specialist could usefully contain a wide variety of reporting methods, for example. Similarly, the Customers specialist might have a method to post balances forward on all customer accounts whose statement cycle is in a certain date range. These are all "heavy lifting" from an accounting point of view, but perfectly valid to have in the white-box specialists. White-box doesn't mean that there's no implementation; it just means that the implementation is intended to be extensible or integratable by someone other than the framework's original developer.
Now, if I had a third-party accounts package (something by Sage perhaps), I could make the AccountingProcessor specialist expose various functions to the four other White-box specialists. It would implement these by making equivalent calls on the underlying accounting package.
I could also swap the heavy-lifting portion of my framework by swapping the black-box AccountingProcessor specialist for one that talks to some
software by Quicken, or perhaps some software that is written in Python as a conventional Zope product.
That's all quite true, but it would probably be simplest to do such a thing using AttributeProviders and SheetProviders in the white-box specialists. It does seem reasonable to have those providers talk to an AccountingProcessor object if you want to make your framework talk to different back-ends, but I think it is misleading and incorrect to call AccountingProcessor a specialist, as it's not an application-level service object, but a private implementation helper. Interestingly, you've just given me what may be a motivating example for using Shane Hathaway's DatabaseAPI in conjunction with ZPatterns, assuming of course that I've correctly understood his most recent explanation of the DatabaseAPI product.
The same goes for the Resource Scheduling framework. We have some White-box specialists, ripe for customisation:
Resources Reservations ResourceUsers
And then for the heavy-lifting we have the black-box ResourceScheduler specialist. Again, this might be a Zope Python Product, or it might be an interface to some application written on top of Microsoft Exchange.
Again, look to what these specialist would do besides look up objects. For example, utilization or load-balancing reports. Generating bills for usage. Generating calendars for individual resources. Checking for conflicts. Etc.
Are specialists intended to be placed inside other specialists, as "contents"?
You *can* do this, but I've not yet encountered a real-life situation where I *would* do this. (Mike has given some examples that suggest it might be useful under some circumstances, however.)
So in this case, would the white-box specialists live inside the black-box specialist -- so they become the customisable aspects of the overall framework? Or would both black-box and white-box specialists live inside an uber-specialist?
If anything, the black box should be inside the white. Otherwise, you are creating confusion between heaven and earth. :) Seriously, the white boxes are the parts you will reference in URL's most often, so why have /AccountingProcessor/Invoices/ when you can just have /Invoices/? If you have to share a black box among white boxes, acquire it. If your "root" gets too messy, then make an "Accounting" folder and put Invoices, AccountingProcessor, and the rest inside of it.
Thus spake Phillip J. Eby (pje@telecommunity.com):
That's all quite true, but it would probably be simplest to do such a thing using AttributeProviders and SheetProviders in the white-box specialists. It does seem reasonable to have those providers talk to an AccountingProcessor object if you want to make your framework talk to different back-ends, but I think it is misleading and incorrect to call AccountingProcessor a specialist, as it's not an application-level service object, but a private implementation helper.
Does anybody out there have even the slightest clue about how to go about using AttributeProviders and SheetProviders? A select few terse hints on this subject would really help us (me) figure it out enough to start working on some howto's.
Interestingly, you've just given me what may be a motivating example for using Shane Hathaway's DatabaseAPI in conjunction with ZPatterns, assuming of course that I've correctly understood his most recent explanation of the DatabaseAPI product.
Am i wrong in thinking that DatabaseAPI is a completely separate solution to the same problem that ZPatters is suppose to address? Personally i have to give DatabaseAPI props for being quite easy to understand and use, while not sacrificing power. sRp -- Scott Parish http://srparish.net/
At 02:21 AM 7/5/00 +0000, Scott Parish wrote:
Does anybody out there have even the slightest clue about how to go about using AttributeProviders and SheetProviders? A select few terse hints on this subject would really help us (me) figure it out enough to start working on some howto's.
You might look at some of the recent posts which included an example of using GenericAttributeProviders to read from a MySQL database, and my reply explaining how to use a GenericTrigger to update that same database.
Am i wrong in thinking that DatabaseAPI is a completely separate solution to the same problem that ZPatters is suppose to address? Personally i have to give DatabaseAPI props for being quite easy to understand and use, while not sacrificing power.
Peter Coad's design approach (which ZPatterns is heavily based on/biased towards) emphasizes four major layers of classes in an application: 1) User Interface (GUI, forms, etc.) 2) Problem Domain (the actual application purpose) 3) Data Management (object persistence/lifecycle management) 4) System Interaction (interfaces w/hardware or other software) ZPatterns is focused on providing tools for transparent mappings between layers 2 and 3, while DatabaseAPI, as far as I can see (and I actually did play around with it today to get a feel for it), is focused on tools for building clean mappings between layers 3 and 4. In my mind, this makes them complementary tools, rather than competitors in any real sense. Indeed, looking at DatabaseAPI has shown me that there are some features I'd planned for ZPatterns (or already started) that I can scrap because DatabaseAPI has them and can easily interoperate. (Personally, I'd like to see a version of DatabaseAPI using PlugIns to structure its user interface, which I think could easily make it even cleaner and easier to use than it already is. It might then also be possible to reuse some of its plug-ins for functionality in areas of ZPatterns. But I digress.) So where do DatabaseAPI and ZPatterns overlap? DatabaseConnector has some functional overlap with Specialist. If you ignore the attribute, sheet, and trigger providing aspects of ZPatterns (and also look only at the raw functionality), the primary difference between a Specialist and a DatabaseConnector is that DatabaseConnectors will probably have methods to delete objects or change their data, which is a no-no for a Specialist because it's an encapsulation breach. Beyond this, there's a significant difference in intent between a Specialist and a DatabaseConnector (IMHO). A Specialist serves as a broker to access objects which fill a certain role in a framework, while a DatabaseConnector represents an object which manipulates "records" which are of "record types" and have "fields". Specialists use Racks to explicitly distinguish between problem-domain and data-domain concerns; you can probably do this with nested DatabaseConnectors but you'll have to do some additional work to support it. ZPatterns could definitely benefit from some ideas found in DatabaseAPI, primarily in the aspect of documenting API's and supporting better design contracts. For example, it would be nice for a Specialist to be able to define the API expected from its Racks, and a for an application framework to somehow define the API expected from the Specialists it will interact with. One could of course use the existing DatabaseAPI product to do these things, but the integration would be less than smooth, since you'd have to make the Specialist ask the Racks for their DatabaseConnectors, or else have a Rack class that delegated to a DatabaseConnector, or something like that. Anyway, I'm going to have to give these possibilities some more thought.
"Phillip J. Eby" wrote: [snip]
Peter Coad's design approach (which ZPatterns is heavily based on/biased towards) emphasizes four major layers of classes in an application:
1) User Interface (GUI, forms, etc.) 2) Problem Domain (the actual application purpose) 3) Data Management (object persistence/lifecycle management) 4) System Interaction (interfaces w/hardware or other software)
Is this from one of his books? If so, which one? I would be interested in gaining more enlightenment. :) Thanks, Jimmie Houchin
At 03:12 PM 7/5/00 -0500, Jimmie Houchin wrote:
"Phillip J. Eby" wrote: [snip]
Peter Coad's design approach (which ZPatterns is heavily based on/biased towards) emphasizes four major layers of classes in an application:
1) User Interface (GUI, forms, etc.) 2) Problem Domain (the actual application purpose) 3) Data Management (object persistence/lifecycle management) 4) System Interaction (interfaces w/hardware or other software)
Is this from one of his books? If so, which one?
"Object Models: Strategies, Patterns, and Applications"
Hi Steve, (and any others who might care to comment....) I've been sorting through old ZPatterns email looking for inspiration and I came upon this:
"Steve" == Steve Alexander <steve@cat-box.net> writes:
Steve> Hi folks, Steve> I've been looking at the DropZone example Phillip Eby Steve> provided on the ZPatterns Wiki. Steve> http://www.zope.org/Members/pje/Wikis/ZPatterns/DropZoneExample Steve> I've decided to start implementing it, so as to give myself Steve> an educational experience in using ZPatterns. Did you get very far with this? I'm still working out the best way to get EMarket to work with ZPatterns in my copious spare time, and I've hit a question... in the original EMarket design Shopper, MarketItem, ShoppingBasket, and ShoppingBasketItem were all classes defined in Python. With ZPatterns I'm moving in a direction in which these will be replaced at runtime with customized objects that will merely play the *role* of Shopper, etc... I see how the data associated with these objects can be virtually provided using SkinScript etc... but I'm a little confused about the methods of these objects. PJE makes it very clear in his DropZone example (cited above) that when you allow objects to 'role play', they do not subclass from anything in particular, but rather just sort of 'drop in' and 'act like' any sort of object they need to, in order to get the job done. However, without subclassing... how do they get the Shopper methods? e.g., one EMarket method might be: aShopper.insertIntoShoppingBasket( mi=aMarketItem, quantity=qty ) One idea that occured to me was to make the specialists 'do' everything. ShopperManager.InsertItemIntoShoppersBasket(shopper=aShopper, mi=aMarketItem, quantity=qty), but this smells a little bit like the 'controller' paradigm that Coad et. al. are so opposed to... It seems like 'big brother' for the ShopperManager to be meddling with the individual items in a shopper's basket... but maybe that's the best way... Anyway.. just fiddling around and looking for ideas... thanks! -steve
Steve Spicklemire wrote:
Hi Steve, (and any others who might care to comment....)
I've been sorting through old ZPatterns email looking for inspiration and I came upon this:
"Steve" == Steve Alexander <steve@cat-box.net> writes:
Steve> Hi folks,
Steve> I've been looking at the DropZone example Phillip Eby Steve> provided on the ZPatterns Wiki.
Steve> http://www.zope.org/Members/pje/Wikis/ZPatterns/DropZoneExample
Steve> I've decided to start implementing it, so as to give myself Steve> an educational experience in using ZPatterns.
Did you get very far with this?
I designed it in some detail on paper. I didn't get into implementation though; a real project using ZPatterns got there first :-) <deletia>
but this smells a little bit like the 'controller' paradigm that Coad et. al. are so opposed to... It seems like 'big brother' for the ShopperManager to be meddling with the individual items in a shopper's basket... but maybe that's the best way...
If the ShopperManager specialist is responsible for the basket propertysheet, then it should provide methods to add and remove items from the basket propertysheet. In plain language, the Shoppers Specialist is responsible for a Shopper's basket. Let's say you're integrating the DropZone system with Etailer, so that SkyDivers can buy parachutes at our on-line shop. Somewhere, you'll have to ensure that SkyDivers get a Basket propertysheet. Perhaps they get this on entering the shop. When you're in a real physical shop, the basket belongs to the shop. I think it is quite natural that the Shoppers specialist is responsible for taking things from the shop's shelves and putting them in the shop's basket that the shopper is holding. You can alter your SkyDiver class so that it has methods for adding items to the basket and so forth, that forward on to the Shoppers specialist. However, this seems unnatural to me. Can a SkyDiver always add an item to her basket, or can she only do this when she is in the shop?
ShopperManager.InsertItemIntoShoppersBasket(shopper=aShopper, mi=aMarketItem, quantity=qty),
Seeing as the context is clearly ShopperManger (or Shoppers), I don't think there's any need for such a long method name. The context clearly involves shoppers and baskets, so perhaps AddToBasket(shopper, item, qty) would be clear enough? If anything, AddToBasket could be a method of MarketItem. Item.addToBasketOf(Shopper). However, if Items live on Shelves in Isles in a Shop, addToBasketOf could be a method of the Shop, that gets found by acquisition from items in the shop. And, perhaps we know who the Shopper is from the AUTHENTICATED_USER of the REQUEST. The Zope object heirarchy might look like this: Shop |-addToBasket(qty) (forwards to ShoppersSpecialist.addToBasket(shopper, item, qty)) | |-ParachutesIsle |-LargeSizeShelf |-BlueParachute Again, I don't know much about Etailer, so I'm kind of guessing. Hope this is helpful. -- Steve Alexander Software Engineer Cat-Box limited http://www.cat-box.net
Hi Steve,
"Steve" == Steve Alexander <steve@cat-box.net> writes:
>> ShopperManager.InsertItemIntoShoppersBasket(shopper=aShopper, >> mi=aMarketItem, quantity=qty), Steve> Seeing as the context is clearly ShopperManger (or Steve> Shoppers), I don't think there's any need for such a long Steve> method name. The context clearly involves shoppers and Steve> baskets, so perhaps AddToBasket(shopper, item, qty) would Steve> be clear enough? Yeah.. the long method name was to help clarify the meaning. ;-) Steve> If anything, AddToBasket could be a method of MarketItem. Steve> Item.addToBasketOf(Shopper). However, if Items live on Steve> Shelves in Isles in a Shop, addToBasketOf could be a method Steve> of the Shop, that gets found by acquisition from items in Steve> the shop. And, perhaps we know who the Shopper is from the Steve> AUTHENTICATED_USER of the REQUEST. Again... it seems to me that these objects aren't allowed to have methods, since that would require sub classing and according to my understanding sub classing is sort of a 'deprecated' approach. Maybe I'm missing something... I like your thought about the 'shop' being the best object responsible for handling the shopping baskets.. it's just a different way to slice the problem.. I could get used to it. ;-) thanks, -steve
Every couple of weeks I get a little time to work on this stuff... well, it's been a couple weeks. ;-) I was flailing last time over the issue of how to create objects that could be 'plugged' into different frameworks cleanly. One problem was that my existing framework had specific classes of objects that had specific methods associated with them.... I was having trouble working out how to use a 'generic' DataSkin in place of a specific object, say shopper, without having my DataSkin subclass somehow from the original shopper object. We were batting around the idea of putting the methods in the Specialist, rather than the object and have the specialist 'reach in and meddle' with the object itself... but now I see another way.. the generic dataskins could simply acquire the methods that they need from the specialist.... so rather than: MySkinManager.DoSomething( mySkin, etc... ) it could be mySkin = MySkinManager.retrieveObject( theObjectID ) mySkin.DoSomething( etc... ) where 'DoSomething' is a method of the Specialist MySkinManager, but it is only intended to be used (by acquisition) as a method of a 'managed skin...'. This all begs some questions.... (1) Is this 'reasonable'? Is anyone else using methods of specialists this way? (2) is it worth enforcing the use by acquisition? e.g., def DoSomething(self, etc... ): """ Do Something Cool.... """ if hasattr(self, '_isRackMountable'): ... continue with something cool... else: raise RuntimeError, "Sorry... this method must be acquired by a DataSkin.." (3) Has anyone found a better way to adorn 'plain' objects with methods? thanks! -steve
Steve Spicklemire wrote:
Every couple of weeks I get a little time to work on this stuff... well, it's been a couple weeks. ;-)
Keep them coming :-)
the generic dataskins could simply acquire the methods that they need from the specialist....
This all begs some questions....
(1) Is this 'reasonable'? Is anyone else using methods of specialists this way?
Let's think of an example from real life. Let's say we have a Person class. We also have a Prison specialist. When a Person is in Prison, they are given a Prisoner propertysheet with properties like state_prisoner_id, security_category, admission_date, sentence_length. A person also has different capabilities when in prison. In general, people can do different things depending on where they are; behaviour depends on type and on context. In prison, a many of the things a person can normally do are forbidden; for example, acquire and spend money. There are also additional things a person can do: see their probation officer; book a family visit. I think your suggestion of having methods in a specialist that get acquired by classes managed by that specialist generally fits in with the thought-experiment of persons in prison. However, perhaps a Folder w/ Customizer Support, and methods in that folder that are made available via acquisition, is a better match still.
(2) is it worth enforcing the use by acquisition? e.g.,
I'm not sure what the benefit would be. Perhaps there could be a plug-in tab in a specialist for "methods acquired by rackmounted dataskins".
(3) Has anyone found a better way to adorn 'plain' objects with methods?
I've used ordinary acquisition, as described just above. You can use Transparent folders to keep things organized neatly. -- Steve Alexander Software Engineer Cat-Box limited http://www.cat-box.net
Steve Spicklemire wrote:
(3) Has anyone found a better way to adorn 'plain' objects with methods?
An AttributeProvider? -- Itamar S.T. itamar@maxnm.com Fingerprint = D365 7BE8 B81E 2B18 6534 025E D0E7 92DB E441 411C
Er Hmmm.... wow. I guess I never thought of attribute providers supplying anything other than instance 'data'. I'll have to try that! Thanks for the idea! This would mean that I could map methods onto my objects from any source I like... <hoping that the acqusition machinery won't get confused! ... I can see it now... who did you say self was again? ;-) > thanks, -steve
"Itamar" == Itamar Shtull-Trauring <itamar@maxnm.com> writes:
Itamar> Steve Spicklemire wrote: >> (3) Has anyone found a better way to adorn 'plain' objects with >> methods? Itamar> An AttributeProvider? Itamar> -- Itamar S.T. itamar@maxnm.com Fingerprint = D365 7BE8 Itamar> B81E 2B18 6534 025E D0E7 92DB E441 411C
participants (6)
-
Itamar Shtull-Trauring -
Jimmie Houchin -
Phillip J. Eby -
Scott Parish -
Steve Alexander -
Steve Spicklemire