oopinheritanceenumsdomain-driven-designdomain-model

Inheritance vs enum properties in the domain model


I had a discussion at work regarding "Inheritance in domain model is complicating developers life". I'm an OO programmer so I started to look for arguments that having inheritance in domain model will ease the developer life actually instead of having switches all over the place.

What I would like to see is this :

class Animal {

}

class Cat : Animal {

}

class Dog : Animal {

}

What the other colleague is saying is :

public enum AnimalType {
    Unknown,
    Cat,
    Dog
}

public class Animal {

    public AnimalType Type { get; set; }

}

How do I convince him (links are WELCOME ) that a class hierarchy would be better than having a enum property for this kind of situations?

Thanks!


Solution

  • Here is how I reason about it:

    Only use inheritance if the role/type will never change. e.g.

    using inheritance for things like:

    Fireman <- Employee <- Person is wrong.

    as soon as Freddy the fireman changes job or becomes unemployed, you have to kill him and recreate a new object of the new type with all of the old relations attached to it.

    So the naive solution to the above problem would be to give a JobTitle enum property to the person class. This can be enough in some scenarios, e.g. if you don't need very complex behaviors associated with the role/type.

    The more correct way would be to give the person class a list of roles. Each role represents e.g an employment with a time span.

    e.g.

    freddy.Roles.Add(new Employement( employmentDate, jobTitle ));
    

    or if that is overkill:

    freddy.CurrentEmployment = new Employement( employmentDate, jobTitle );
    

    This way , Freddy can become a developer w/o we having to kill him first.

    However, all my ramblings still haven't answered if you should use an enum or type hierarchy for the jobtitle.

    In pure in mem OO I'd say that it's more correct to use inheritance for the jobtitles here.

    But if you are doing O/R mapping you might end up with a bit overcomplex data model behind the scenes if the mapper tries to map each sub type to a new table. So in such cases, I often go for the enum approach if there is no real/complex behavior associated with the types. I can live with a "if type == JobTitles.Fireman ..." if the usage is limited and it makes things easer or less complex.

    e.g. the Entity Framework 4 designer for .NET can only map each sub type to a new table. and you might get an ugly model or alot of joins when you query your database w/o any real benefit.

    However I do use inheritance if the type/role is static. e.g. for Products.

    you might have CD <- Product and Book <- Product. Inheritance wins here because in this case you most likely have different state associated with the types. CD might have a number of tracks property while a book might have number of pages property.

    So in short, it depends ;-)

    Also, at the end of the day you will most likely end up with a lot of switch statements either way. Let's say you want to edit a "Product" , even if you use inheritance, you will probably have code like this:

    if (product is Book) Response.Redicted("~/EditBook.aspx?id" + product.id);

    Because encoding the edit book url in the entity class would be plain ugly since it would force your business entites to know about your site structure etc.