In trying to learn OO, I'm having a bit of trouble figuring out the right way to access classes in a composition hirearchy. Consider the following: Client HAS A Project(s) HAS A Task(s). I've read that the proper way to access the Project(s) associated with
a Client is to create an instance of the Client class and then call something like myClient.GetProjects() instead of creating an instance of the Project class and then calling something like ClientProjects[] = myProject.GetProjects(Client_ID) as the project
class should only be aware of itself. I think I can see that. What I cannot see is the correct way to either get or set TASKS associated with a Project - this is 3 deep in the composition hirearchy. How would I set or update a task for a project in this scenario.
Is it wrong to go straight to the task class and set it's properties and passing a Project ID to the constructor? This would seem to create coupling between the task and project classes. Is this degree of coupling OK at this level? or do I do something like:
ClientProjects[] = myClient.GetProjects(); ProjectTasks[] = ClientProjects[3].GetTasks(); ProjectTasks[3].EndDate = NewEndDate; So in this sense I'm still accessing the Tasks by drilling down through the hirearchy and am not creating coupling by associating
a task class to a project via a project ID in the Task constructor? On top of this, the classes (Project and Task) will need to have public methods/properties for the above to work. Is this right - or should they only ever be accessed via the Client class
... which brings me back to how do I then access the Task class? Confused! This is probably elementary to most of you, so I apologize for that. Just trying to get a handle on it! Thanks, AKM
All that you've said is correct! It all depends on what you want to do :) "I've read that the proper way to access the Project(s) associated with a Client is to create an instance of the Client class and then call something like myClient.GetProjects() instead
of creating an instance of the Project class and then calling something like ClientProjects[] = myProject.GetProjects(Client_ID) as the project class should only be aware of itself. " Humm, i think you are mixing things. "myClient.GetProjects()" Correct "myProject.GetProjects(Client_ID)"
Wrong. But "myProjectMgmtComponent.getProjectByClient(Client_ID)" Correct. The point is in "Components" you put methods that allow the user to query the Business Layer for objects collection or root object, that is initial objects from to which all other required
objects are connect. "Is it wrong to go straight to the task class and set it's properties and passing a Project ID to the constructor?" Again, no. It is not wrong or right. If you get an object of type Task and if eventually the task knows that the objects
it is grouped in, then when you change its state the Task object can "notify" the Project of state changes. "This would seem to create coupling between the task and project classes." You will always have coupling I believe, either if when changing a task state
you do it through the aProject or aTask (either way aProject will/should be called). Suppose that you change the date of task in such way that it overlaps another task, the object that should validate these "overlaps" is the Project object I think. "So in
this sense I'm still accessing the Tasks by drilling down through the hirearchy and am not creating coupling by associating a task class to a project via a project ID in the Task constructor?" You could have "aProjectMgmtComponent.getTasksByProject(projectID)".
"Is this right - or should they only ever be accessed via the Client class ... which brings me back to how do I then access the Task class? Confused!" People get confused when it comes to aggregation. Basically it comes down to programming style. If you allow
the caller to access aggregated items then you should do it across all development. If not, then you should have a policy stating the rules to decide to opt for one or another. For instance aOrder and its orderLines (orderlines is not even a clear business
object). Clearly a very strong aggregation so basically one could sat to this kind of aggregations allways call aOrder to set and update orderlines. Now when as for Task is too strong of a concept to do it in this way I believe, but then this is a very fuzzy
concept. I Suggest you read "Streamlined Object Modeling" book as it explorers different kinds of aggregations and they can be coded. Nuno
Nuno: Many many thanks for your reply - VERY clear!! I will certainly look at the book you mention. I guess I was becoming increasingly confused by the notion of whether or not to make my classes inaccessible via "internal" and have them in their own namespace
with only a top-level class as publicly accessible. The notion that some degree of coupling is neither avoidable or necessarily "bad" makes the whole picture much clearer. Thank you! AKM
One more thing, If you really care to make tasks and projects somewhat reusable, I sould add another class called Calender (just like Outlook). Then add or remove events from the calender. So you could have event (something that happens during a period of time).
Then a ProjectTask could be a role of the event participating within the scope of a Project. Say: Calender [1:N] Event Event [1:1] ProjectTask (note, not sub classing :) ProjectTask [N:1] Project Just some ideas, it all depends on what you want to do. Just
to point out that a task generically speaking does not belong to a project, so coupling is needed one way or another if you have business rules that force the coupling between a task and the project. You could add other kinds of tasks or even a specific event
could participate in more then one type of collaboration (SoftwareProject Collaboration and ProductMgmtProject). One could have several kinds of Projects etc etc. Nuno PS: Anyway focus on what you need to build, neither more or less. As you can see there are
sevarl ways to tackle reusability later on when the time comes.
I like the idea of a top-level broker that you mentioned. I'm presuming that this would be resposible for getting me an instance (or array) of objects depending on what type I'm after aka a Factory Pattern. My question is this: The broker would pass me an instance
of a Client object that I specifically request - myClient = Broker.GetExistingObject(Client, Client_ID) (or some such method). Do I then use the Client object to get a NEW instance of project class like myProject = myClient.GetNewProject(), populate the Project
object and then call an update method in the Client object like: myClient.SetProject(myProject). Or should I use the Broker to get me a new instance of the Project class and then call a SetProject method within the Client object. Thus, the Client object is
responsible for updating a Project associated with it, but not responsible for retrieving a Project object instance? Or does it even matter?!! Thanks again - your comments are VERY much appreciated. AKM
ell, all I can say you is how I would model it, and this basically is code for the EntityBroker :-) ::EntityManager em = ...... (this is the broker). Finding ::Client c = (Client) em.Get(typeof(Client), primarykey); alternative - with some nam instead of the
key ::Query q = em.CreateQuery (typeof(Client), new Condition ("ClientKey", Expression.Equals, ::whateverkey); ::Client c = (Client) em.FindScalar (q); Next is getting the NEW project. This would normally look like this: :_Project p = (Project) em.Create (typeof(Project));
::p.Client = c; ...more configuration... This CAN be a little painfull. So it does make sense to put this into some helper. Now, where you make this is your thing. It can be in the Client: ::Project p = c.CreateNewProject (parameters); but this would be a
convenince method. Basically taking the parameters, and then creating the object and also configuring it. Makes it easier to create the complete object in a state that is usable right from the start. This is absolutly your choice. I would prefer to have this
in the client, as a method. OTOH, for form flow it does not make a diference, and collecting the parameters first (to call the method) is harder than creating the object and thn use databinding and a form to ENTER the data. Harder simply because it is additional
- you need the databinding way anyway for editing, but then you need a SECOND code path for creation. OTOH, you can always have the convenience method and use the generic broker based approach when forms get involved. This is all about style and standards
:-)
Thona: Thanks for your response. Between you and Nuno, I'm beginning to like the idea of a Broker class more and more to handle the getting of objects. From there, I can see using the objects themselves to handle setting values and conducting all the necessary
business logic. I'm certainly not at a point where I either need or would even understand an O/R mapper ... but I like the idea! Nuno suggested a book that looks rather good and I will buy, is there another one that you would suggest looking at? Many thanks,
AKM
If you want to apply the concepts of the book and have "easy" persistance of those objects you definitly need an O/R Mapper. "Nuno suggested a book that looks rather good " The book is EXCELLENT! All the questions, doupts, etc you may have regarding OOM and
Implementation this book answers them in a practical manner. It can make anyone look and be really smart, faster within this scope. Nuno
A.K.M
Member
65 Points
13 Posts
Using OO composition
Dec 02, 2003 07:32 PM|LINK
nbplopes
Participant
1745 Points
349 Posts
Re: Using OO composition
Dec 02, 2003 07:59 PM|LINK
A.K.M
Member
65 Points
13 Posts
Re: Using OO composition
Dec 02, 2003 09:03 PM|LINK
nbplopes
Participant
1745 Points
349 Posts
Re: Using OO composition
Dec 02, 2003 10:33 PM|LINK
A.K.M
Member
65 Points
13 Posts
Re: Using OO composition
Dec 02, 2003 11:56 PM|LINK
thona
Member
20 Points
2923 Posts
Re: Using OO composition
Dec 03, 2003 03:21 AM|LINK
A.K.M
Member
65 Points
13 Posts
Re: Using OO composition
Dec 03, 2003 04:10 PM|LINK
nbplopes
Participant
1745 Points
349 Posts
Re: Using OO composition
Dec 03, 2003 04:42 PM|LINK
A.K.M
Member
65 Points
13 Posts
Re: Using OO composition
Dec 03, 2003 05:13 PM|LINK