views:

1695

answers:

5

While designing my objects I find composition to be a better choice from the perspective of testability. The reason being, I can mock parts of the composition structure if I need to, while running unit tests. This is not possible if I have an inheritance hierarchy.

I would like to know if others have also found this to be a reason to prefer composition. Also what other testability pitfalls did you get into because inheritance was used?

+16  A: 

I believe that the more you start to develop using design patterns, you'll find more and more often where composition is going to be favored over inheritance. I actually believe in the Head First: Design Patterns book that "Favor Composition Over Inheritance" is one of the primary design principles.

Your example of being able to mock up parts of the composition for testing is probably one of the best examples possible.

Edit: Although the basic principle in design patterns is to favor composition over inheritance, that doesn't mean that there aren't design patterns which utilize inheritance where it is needed. Another basic example is the decorator pattern, where you are coding towards an abstract superclass (although this is for type matching and not for implementing an "is-a" relationship).

TheTXI
Hmm...wish I knew why someone voted this down. If I knew a particular reason I could make an attempt to clarify or make modifications.
TheTXI
Actually, "being able to mock up parts of the composition for testing" is not a good example at all. The true reason composition makes it easier lies in the technical limitations of most mocking tools. Remove those limitations, and mocking inheritance becomes just as easy as mocking composition.Apart from that, I fully agree that favoring composition over inheritance is a good idea.
Rogerio
+6  A: 

The Gang of Four Design Patterns book is basically all about why to prefer composition over inheritance and offers many ways to do that. Some reasons:

  1. # of classes increases the complexity of the code base
  2. In many newer languages, inheritance is limited to one class, while you can compose as much as you want
  3. Base classes cannot be changed at runtime (essentially the issue behind what you are running into).
Lou Franco
What does the number of classes have to do with this? Does composition imply fewer classes than when inheriting?
Lars A. Brekken
Well maybe. The decorator pattern uses a combination of inheritance and composition, and results in fewer classes than if only inheritance had been used.
Parag
+5  A: 

It's not an either-or situation. They're not competitors.

Inheritance is rather easy to unit test, also. However, it sometimes requires mock concrete classes to test an abstract superclass.

Inheritance can easily be used improperly. Some designs look like "is-a" situations, but aren't really -- they're more nuanced. Sometimes it's really "behaves-like" where you need some kind of composition (a Strategy, for example) to separate behavior from other attributes.

S.Lott
Sounds a lot like Chapter 1 in Head First: Design Patterns, the "Strategy Pattern" where you are taught to design and code to an interface and not an implementation.
TheTXI
Great point that it's not either-or. Lately, I find myself preaching so much about composition simply because "is-a" is so often mistaken for "behaves-like" -- at least in my experience. It's good to be reminded that they each have their place.
Peter Meyer
+1  A: 

"Favor object composition over class inheritance" is actually from GoF book. This conversation with Erich Gamma describes this idea from the book.

One important pattern that requires inheritance is a template method pattern. This pattern is widely used very handy so inheritance is here to stay. Another common pattern that would use inheritance is Composite pattern. The point I try to make is that don't discount inheritance at all, but I hope it's clear from just looking at so many common APIs anyways...

grigory
+2  A: 

I think the biggest reason why composition is easier to test is that (implementation) inheritance tends to create very coupled classes that are more fragile (Fragile Base Class) and harder to test in isolation.

Inheritance definitely has its uses, but I find myself preferring composition over inheritance more and more often.

Lars A. Brekken