Hello all,
I am quite new to the OO world, I have been working with .NET for about a year and most of the work I have done with it has been procedural in nature. I got the Expert Business Objects book and am trying to change my thinking to fit OO programming.
I have a rather general question with a mock application I'm trying to develop with CSLA.NET. I have come up with a mock use case based on the company I work for. In trying to layout the object design I've come across a problem and want to make sure I'm going down the right path.
My design has several root objects.
Vendor, Customer, Driver, Plant, Contact
I also have a class called Address. Each one of the above objects exhibits a has-a relationship to the Address class. Further Vendor, Customer, Plant also have a has-a relationship to the Contact Class.
In the book Rocky talks about normalizing behavior, so my thought is that the way I have this setup is correct, however he also advises against overly complex relationships so this gives me pause. The mock application isn't going to be used for anything, but I would like to understand and make sure I am learning the design process correctly.
Anyone out there have a similar problem/solution? Am I heading down the right path? Any advice would be greatly appreciated.
Thanks,
Justin
On the surface it sounds like you are analyzing your objects based on data relationships - which is something to avoid.
As a specific example, you note that Plant has-a Contact. While that is most likely a valid data relationship, it is only meaningful in your object model if you have a use case where that matters.
In other words, objects come into being through a use case that requires them, not just because there's some data that exists in the database.
So you might have an "Edit Plant Profile" use case. And in that use case the user may be editing the plant information, and as part of that information there's a contact for the plant.
But the use case also needs to define how the user associates a contact with the plant. Do they enter the contact info directly? Or do they choose the contact from a list of existing contacts? Or both? And if they can choose the contact from a list, do they need the ability to add a contact if it isn't in the list? And if THAT is the case, then you have the scenario where one use case links to another - because you can be sure that "Add a Contact" is its own use case, with its own objects.
What I would expect to see out of this are objects like this:
"Edit Plant Profile"
Plant<-BusinessBase (root)
PlantContacts<-BusinessListBase (child)
PlantContact<-BusinessBase (child, probably display-only)
"Add a Contact"
Contact<-BusinessBase (root)
The responsibilty of Contact is to enter/edit valid contact data. The responsibility of PlantContact is to indicate an association between a plant and a contact. Different use cases, different responsibilities and thus different objects/classes.
Rocky,
I think you're exactly right, looking back at it I am looking at my data relationships and trying to base objects off of them, I'm trying to get myself to stop doing this (it's a lot harder than it sounds)
Looking at the object model you describe, I would then look at Vendor, Customer the same way even though those contact objects are identical? So I would have a Contact class and then in Vendor for instance I would have
"Edit Vendor Profile"
Vendor<-BusinessBase (root)
VendorContacts<-BusinessListBase (child)
VendorContact<-BusinessBase (child, probably display-only) so on and so forth with all of my objects that have a has-a relationship to the Contact class?
Then there is the question of Address class. I suppose the same would hold true but since the circumstance is a bit different I want to make sure I'm doing this right.
The use case says that all Entities (Vendor, Driver, Plant, Contact etc.) will have an address that is unique to that Entity. Further on most entities (Driver is the exception here) will have at least one contact, the address of a contact may or may not be the same as the entity address.
So I would have another use case "Add a Address"
Address <- Business Base (root) then in the case of a Vendor
I would modify the above by adding VendorAddress class.
Again working to normalize the behavior here since an Address is always the same set of variables Street, City, State etc. or should I look at this like normalization in the database where you can end up overdoing it and add too much complexity? I could for instance just add the Street, City, State properties to the Vendor since there isn't a collection of addresses.
Again I appreciate the input
Justin
Justin,
Here is my 2 cents. If you don't have a collection of Addresses to maintain for a Vendor, then you are better off adding the Street, City, State etc properties to the Vendor object. Same holds true for other objects like Driver, Plant etc.
Cosmic Ovungal
If Vendor and Customer are the same class, you only have one class. Address is a separate class. Do not place the address data into the Vendor or Customer class. A class should only encapsulate one set of cohesive behaviors. If you placed the Address information into the Vendor class, the Vendor class would be responsible for the behavior of a Vendor and an Address. Splitting them up will make your code more cohesive and flexible.
IMHO, your database structure shouldn’t really dictate you object structure. This makes your design tightly-coupled with the database. Deciding whether you should include the address properties in the Vendor class based on the number of address tables you have, doesn’t seem like a good idea to me. All addresses will share some behavior and that behavior doesn’t belong in the Vendor class. Each class should only encapsulate one set of cohesive behaviors. Adding the address properties to the Vendor class violates this. Further, this also violates the single-responsibility principle. The Vendor class would have two reasons to change.
To be honest, I can see it both ways.
The Address (in this mock design) is a 1:1 relationship with any other object, a Vendor can have 1 and only 1 address, a Contact can have 1 and only one address. It I wanted to do some specific validation on the address I could see having it in another class, however I can also see it as just a simple property of an object.
All of my objects Vendor, Customer, Plant etc. Have a Name property, I don't try and break this out into a separate class because it's simple property of an object, so I can see it both ways.
I would like to say thank you to everyone who responded. I appreciate all the input.
BTW Rocky, Thanks for the book it's an incredible resource even if it does take a little while to get through my thick skull
Thanks again to all,
Justin
From: malloc1024 [mailto:cslanet@lhotka.net]
IMHO, your database structure shouldnbt really dictate you object structure. This makes your design tightly-coupled with the database. Deciding whether you should include the address properties in the Vendor class based on the number of address tables you have, doesnbt seem like a good idea to me. All addresses will share some behavior and that behavior doesnbt belong in the Vendor class. Each class should only encapsulate one set of cohesive behaviors. Adding the address properties to the Vendor class violates this. Further, this also violates the single-responsibility principle. The Vendor class would have two reasons to change.
I am interested in how this will affect the data access portion of it. If we encapsulate the rules for this Address object, will the Parent object be in charge of saving the address information, whether that be in an global Address table or not? If all addresses are saved in the same table, then the update/insert data access would be in the Address object. If all addresses aren't saved in a specific table, then would the Address object have to do something like :
From: MichaelBosch [mailto:cslanet@lhotka.net]
Sent: Wednesday, May 31, 2006 5:22 PM
To: rocky@lhotka.net
Subject: Re: [CSLA .NET] RE: OO design
If Me.Parent.GetType = Vendor
then save here,
else
save there...
I guess what I'm asking is whether the parent is in charge of saving the address information or the address itself because this address looks like a 1/2 business object 1/2 data structure mutant. I know objects should not be defined by data, but.. uhmm.. how do I save it?
Hi Rocky. I've just found this old post and one question comes to my mind. In the case of embedding the [Address] BO as a property of the [Vendor] BO, how do you bind the [Vendor].[Address].[..properties..] in the UI?
Troncho
I agree. If you are only normalizing data, you could place the address properties in the vendor class. However, addresses usually contain address specific behavior. This is why I suggested using an address class, to separate behavior. Using an AddressRule class is a good idea because it encapsulates the address specific behavior. I have used similar classes in the past and they have worked out well. As long as the address behavior is encapsulated in its own class, you should have a good design.
Copyright (c) Marimer LLC