[Zope-dev] ZPatterns, ZClasses, Specialists: Assigning responsibilities

Phillip J. Eby pje@telecommunity.com
Mon, 18 Dec 2000 11:47:45 -0500


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.