Use BusinessBase for both base and derived classes

Use BusinessBase for both base and derived classes

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


Frances83 posted on Thursday, July 23, 2009

Hi all,

I apologize in advance if this question has been asked before on this forum, but I couldn't find it Smile [:)]

I have the following situation (as a simplified example):

In our app we have to support addresses for several countries, i.e. New Zealand, Australia etc. The addresses largely consist of the same properties, so we have a base class called BaseAddress which has properties like Country, City and ZipCode. The NZ address (NZAdress) derives from BaseAddress and has some extra properties of its own, like Suburb.

Now we're integrating CSLA .Net in our app, and I'm trying to refactor the Address-classes. Ideally, what I want is that:


I know the last is not possible, since .Net doesn't support multiple inheritance, but I'm wondering if there's a clever trick in CSLA .Net to work around this?

Thanks in advance for your reply,
Frances83


SonOfPirate replied on Thursday, July 23, 2009

Not sure I follow the request.  By deriving NZAddress from BaseAddress, it does inherit BusinessBase so you do get the benefit of all behaviors in that class plus polymorphism which will allow you to type your variables and references as either BaseAddress or BusinessBase.  Is there something else you are trying to accomplish?

If you are looking to strongly type the generic BusinessBase methods to NZAddress, then let me suggest this: 

This will allow you to strongly type BusinessBase and allow polymorphism through the AddressBase class.

If this isn't what you were after, please explain.

 

Frances83 replied on Thursday, July 23, 2009

SonOfPirate:
By deriving NZAddress from BaseAddress, it does inherit BusinessBase so you do get the benefit of all behaviors in that class plus polymorphism which will allow you to type your variables and references as either BaseAddress or BusinessBase.


Hi SonOfPirate,

Thanks for your response. Let me explain further. What you said in the above quote I tried to use as well. My BaseAddress class looked like this:

    [Serializable()]
    public class BaseAddress : BusinessBase<BaseAddress>, IAddress
    {
        public static PropertyInfo<string> countryProperty = RegisterProperty<string>(c => c.Country, "Country", String.Empty);
        public static PropertyInfo<string> addressProperty = RegisterProperty<string>(c => c.Address, "Address", String.Empty);
        public static PropertyInfo<string> cityProperty = RegisterProperty<string>(c => c.City, "City", String.Empty);
        public static PropertyInfo<string> zipCodeProperty = RegisterProperty<string>(c => c.ZipCode, "ZipCode", String.Empty);

        // All the rest of the implementation etc
    }


And my NZAddress like this:

    [Serializable]
    public class NZAddress : BaseAddress
    {
        private static PropertyInfo<string> addressLineTwoProperty = RegisterProperty<string>(c => c.AddressLineTwo, "AddressLineTwo", String.Empty);
        private static PropertyInfo<string> suburbProperty = RegisterProperty<string>(c => c.Suburb, "Suburb", String.Empty);
       
        // All the rest of the implementation etc.
    }

The problem here being that in NZAddress I would get the error: 'BaseAddress' does not contain a definition for 'AddressLineTwo' and no extension method 'AddressLineTwo' accepting a first argument of type 'BaseAddress' could be found (are you missing a using directive or an assembly reference?)

So if I derive my class from a class which implements BusinessBase, I can't add PropertyInfo objects to the derived class! Which is a bother Wink [;)]

Frances83 replied on Thursday, July 23, 2009

I am tired... Whole problem fixed by just using a different way of registering the properties... This works:

private static PropertyInfo<string> addressLineTwoProperty = RegisterProperty<string>(new PropertyInfo<string>("AddressLineTwo", "AddressLineTwo", String.Empty));

        public string AddressLineTwo
        {
            get
            {
                return GetProperty(addressLineTwoProperty);
            }

            set
            {
                SetProperty(addressLineTwoProperty, value);
            }
        }


Thanks for the eye opener Smile [:)]

dlambert replied on Friday, July 24, 2009

I think if you're going to do this, you might want to consider having:

* BaseAddress
* NZAddress : BaseAddress
* Address : BaseAddress

This last class will end up being essentially an empty shell, but you'll then have a good way to handle departures of your two concrete classes (this is bound to happen at some point).

lucafontanarosa replied on Tuesday, January 19, 2010

public abstract class AddressBase T : BusinessBase T where T:BusinessBase T


then you can do all you were saying you couldn't do.

skagen00 replied on Wednesday, January 20, 2010

You may have a case where you need to have separate descendents for each different address format, but that could get problematic too.

I don't know if you've ever seen this:

FRANK'S COMPULSIVE GUIDE TO POSTAL ADDRESSES
http://www.columbia.edu/kermit/postal.html

Is the number of countries you need to support open-ended or pretty well defined?

p.s. there are really good resources out there for phone numbers, too, if you need to handle that. A globalized "phone number" solution is really quite easy to implement. Addresses, not so much.

whelzer replied on Wednesday, January 20, 2010

Personally I would just create seperate distinct classes for all your use cases.
If you end with NZAddress, AusAddress, IreAddress, etc so be it.  It might seem like a good idea to have a base class but what does it really give you  - a few properties that you would most probably code gen in about a nanosecond?  Generally speaking by having BaseAddress you'll end up with code that is harder to maintain. You'll probably end up with props/methods that not all inherited classes need and a bug in there will flow down to all your classes.  Rocky and others has explained  this much better in previous posts.

In our early csla days we made the same "mistake" with baseInstrument (BB) and now have around 9 classes inheriting from this, it gives me nothing but trouble (and a few properties)... eg I get a requirement for a new piece of data, it is common to 4 instruments do I put in the base or just those that need it.  It gets worse when you consider validation rules, authorisation, the DP etc.  Not saying it can't be done but unless there is a clear business resason to do it I wouldn't bother..  

skagen00 replied on Wednesday, January 20, 2010

If this is meant to be a solution that can support international addresses in general I really don't think separate classes for each country is a good idea.

My two cents

skagen00 replied on Thursday, January 21, 2010

Someone posted a question. People are giving answers. Don't you think by asking a question the developer is soliciting suggestions? It seems like using inheritence is a primary aspect to the question.

If with every country you're creating a new class - something isn't quite right. But that said, if the realistic universe of countries is somewhat defined, then it's probably not a big deal. It sounds like that's the direction the developer was leaning - so be it.

If a sampled purpose of separate classes per country would be to have a postal code property for Canada versus a zip code property for US with a validation rule on each for format & length, for example -- that can be done by having a postal code property on a single class, with a regular expression for each country (country as an aspect of the address) to validate a postal code along with some sort of description on the country as to what its referred to.




dlambert replied on Thursday, January 21, 2010

FWIW, I've used inheritance with CSLA classes with great success. As others have mentioned, it's important to understand whether you're adding complexity or removing it by using inheritance, and that's going to vary greatly based on the design of each individual application.

Personally, I'd be a little wary about a design where I've got a class per country, whether they're inherited or not -- I can envision scenarios where that makes sense, but I'd expect them to be rare.

Copyright (c) Marimer LLC