Design Question

Design Question

Old forum URL: forums.lhotka.net/forums/t/1279.aspx


JoOfMetL posted on Wednesday, September 20, 2006


Hi,

I have a question concerning the design of my application.

Company has an address. 
Person has a list of address.


So I have :

    Company : EditableRoot
    Person : EditableRoot
    PersonAdresses: EditableChildList
    Adresse : ??

With :

Company {

     Adresse _adresse;

}   

Is this possible ?

Thank you

ajj3085 replied on Wednesday, September 20, 2006

Yes, its possible.  The question though is do the addresses behave the same when attached to a person and company?  Address would be an EditableChild.

JoOfMetL replied on Wednesday, September 20, 2006


The object is the same.

But the stored procedures are different according to whether I insert an address for a companie or a person.

 In the same way, for a person, the Update method of adress takes in parameter the parent object (persone) and not for a company.

It would thus be necessary that I make several methods update?

skagen00 replied on Wednesday, September 20, 2006

You may consider making an interface shared by company and/or person, such as "IContact".

Then, pass along IContact as the parent object to the Address's update().

Since you need to use different stored procedures from what you say, just do a comparison on IContact such as "if (IContact Is Person)" then run your one stored procedure for persons, otherwise run the one for companies.

 

 

 

JoOfMetL replied on Wednesday, September 20, 2006


I thought used an interface but I did not know if it were the good solution

Thank you.

ajj3085 replied on Wednesday, September 20, 2006

JoOfMetL:
The object is the same.

But the stored procedures are different according to whether I insert an address for a companie or a person.


This raises a question which I often struggle with:  Is how the object persists itself part of its behavior?

More and more I've been answering that with a 'yes.'  The reason is that you may change a contact's address in such a way that it breaks the companies address.

For example, in my application, contacts have a single address.  A department could only have one.  Now the requirements have changed, and departments can have many addresses, and each address must have a Type asssigned (receiving, mailing, shipping, etc). 

I would say create two classes.  The data access for both classes can be refactored into another, internal class.  I have done this, and it seems to work much better than creating a single Address class.

Common address rules may also be refactored in this way.  You can now have two classes which share much of their code.  Maintaining each one is eaiser, because you know a change to one won't break the other, and their common code can be reused.

HTH
andy

malloc1024 replied on Wednesday, September 20, 2006

The behavior of objects can change dynamically.  Take a look at the strategy pattern and other similar patterns.  If there are small differences between two address classes, swap out the behavior at runtime for the behavior you need.  This is a much better solution than creating two separate address object because you are favoring composition and you are reusing most of the code.

ajj3085 replied on Wednesday, September 20, 2006

The problem is that a DepartmentAddress has an AddressType property, where as ContactAddress does not.  I'm not sure how that fits into the Strategy pattern.

simon_may replied on Wednesday, September 20, 2006

Andy, Is it not a contact address?

Simon

ajj3085 replied on Wednesday, September 20, 2006

In my application, a contact is a person.  Companies and departments are not contacts.

SonOfPirate replied on Wednesday, September 20, 2006

The AddressType defines the "relationship" and not the address itself.  Does the type affect how the address behaves?  Probably not because you can have the same address for different types (such as billing and mailing).

This is a situation I have run into frequently and have yet to come up with a graceful solution - how to incorporate complex relationships such as this into the design.  Should your DepartmentAddress class, with its AddressType property inherit from the common Address class so that you can take advantage of the code that already exists in that class?

And, when you change the AddressType aren't you actually changing the relationship and not the underlying address?  So, if you derived DepartmentAddress from Address, the primary key you have points to the record in your Addresses table - how do you reference the many-to-many table containing the AddressType column so that it can be changed?

Again, I've put together a couple of different solutions to this but I've never been real happy with any of them, so I'm looking forward to hearing your take on it.

ajj3085 replied on Wednesday, September 20, 2006

I agree, at the database level.

At the business level though you wouldn't (I don't think) create a class for the relationship which contains the address.  Well maybe that's one way to go.. encapuslate the address class.  Hadn't thought of that.

