Hi Steve, Steve Spicklemire wrote:
Hi Itai,
"Itai" == Itai Tavor <itai@optusnet.com.au> writes:
Itai> I'm already using globally unique ids, but still, doesn't Itai> using the same id for the Participant and the Actor make Itai> these objects too tightly coupled? Seems to me that Actors Itai> should provide an interface for finding actors to the rest Itai> of the application; other objects should not make Itai> assumptions about the internal storage of Actors, and Itai> particularly what ids they use. No?
Well... there are two aspects here: 1) Who knows about how various Participants and Actors are managed and 2) How are they actually managed. Tight coupling is only about "1". It seems to me that "2" is up to you as the developer to decide based on the particular situation.
I'm sure that ZPatterns Zen is like most things... you learn by getting your fingers burnt ;-). However it seems to me that it should be OK for an Xs Specialist to implement
getXforY( y_id )
or
getXsforY( y_id )
(if there is more than one x for a single y.
If you have an XOR relationship, with several potential Specialists I think you could either:
(A) iterate through the list of possible Specialists and ask each to getXforY until you get a hit...
or
(B) have a 'clearing house' Participants specialist, with a Rack for each of the Participant types and let it iterate through the racks and return an object of the right type based on which one is a 'hit'. (Specialists of course do this automatically!)
The advantage of (A) is, one less Specialist. The disadvantage is that the Actor Specialist needs to 'know' about the list of Participant Specialists itself.
The advantage of (B) is that the clearing house Specialist keeps track of all the different Participants types... and the iteration is 'automatic'.
However... I think that either of these is 'OK' as far as coupling is concerned. In both cases the information about the different types of Participant is kept in a single centralized place [(A) in the Actors Specialist] and [(B) in the clearing house Specialist]. *If* you had some *other* Specialist that also needed to iterate through the various types of Participants... *then* B would be a clear advantage, and probably worth the added complexity.
I use (B) when some participants need to take on a certain role, like 'ordering entities', 'billable entities', etc. In this case, each role might be filled by a different group of participants, so a new Specialist is necessary. I implemented this for my Actors like you suggested, and it works nicely and doesn't seem overly complicated. In other XOR cases, I would favor (A). I think (B) in these cases would be an overkill. One thing about implementing (A) - it can be done in two ways: - Store participant_id in Actor. Actor calls ParticipantSpecialist.getParticipant(self.participant_id) - Store actor_id in the participants. Actor calls ParticipantSpecialsit.getParticipantForActor(self.id) Or, you'd probably want to do both - store Actor.my_participant_id and Participant.my_actor_id. But in this case, you don't need getParticipantForActor, you just use getParticipant(self.my_participant_id). Does this make sense?
(P.S. it was refreshing to hear pje mention that he and Ty had to "bite the bullet" and add new classes/Specialists on a project and only *after* that it got much simpler, clearly implying that the original design was less than perfect. It seems to us newbies sometimes that they possess the Deific characteristic of near (object oriented) infallibility whereby they produce clean, elegant, yet simple object oriented designs with the same graceful ease with which they might compose a grocery list, while we mortals struggle for hours and days to come up with something that they might discard after a moment's thought. Anyway.... in the end we'll all learn the most by hard experience, if only she were a more forgiving Mistress!)
Being able to get it right the second time is still close enough to infallible for me :-)
(P.P.S. I still really like your idea of codifying some of these ZPatterns techniques into a sort of gallery of ZPatterns Implementations. I'm working already on incorporating some of these into the ToDo example.)
I'd like to see what you manage to fit into the example. I think that once you get one implementation from the gallery added, and we can see that it's simple and works well in this application, we can consider it our 'recommended implementation of the moment'. P.S. I've been struggling with a problem that might get cleared up if you added it to the example: Say you want to allow a user to add a ToDo from the Deliverable screen (in addition to the existing menu for selecting existing ToDos). You could either place a 'create ToDo' form right there, using a UI snippet from ToDos, or link to ToDos.addToDoForm. The problem is how to get the id of the new ToDo into the deliverable. If you didn't store todo_ids in Deliverable, instead calling ToDos.getToDosForDeliverable(), there would be no problem. Otherwise, you'd need a addToDoInterface in Deliverable, which will call ToDos.addToDo, then add the new ToDo id to todo_ids. Or, as a third option, you could pass a method to ToDos.addToDo, and get it to call this method and give it the new id. What do you think? Want to tackle this in the example? 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"