[Zope-dev] Questions about implementing object models with ZPatterns

Phillip J. Eby pje@telecommunity.com
Tue, 07 Nov 2000 11:20:18 -0500


At 05:19 PM 11/1/00 +1100, Itai Tavor wrote:
>
>Ok... I think I get the "Specialist per role, not per class" part. 
>But I still can't make the jump from a class diagram to a 
>ZClass/Specialist setup.

A class diagram contains all the roles - they're the lines between the
classes.  :)

Look at it this way...  if an object has a particular association role that
it needs filled, and there is more than one kind of object that can fill
that role, then presumably those objects must all implement a certain
interface, right?  You need to create a Specialist for that interface.

In other words, there is usually one Specialist per collaboration interface
-- which is NOT a one-to-one mapping with classes, since some classes may
implement multiple interfaces, and some classes may all implement the same
interface.


>I can solve some of it by subclassing ZClasses. So, if I need 
>Customers and Resellers, I'll make a Specialist for each, and a 
>Customer and Reseller ZClasses, both subclassed from Person which 
>stores common properties for a person. This part is ok. 

What *role* do Customer and Reseller objects play in your system?  It
sounds to me like perhaps they play the role of "thing that places orders"
or "thing that orders are shipped to".  Depending on your application's
functions, you could need as many as FOUR specialists:

Customers
Resellers
BillableEntities
ShippingDestinations

Where the latter two specialists would contain a pair of Racks that mapped
back to the Customers and Resellers specialists, respectively.


>But it gets 
>more complex than that. Take this example: Every OrderLineItem object 
>can have one or more Payment objects associated with it. There are 3 
>possible payment types - Check, Charge and BankDeposit, so I make a 
>ZClass for each one, all subclassed from a general Payment ZClass. I 
>create one Payments Specialist with 3 Racks. Where do I store methods 
>that are specific to one payment type? In the Rack? I can't store 
>them in the Specialist - it would be a mess, and I can't store them 
>in the ZClass, because the ZClass doesn't know about the rest of the 
>application. 

Huh?  What do you mean by "methods that are specific to one payment type"
in this context?  What do payments do that requires knowledge of the rest
of the application?  If it's a problem-domain method, it belongs in the
ZClass.


>Actually, writing this down makes me realize that it 
>could work... would Payments.getItem(some_payment_id).someMethod() 
>call someMethod in the Rack if one exists, and the one in the 
>Specialist if not?

No.  DataSkins acquire only from the Specialist, not the Rack.  However,
you can use ClassExtenders in the Rack to provide methods to an object.
But you *can't* override methods that already exist on the ZClass.  This
should not ordinarily be an issue since you should only be doing problem
domain methods on your ZClasses anyway, and there should be no need to
override them.


>Another problem I'm having is how to store id's for different objects 
>in the the same field. In the Payments example above this is not a 
>problem, because all payments are supplied by the Payments 
>specialist. But what about another example - Customers and Resellers 
>are two totally different roles, so they each get a Specialist. the 
>Payment object has from_id and to_id fields, and each of those can 
>hold the id of a customer or reseller, or some special code to 
>indicate the store. I could add from_type and to_type fields, or I 
>could prefix the id with a code letter, but neither seem like a good 
>solution. Is there a recommended approach for solving this problem?

See above, where I mention BillableEntities and ShippingDestinations.
Having only one specialist per role means that you never have to worry
about ambiguous identities.

Please note, however, that at this stage of design you shouldn't be looking
at how the references are going to be stored.  At the abstract design
stage, you would just have "Payor" and "Payee" attributes that are the
actual related objects.  When you write your SkinScript later, you can set
up how the linkages work, using ID fields, or SQL columns, or whatever.