To dig deeper, the address type may affect behavior.  A shipping address might reject PO boxes while a billing address would not (although i admit I'm straying from my previous example).

To answer your question about how I perform the data access..

I have an AddressData internal class, which accepts classes implementing IAddress.  This handles the Address data modifications.  The DepartmentAddress BO uses AddressData to create the address record, then it goes and works on creating the row in the many to many DepartmentAddress table..  The DepartmentAddress class 'knows' about the many to many relationship.

I'm fairly happy with this solution; its kind of an extension to the solution which Rocky provides in the PTracker demo.  Of course there is much code which is similar... but i might be able to eliminate this by encapsulating a generic Address class.. an interesting idea I think.

malloc1024 replied on Wednesday, September 20, 2006

Andy,


In regard to your specific example, no the strategy pattern doesn’t work for the address type.  I was not trying to address you specific example with my answer.  I will try to address your specific example.  First, the address class should not contain logic that determines how many the parent can contain of it.  This logic doesn’t belong in the address class.  For the address type issue, there are a few ways you can approach this.  You could set the address type to all of them for a contact since the receiving, mailing, and shipping address for a contact would most likely be the same.  There are other approaches as well. This is a better than creating two classes just because one has an address type.  An address type is data not behavior anyway. An address is an address, there should not be many differences in behavior between a contact address and a department address.

skagen00 replied on Wednesday, September 20, 2006

Could you have it built in where you have a properties on your company to point to specific address instances in your collection - "ShippingAddress", "ReceivingAddress", etc?

Could have validation rules such that all four fields must have an address assigned, and default the first address of the collection to fulfill all of these roles. 

Just a suggestion!

 

 

 

SonOfPirate replied on Wednesday, September 20, 2006

You can but besides the DBA's going nuts, what if you want to add or remove a type from the app?  This approach isn't extensible - which may or may not be a problem.  Even if its not going to be used, I prefer to leave apps extensible cuz things always change.

skagen00 replied on Wednesday, September 20, 2006

I wouldn't advocate structuring the database the same way.

You'd have company, address, and companyaddress.

You'd also have addresspurpose and companyaddresspurpose.

addresspurpose would contain values of Shipping, etc.

companyaddresspurpose would have a primary key of companyid and addresspurpose, and have a foreign key to the companyaddress table. 

That way you don't have to pester the DBA if additional types get added.

 

 

ajj3085 replied on Wednesday, September 20, 2006

malloc,

I don't think I said the Address should limit how many shipping etc. addresses that a department can have.  At least I never meant to.

It seems like bad design for me for an contact address to have a type property which is not used at all.

In my database, I have a many to many table for DepartmentAddress which does what you'd expect.  This is where the AddressType is kept.  For a contact though, the AddressId (since contacts can have one and only one address in my world) is stored directly in the Person table.

I agree that AddressType is not a behavior, but I don't think having a property which does nothing is a good idea either.  What happens when setting AddressType to a certain value affects behavior?  Do you create a new class?  Or do you have a rule that checks type and say the Lines of the address for PO?  Addresses and PhoneNumbers have been pretty challenging to 'figure out' in the behavior / business object world for me.  I'd like to hear how others have handled these issues.

malloc1024 replied on Wednesday, September 20, 2006

Andy,

IMO, it is better to have a class that contains a property that you aren’t going to use than create a new class based on data.  An address class represents an address not the data you have in your database.  Two class that have the same behavior but different properties are really the same class.  If setting the address type changes behavior, you simply swap in behavior that does nothing for an object that doesn’t use an address type.


ajj3085 replied on Wednesday, September 20, 2006

Well, lets take this to an extreme.  Not an address class, but another class.  The behvior is the same in all uses of this class, but parent classes of that class only use at most a quarter of any of the properties.  Does it still make sense to use that class in all cases?

I'd love to hear from Rocky on this.  I personally don't think they are the same at that point.. after all and object is "smart data," which I think is even in his book...

Take data out of classes, and we basically are back to procedural programming, aren't we?

malloc1024 replied on Wednesday, September 20, 2006

Andy,

Rocky would probably say that this is a differnet use-case and therefore should be seperate classes.  I believe CSLA was designed with a use-case driven design in mind.  I think that a use-case driven design is different than a pure OOD desgin, although I could be wrong about that.  It seems to me that a use-case driven design doesn't promote reuse as much.  I would love to hear more about the differences beteween the two if they exist.


As far as your most recent  example I would create a class that encapsulates the common behavior in a seperate class. I would create a class for the different types.  Each of those classes would delegate its behavior to the class that contains the common behavior.  There might be a more elegant solution, but I would have to think about it more.

ajj3085 replied on Wednesday, September 20, 2006

Isn't that the solution I suggested for the orginal address problem though (DepartmentAddress and ContactAddress)? Smile [:)]

malloc1024 replied on Wednesday, September 20, 2006

Andy,

lol.  It is similar to what you suggested in the first place.  However, I am not completely satisfied with the address solution.  You shouldn’t have to create a new address class just because one address has an address type.

simon_may replied on Wednesday, September 20, 2006

That was in fact what I meant above about a "contact address" type. Probably never used but keeps the shape of the data constant. No need for a second Address type or record schema.

Simon

JoOfMetL replied on Wednesday, September 20, 2006


Thank you,

I had not thought of it.

It is a good idea and I think that I will make like you.

Copyright (c) Marimer LLC