11 Mar 2012

Composition versus Inheritance?

Composition versus Inheritance? When designing components and classes, it's a question that always pops up and seems to stir lots of emotions regarding which is the best approach to take. The question is why? Composition and inheritance shouldn't be seen as competing best practices because they have two very different roles to play in design.
Favor 'object composition' over 'class inheritance'. GoF
It's a term heard many times over and it has a very valid point. Unfortunately, it is a single line taken out of a three page summary that is part of a larger section describing design patterns and reusable software. Composition definitely provides greater flexibility and encapsulation. You can change the implementation without affecting your API, however it does result in a slightly more complex system. Inheritance does provide a more simplistic approach to design but exposes your parent API, meaning that your are forever stuck with being a child to that parent. So what happens when you are creating a design that is unlikely to change in the future? Like choosing a language that is best fit for the job, have a look at your problem and choose what solution fits best.

Deciding on whether design using composition or inheritance can be difficult choice, but answering the following questions can sometimes shed some light on the correct path.
  1. Are you creating or extending a piece of functionality or are you trying to describe a structural piece of information?
  2. If it is a structural design, how complex is that design and is it likely to undergo some frequent major changes over the next few years?
What the questions above are really trying to get at is, are you describing something that is unlikely to change or are you defining how something works? For instance, if you were trying to create a model for animals, using inheritance over composition might make more sense. It would be a nightmare to try and describe the below class diagram using composition. The fact that a tiger is a mammal is unlikely to change in any of our lifetimes (unless there is some freak nuclear war that mutates them, fingers crossed it's something cool). The fact that a tiger is a cat and a cat is a mammal is also unlikely to change. With inheritance the below class diagram would be relatively simple to represent as opposed to composition.
What would happen with the above structural design with generics and grouping via parent types if we were to use composition? If you wanted to perform the following:
public List<Tiger> getTigers(List<Mammal> mammals) {
 // some code
}
the composition design would require you to define a tiger in the following way
public class Tiger implements Cat, Mammal, Animal {
 // some code
}
and use object delegation to provide implementations for the interface methods. This is clumsy and inefficient for something that, truly, will not change. Whilst you may think this scenario is too far fetched, then what about describing your POJO classes for your presentation layer? I have recently worked with a web app where the structural design was described using inheritance and it worked really well for what was required. I could not have imagined doing it using composition.

So should we always use inheritance? Of course not. When creating or extending functionality, composition will generally be a better option. A real world example where composition should have been used instead of inheritance? java.util.Properties. I bet this is one example where the JDK developers would be kicking themselves now. java.util.Properties extends java.util.Hashtable. In what world does a Properties file have anything to do with a Hashtable apart from the fact that they are both key value. It made life easier during the development stage however they are forever stuck with being a Hashtable now, even though I am sure they would love to change it to something else. On top of that they have left the Hashtable API exposed, meaning that you can directly modify and add items to the hashtable without going through the Properties API. Properties are traditionally a string based class, however it's possible to add any object to the hashtable meaning that the Properties.getProperty(String key) method is forced to do the following
public String getProperty(String key) {
  Object oval = super.get(key);
  String sval = (oval instanceof String) ? (String)oval : null;
  return ((sval == null) && (defaults != null)) ? defaults.getProperty(key) : sval;
}
That's right, check every item to ensure it is of type string. How ugly. If Properties were designed using composition
public class Properties{
  private Hashtable properties;

  public String getProperty(String key) {
  // some code
  }

  public void setProperty(String key, String value) {
  // some code
  }
}
it would have been so easy to swap out the internals
public class Properties{
  private HashMap properties;

  public String getProperty(String key) {
  // some code
  }

  public void setProperty(String key, String value) {
  // some code
  }
}
and the problem of the "place anything in the Properties implementation" goes away.

So when you are deciding on whether to use composition or inheritance, ask yourself are you creating functionality or describing something?

3 comments:

  1. Nice example on the Properties class.

    I don't think the Animal hierarchy is a good example of your point though.

    It seems to me that the inheritance is only modelling one aspect of the classes (species) which provides some small benefit when you're using it in that particular way, such as a getTigers() method.

    But tigers are multi-faceted creatures. What happens when you want to do getOrangeAnimals()? You're back into compositional territory, since you can't have multiple inheritance and therefore can't represent both species and colour in a hierarchy. And again for getCarnivores(), getDomesticatedAnimals() etc.

    It depends a lot on context of course, but I'd tend to favour consistency over a single-case simplicity - especially when that simplicity is known to come with added coupling.

    Perhaps it's not such an issue on the presentation layer, where all objects are created to serve a single purpose, but I do think you need to consider the risk, inflexibility and possibly even technical debt you introduce with a large inheritance hierarchy.

    ReplyDelete
  2. Context is definitely a major factor in deciding whether or not you should implement via composition or inheritance.

    In saying that, why would you have any methods like getOrangeAnimals(), getCarnivores(), getDomesticatedAnimals() within a Tiger class? It doesn't really seem to fit and you begin to lose focus as to what the Tiger class is for. A Tiger shouldn't really know or be able to get any other orange animals. Having something like getColour() would prove to be more useful and having other services to collate Orange animals. However, I do get your point and you need to way up simplicity versus complexity. The point is when you know your structure won't change for two years, what is better to have simplicity or complexity.

    ReplyDelete
  3. Those aren't on the Tiger class, they're the equivalent of your getTigers() method (which obviously isn't on the Tiger class!).

    A getColour() method would definitely be better - but that's composition rather than inheritance. You could make the same argument for getSpecies() instead of the hierarchy.

    ReplyDelete