This is why you need Composition over Inheritance

Check out my new course Learn you some Lambda best practice for great good! and learn the best practices for performance, cost, security, resilience, observability and scalability.

I was attempting to make some changes to some fairly old code in our codebase (something I probably wrote myself…) which hasn’t been touched on for a while.

Naturally, my first step is to understand what the code does, so I started by looking at the class where I need to make my changes.

composition over inheritance_1

Perhaps unsurprisingly, I couldn’t figure out how it works.. The class contains only a handful of override methods, but I have no idea how they fit together.

So I started digging deeper through several layers of abstract classes, each filling in parts of the puzzle, until I reached the base of this class hierarchy.

By this point, I’m staring at a control flow full of strategically placed gaps. Going back-and-forth along the class hierarchy several times, I ended up with a vague sense of how the various pieces of logic scattered across the hierarchy fit together.

composition over inheritance_2

What’s more, where we needed to deviate from the control flow dictated by the base class, we have had to reinvent a brand new control flow mid-hierarchy, making it even harder for me to understand what’s going on.


This is not where I want to be… I want to be able to reason about my code easily, and with confidence.

I suspect a great many of you have experienced similar pains in the past, but how do you go about applying Composition over Inheritance?


Wikipedia’s definition and example of Composition over Inheritance focuses only on domain modelling, and I’m generally not a fan of conclusions such as:

To favor composition over inheritance is a design principle that gives the design higher flexibility, giving business-domain classes and more stable business domain in the long term.

In other words, HAS-A can be better than an IS-A relationship.

What does this even mean?!? Are you able to back up these claims of “high flexibility” and “more stable business domain in the long term” with empirical evidence?


In my view, the real benefit of Composition over Inheritance is that it encourages better problem decomposition – if you don’t break up the problem into smaller pieces (that are easier to tackle) first you have nothing to compose with later on. Scott Wlaschin’s railway oriented programming approach is an excellent example of how to apply composition in a practical and elegant way.



In his keynote The Old New Old New Things at BuildStuff 14, Greg Young described problem decomposition as the biggest problem we have in the software industry, because we’re just so bad at it…

And the challenge of problem decomposition is not limited to code organization. Microservices are all the rage right now, and the move from monolithic architectures to microservices is another example of problem decomposition, albeit one that happens at a higher level.


So I’ll be taking knife to the aforementioned class hierarchy and replacing them with small, composable units, using a language that is a great fit for the job – F#!

Will you follow my lead?



Railway oriented programming

Is your programming language unreasonable

Service architectures at scale, lessons from Google and Ebay

Martin Fowler on Microservices

Greg Young – The Old New Old New Things

Liked this article? Support me on Patreon and get direct help from me via a private Slack channel or 1-2-1 mentoring.
Subscribe to my newsletter

Hi, I’m Yan. I’m an AWS Serverless Hero and the author of Production-Ready Serverless.

I specialise in rapidly transitioning teams to serverless and building production-ready services on AWS.

Are you struggling with serverless or need guidance on best practices? Do you want someone to review your architecture and help you avoid costly mistakes down the line? Whatever the case, I’m here to help.

Hire me.

Check out my new podcast Real-World Serverless where I talk with engineers who are building amazing things with serverless technologies and discuss the real-world use cases and challenges they face. If you’re interested in what people are actually doing with serverless and what it’s really like to be working with serverless day-to-day, then this is the podcast for you.

Check out my new course, Learn you some Lambda best practice for great good! In this course, you will learn best practices for working with AWS Lambda in terms of performance, cost, security, scalability, resilience and observability. We will also cover latest features from re:Invent 2019 such as Provisioned Concurrency and Lambda Destinations. Enrol now and start learning!

Check out my video course, Complete Guide to AWS Step Functions. In this course, we’ll cover everything you need to know to use AWS Step Functions service effectively. There is something for everyone from beginners to more advanced users looking for design patterns and best practices. Enrol now and start learning!

Are you working with Serverless and looking for expert training to level-up your skills? Or are you looking for a solid foundation to start from? Look no further, register for my Production-Ready Serverless workshop to learn how to build production-grade Serverless applications!

Find a workshop near you