ZPatterns, ZClasses, Specialists: Assigning responsibilities
I'm having problems deciding where certain methods should be implemented. In some cases it's easy - for example, objects manage themselves, Specialists manage collections, so editInstanceForm belongs in the ZClass, while listOpenOrders belongs in the Specialist. But here are some cases where it's not as clear: 1. I want to edit an object from the editing form of another object. So I give my object an editInstanceSnippet method. It's very similar to editInstanceForm, except that it's not a full html document. Should it go in the ZClass? But it's a method used for application integration - so maybe it belongs in the Specialist? 2. In a typical shopping cart application, a Product object will be responsible for adding itself to an order, right? So the Product will have an addMeToOrderForm, which will call addMeToOrder, which in turn will call order.addOrderLineItem method. I think. But here's a complication: I have the following ZClasses, with matching Specialists: Product, Graphic, Order, OrderLineItem. When a customer adds a product to their order, they have to provide a graphic file which will be printed on the product (imagine buying a lunch box with your cat's photo on it). The Graphics Specialist can provide a addGraphicSnippet form. But who's responsible for asking for this graphic when adding the product to the order? Is it still the Product object? But a Product turns into a Product-with-Graphic only when it's a part of an order, so is it correct for the Product to even know about Graphics? the alternative is to move the addToOrder methods to either Order or OrderLineItems, but this doesn't make any more sense because these would then have to know a lot more about a Product than is good for them. Any ideas? TIA Itai -- Itai Tavor "Je sautille, donc je suis." C3Works itai@c3works.com - Kermit the Frog "If you haven't got your health, you haven't got anything"
Itai Tavor wrote:
I have the following ZClasses, with matching Specialists: Product, Graphic, Order, OrderLineItem. When a customer adds a product to their order, they have to provide a graphic file which will be printed on the product (imagine buying a lunch box with your cat's photo on it). The Graphics Specialist can provide a addGraphicSnippet form. But who's responsible for asking for this graphic when adding the product to the order? Is it still the Product object? But a Product turns into a Product-with-Graphic only when it's a part of an order, so is it correct for the Product to even know about Graphics? the alternative is to move the addToOrder methods to either Order or OrderLineItems, but this doesn't make any more sense because these would then have to know a lot more about a Product than is good for them. Any ideas?
Sounds to me like you have a new type of Product. You have your basic products (of which there are many kinds), and you have ProductWithGraphic products. A ProductWithGraphic is a "calculated product": it is composed of a basic product and a graphic. Its cost, delivery time, packing charge, and so forth, are calculated based on the combination of the basic product and the graphic. To the rest of the application, a ProductWithGraphic is just another kind of product. -- Steve Alexander Software Engineer Cat-Box limited http://www.cat-box.net
Itai Tavor wrote:
I have the following ZClasses, with matching Specialists: Product, Graphic, Order, OrderLineItem. When a customer adds a product to their order, they have to provide a graphic file which will be printed on the product (imagine buying a lunch box with your cat's photo on it). The Graphics Specialist can provide a addGraphicSnippet form. But who's responsible for asking for this graphic when adding the product to the order? Is it still the Product object? But a Product turns into a Product-with-Graphic only when it's a part of an order, so is it correct for the Product to even know about Graphics? the alternative is to move the addToOrder methods to either Order or OrderLineItems, but this doesn't make any more sense because these would then have to know a lot more about a Product than is good for them. Any ideas?
Sounds to me like you have a new type of Product.
You have your basic products (of which there are many kinds), and you have ProductWithGraphic products. A ProductWithGraphic is a "calculated product": it is composed of a basic product and a graphic. Its cost, delivery time, packing charge, and so forth, are calculated based on the combination of the basic product and the graphic.
To the rest of the application, a ProductWithGraphic is just another kind of product.
Thanks, this is an interesting suggestion... but I'm not sure how it would work. It gets very complicated when I try to think of implementing it. The application accesses products using a Products Specialist, with a Rack for each type of product. The contents of these Racks make up the Product catalog of the store. The Products Specialist implements the role of 'things that can be added to an order'. On the other hand, ProductWithGraphic is not part of the store's catalog. A new instance of it is created every time a shopper adds a product to their cart. So it does not fill the role 'thing that can be added to an order'. rather, its role is of something that has been ordered and is being fabricated. So treating ProductWithGraphic as another kind of Product doesn't seem to make sense... I do realize I need a new kind of product - CustomizableProduct. But, looking at the role of a ProductWithGraphic, it looks a lot more like an OrderLineItem than a Product. It's part of an order. It's state changes are part of the order handling process. So wouldn't it make sense to have a lineItemWithGraphic object in the OrderLineItems Specialist? That seems much simpler to me... except that the responsibilities question in it is still open. Back to square 1. This is how I see it: - Products Specialist productRack customizableProductRack - OrderLineItem Specialist lineItemRack lineItemWithGraphicRack - product.addMeToOrder(): order.addLineItem(product_id=id, add='lineItem') - custimazable_product.addMeToOrder(): order.addLineItem(product_id=id, add='lineItemWithGraphic') I imagine, then, that the UI for uploading the graphic would be included in product.addMeToOrderForm, using a UI snippet from the OrderLineItemsWithGraphic Specialist. Then I could pass REQUEST on to order.addLineItem and to OrderLineItemsWithGraphic.add, which would then upload the file? Woof... so long. I'd appreciate any comments on this - especially on the question on whether it's better to have a specialized type of OrderLineItem, or to link the standard OrderLineItem to a Product object in case of a standard product, or, in the case of a customizable product, to a new object which stores the graphic and tracks the fabrication of the customized item. TIA Itai -- Itai Tavor "Je sautille, donc je suis." C3Works itai@c3works.com - Kermit the Frog "If you haven't got your health, you haven't got anything"
At 04:21 PM 12/18/00 +1100, Itai Tavor wrote:
This is how I see it:
- Products Specialist productRack customizableProductRack
- OrderLineItem Specialist lineItemRack lineItemWithGraphicRack
- product.addMeToOrder(): order.addLineItem(product_id=id, add='lineItem')
- custimazable_product.addMeToOrder(): order.addLineItem(product_id=id, add='lineItemWithGraphic')
This should probably be more like: product.addMeToOrder(): item = OrderLineItems.newLineItemFor(self) item.setQuantity(...) etc. order.addLineItem(item) customizable_product.addMeToOrder(): item = OrderLineItems.newLineItemFor(self) item.setGraphic(...) item.setQuantity(...) etc. order.addLineItem(item) This approach makes things more declarative. The product classes can have properties or interfaces that the OrderLineItems specialist can use to decide what kind of line item would serve them best. You can then change your line item assignment rules without necessarily requiring changes to the product classes.
I imagine, then, that the UI for uploading the graphic would be included in product.addMeToOrderForm, using a UI snippet from the OrderLineItemsWithGraphic Specialist. Then I could pass REQUEST on to order.addLineItem and to OrderLineItemsWithGraphic.add, which would then upload the file?
I think you're right about this being an OrderLineItem. A couple of fine points, however... First, I don't think there needs to be an "OrderLineItemsWithGraphic" specialist, since there is nothing else that would talk to it. It's fine in this case to have the line item classes (either with graphic or without) handle their own UI snippets. UI delegation is for when an object needs to display UI for some *other* object than itself, since you can always use class extenders and other techniques to reshape the apparent class of an object retrieved from a specialist. The interface which other objects deal with is "OrderLineItem", and they simply expect a portion of the form to be rendered, and it's okay for the class to handle that. Second, you need to define that interface so that the Order can give the line item constraints on how it does that UI, so it can share the screen and REQUEST with other objects/data that the Order needs. One easy way to do this is to use a namespace parameter, that simply gives the line item a name prefix to use on its fields. Alternatively, you can use the "record" approach, like this: <INPUT TYPE="TEXT" NAME="lineitem1.desiredSize:record:int" VALUE="4"> <INPUT TYPE="FILE" NAME="lineitem1.imageFile:record:file"> ... The resulting REQUEST object from submitting the form will contain a single object, "lineitem1", with "desiredSize" and "imageFile" attributes, so you'll only have to pass a single parameter back to the line item. I've never tried doing a record with a file in it before, so I don't really know how well that works.
Woof... so long. I'd appreciate any comments on this - especially on the question on whether it's better to have a specialized type of OrderLineItem, or to link the standard OrderLineItem to a Product object in case of a standard product, or, in the case of a customizable product, to a new object which stores the graphic and tracks the fabrication of the customized item.
Here's the question... how many behaviors are different in the order line item itself? Are you also using fulfillment line items? If the only difference to the order line item is that it references some additional data, then I'd say a single class would be fine. Most of the behavior probably comes in on the fulfillment line item, yes? Again, you can ask your FulfillmentLineItems specialist to create "newLineItemFor(orderLineItem)" and let it decide what kind of implementation to hand back. In this case, it probably will be a different class, while for the order line items, it may or may not buy you anything. Anyway... remember that Specialists are there to hide implementation decisions like what classes are being used. If you look at the ZPatterns Wiki you'll see references to some of the design patterns which Specialists are an instance of, which will give you some hints as to the many kinds of things they can "hide" for you (and which therefore you should avoid revealing in other code). One of those patterns is that as an object "trader" or "broker", Specialists can be used to create new instances of objects that meet a certain interface, but whose implementation has been selected on the basis of declarative criteria by the requesters.
participants (3)
-
Itai Tavor -
Phillip J. Eby -
Steve Alexander