This is why you need Composition over Inheritance

I was attempt­ing to make some changes to some fair­ly old code in our code­base (some­thing I prob­a­bly wrote myself…) which hasn’t been touched on for a while.

Nat­u­ral­ly, my first step is to under­stand what the code does, so I start­ed by look­ing at the class where I need to make my changes.

composition over inheritance_1

Per­haps unsur­pris­ing­ly, I couldn’t fig­ure out how it works.. The class con­tains only a hand­ful of over­ride meth­ods, but I have no idea how they fit togeth­er.

So I start­ed dig­ging deep­er through sev­er­al lay­ers of abstract class­es, each fill­ing in parts of the puz­zle, until I reached the base of this class hier­ar­chy.

By this point, I’m star­ing at a con­trol flow full of strate­gi­cal­ly placed gaps. Going back-and-forth along the class hier­ar­chy sev­er­al times, I end­ed up with a vague sense of how the var­i­ous pieces of log­ic scat­tered across the hier­ar­chy fit togeth­er.

composition over inheritance_2

What’s more, where we need­ed to devi­ate from the con­trol flow dic­tat­ed by the base class, we have had to rein­vent a brand new con­trol flow mid-hier­ar­chy, mak­ing it even hard­er for me to under­stand what’s going on.


This is not where I want to be… I want to be able to rea­son about my code eas­i­ly, and with con­fi­dence.

I sus­pect a great many of you have expe­ri­enced sim­i­lar pains in the past, but how do you go about apply­ing Com­po­si­tion over Inher­i­tance?


Wikipedia’s def­i­n­i­tion and exam­ple of Com­po­si­tion over Inher­i­tance focus­es only on domain mod­el­ling, and I’m gen­er­al­ly not a fan of con­clu­sions such as:

To favor com­po­si­tion over inher­i­tance is a design prin­ci­ple that gives the design high­er flex­i­bil­i­ty, giv­ing busi­ness-domain class­es and more sta­ble busi­ness domain in the long term.

In oth­er words, HAS-A can be bet­ter than an IS-A rela­tion­ship.

What does this even mean?!? Are you able to back up these claims of “high flex­i­bil­i­ty” and “more sta­ble busi­ness domain in the long term” with empir­i­cal evi­dence?


In my view, the real ben­e­fit of Com­po­si­tion over Inher­i­tance is that it encour­ages bet­ter prob­lem decom­po­si­tion – if you don’t break up the prob­lem into small­er pieces (that are eas­i­er to tack­le) first you have noth­ing to com­pose with lat­er on. Scott Wlaschin’s rail­way ori­ent­ed pro­gram­ming approach is an excel­lent exam­ple of how to apply com­po­si­tion in a prac­ti­cal and ele­gant way.



In his keynote The Old New Old New Things at Build­Stuff 14, Greg Young described prob­lem decom­po­si­tion as the biggest prob­lem we have in the soft­ware indus­try, because we’re just so bad at it…

And the chal­lenge of prob­lem decom­po­si­tion is not lim­it­ed to code orga­ni­za­tion. Microser­vices are all the rage right now, and the move from mono­lith­ic archi­tec­tures to microser­vices is anoth­er exam­ple of prob­lem decom­po­si­tion, albeit one that hap­pens at a high­er lev­el.


So I’ll be tak­ing knife to the afore­men­tioned class hier­ar­chy and replac­ing them with small, com­pos­able units, using a lan­guage that is a great fit for the job – F#!

Will you fol­low my lead?



Rail­way ori­ent­ed pro­gram­ming

Is your pro­gram­ming lan­guage unrea­son­able

Ser­vice archi­tec­tures at scale, lessons from Google and Ebay

Mar­tin Fowler on Microser­vices

Greg Young – The Old New Old New Things

Liked this post? Why not support me on Patreon and help me get rid of the ads!