Specilaising From a base object

Specilaising From a base object

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


REA_ANDREW posted on Wednesday, March 26, 2008


I have a base class called ContactInformation.  I then inherit from this class in CustomerContactInformation as I wish to add 2 more fields to CustomerContactInformation.

In the database I have a table called Person.Address, and another called Customer.Address .  The difference being that all common address information is stored in the Person.Address table.  Inside the Customer.Address table I have

CustomerID
AddressID
AddressTypeID

As there is a one to many relationship between customer and address.  I am struggling on the business object design for this inside the CSLA framework.

I create an abstract base class for the contact information
I inherit from this class to make the CustomerContactInformation.

With regards to the methods the base class defines, I do not want to hide them but rather declare new ones and run the base method.  Is this the correct way to go about this? 

So in the CustomerContactInformation's ExecuteFetch Block, I call base.ExecuteFetch(connection,criteria)

Is this a good way to do this, or is there a more tried and tested way of approaching this scenario?

Cheers

Andrew

JohnB replied on Wednesday, March 26, 2008

I'm assuming that both ContactInformation and CustomerContactInformation inherit from Csla? Typically with Csla you would not use inheritance between these two classes.

Per Rocky: "Using inheritance to "reuse" properties and fields is counter-productive."

Therefore, I would rethink about your objects from a single responsibility perspective.

Here are some links that may help.

Single Responsibility Principal

http://forums.lhotka.net/forums/thread/1658.aspx

Hope this helps some,
John

REA_ANDREW replied on Wednesday, March 26, 2008

It really does help, thankyou.

OK, so following on from that, can the database design can stay the same, and it is simply the business object design that should change.  So by this I mean:

I will do away with the base class for ContactInformation and simply import all fields and properties into the CustomerContactInformation class.

In the DataAccess regions I will have to interact with two tables, via stored procedures.  I cannot see a problem with this, but I would just like to confirm my thoughts with you. 

Cheers,

Andrew

SomeGuy replied on Wednesday, March 26, 2008

You can also look at the ResourceAssignment(s) and ProjectResource(s) classes (and the underlying static Assignment class) in PTracker to get an idea of how to use Interfaces and composition to create your objects.

What you would end up with is a static Address class that can handle the data access to Person.Address. You can create an IAddress interface that defines the properties required also. You would implement IAddress in CustomerAddress or CustomerContactInformation. That class would then call the static Address class to save the Address info and then call a SP for the CustomerAddress info.

That would allow you to reuse the Address class and interface for an EmployeeAddress or Supplier
Address classes. They would be just cut and paste copies of CustomerAddress for the most part.

E

 

JohnB replied on Wednesday, March 26, 2008

You're on the right path. Your database schema should not define how your objects look.

As far as the DataAccess, I don't see an issue with what you're doing.

John

tmg4340 replied on Wednesday, March 26, 2008

REA_ANDREW:
OK, so following on from that, can the database design can stay the same, and it is simply the business object design that should change.

There is nothing wrong with the database design you have.  However, there is one thing you might want to consider.

I've done designs similar to this in the past, and the one-to-many relationship between "Address" and "CustomerAddress" can be a real pain to manage.  Let's start with a Customer whose billing and shipping addresses are the same, thus generating one "Address" record and two "CustomerAddress" records.  What if they change one of them?  What if they change both of them?  What if they change one (or both) of them to another existing address in the database?  And what if that existing address is associated with a different Customer?  Similar questions arise when you have a Customer with different billing and shipping addresses that become the same.

If you intend to keep your "Address" table from having duplicate addresses in it - thus enforcing the "one" part of the relationship - the logic that you put into your stored procedure becomes a rather complex process.  What the app considers a simple update could involve deleting, inserting, or updating existing data, and probably will include more than one of those operations.  The check for existing Address data could be rather expensive as well, as you'll have to do a field-by-field check across the entirety of the address, which is a bunch of string comparisons that could include case sensitivity.  The code required to make this system work reliably is non-trivial.  And you can't do a whole lot to help manage this complexity from within your app - pretty much all of it is going to end up in database code.

I'm not suggesting that you merge your two tables.  Having a base "Address" table keeps the data in one place, which can be helpful if you have addresses in different parts of your application.  But I am suggesting you consider letting your "Address" table hold multiple records that contain the same address.  Under that scenario, while your database considers the relationship a one-to-many, in practice it becomes a one-to-one.

I realize that this has little to do with your CSLA class designs.  And perhaps you already have all this worked out on your database.  But if you don't, you might want to go back and take another look.

- Scott

REA_ANDREW replied on Wednesday, March 26, 2008

Hi Scot,

Thanks for your help on this.

Yes I do allow the possibility of duplicate addresses being input, I do not mind this.  I have an AddressID field inside the table which is an uniqueidentifier, as this is used as a foreign key inside the CustomerContactInformation combined with an AddressType etc...

Cheers

Andrew

dlambert replied on Wednesday, March 26, 2008

It sounds like this is more about composition than inheritance, but I've used inheritance with great success to implement objects that are really similar to one another.

The client I'm working with is really particular about how their DB schemas are set up, and there's a standard they follow for lookup values that's sort of a pain to work with.  First, each type of lookup value has to be in its own table rather than a master key-value table, and all lookup values tables have (in addition to key and value), a sequence number, a start (effective) date, an end (effective) date, a last-changed timestamp, and a last-changed user ID.

To make matters worse, I've seen these tables done with either strings or integers as IDs (keys), and these tables are sometimes extended to hold other values.  Needless to say, there were potentially a lot of largely repeated code in order to handle some small variances.

So I built a base class for the value and another base class for the list, and I'm derivnig concrete classes for each type of lookup value, and it's handling this stuff really well.  The value base class has a generic key type, and it handles all the standard fields, plus populating those fields from a datareader (sort of like ResourceInfo in the ProjectTracker app).

The list base class handles dataportal_fetch as you'd normally expect, with one difference.  It uses a virtual method to get the SQL command name it's going to us to get the data reader, and this method is implemented in the concrete class.  Ex:

        protected override string GetFetchCommand()
        {
            return "SelectMeetingPurposes";
        }

For a "standard" reference / lookup table, this is all I have to implement to handle a new lookup type.  When I need to extend the standard table, I add those properties in the concrete class, then override a method populate those fields, leaving the "standard" fields for the base class to populate:

I wouldn't recommend doing something like this for just a couple of classes, but in this case, this pattern is repeated many times, and it's really nice to have base functionality handled for me.

REA_ANDREW replied on Wednesday, March 26, 2008

dlambert

Thanks for your input on this, I appreciate it. :-)

Andrew

Copyright (c) Marimer LLC