Why prefer composition over inheritance
In the context is managing pluggable behavior, two possible alternatives are using an abstract class with an abstract method and plug the functionality by subclassing and implementing the method (in Java-land called a template-method), the other is defining an interface (usually a SAM, or Single Abstract Method interface) and passing it to the dependent class (or buzzwordizingly, injecting it). Which is preferrable?
The story begins
Suppose you client runs a bakery, so you are pretty tired when you arrive to the meeting at 4:30 AM (just before putting the first rolls on the assembly line) and you take note of the following procedure:
- prepare ingredients
- bake the bread
- check quality
- put the bread on display
The client tells you there are many ways to bake various breads from different ingredients, and that he wants to see your model working by the next day (btw you can meet at a more convenient time like 5:00 AM if you would like). So you go home, switch on the computer, launch the text editor and fall asleep. After waking up, you stare into the glossy screen and see the reflection of a familiar keyboard pattern imprinted into your forehead. You decide you need coding right now, so you take a shower and start browsing through emails go ahead. You sketch up two alternative ways to model. First:
And the other one:
No big difference. A faint voice in the back of your head tries to whisper “use fun..” but you think it is fun enough to sleep for now. Next day you present the first model to the client who is pretty happy and tells you about his vivid dream about the next best thing after sliced bread: Boxed bread! Bread that is put into various neat little paper boxes. He wants you to model an extra phase of postprocessing the bread once it is quality-checked, like slicing or boxing it. He also gives you a full bag of rolls free of charge. You go home, have some bites, try to smear the keyboard imprint away after waking up and sit down to code. First you take the presented model and start hacking it:
By now you realize that the baker will probably beat you with the shovel if you hand off the result, and that programming was a wrong choice of career and you would rather tend poultry if could start again. As a last resort you dig up the alternative model from yesterday and start extending that:
Wow, much better! You could reuse the bread baking strategies as-is, and could add the orthogonal concept of post-processing with ease. Aftern a good bit of snoozing, you present the results next dawn and get a nice bag of rolls again. You know that the job is done and is done right, so you set out to leave, when the baker tells “I’ve got a new assignment for you! I would like to make a killer feature, boxed sliced bread!”. You faint on the spot, and when you wake up… that’s to be continued.
Template methods are not inherently bad and in the current context might be a viable solution if the language supports mixin composition. However for now we will continue the path pawed by the solution using injection and Strategies in future posts, and may revisit mixin composition at a later time.
Update: See also the relevant item from Effective Java, Item 16: Favor composition over inheritance.