Composition over inheritance

One last point that we should touch on before we continue is the idea of composition over inheritance. It is generally useful and also very relevant for the domain model of the applications that we will implement in the next chapters.

While designing the domain model of applications, you will often have the choice between relying on is-a relationships (that is, inheritance) or has-a relationships through composition and interfaces.

Creating good domain models is both challenging and fun. It takes experience to create solid ones with the right amount of abstraction and that can evolve while remaining maintainable over time. It is definitely a skill well worth acquiring for any software developer.

Inheritance is most useful for grouping related concepts together, but the problem with it is that it encourages you to create a hierarchy of classes very early during the development of your application, and often things change (a lot) over time. This is why you will probably make design mistakes at an early stage, leading to important maintenance problems later on (especially if you are working on a large project).

For this reason, unless you are able to predict the future somehow, you will probably be better off with composition.

Composition is generally a more flexible approach, through which you compose elements in your system and split the responsibilities more logically. Instead of trying to fit everything into some logical hierarchy of classes, you define contracts through interfaces and reuse implementations in order to implement the functionality.

With composition, your applications should better stand the test of time and will be easier to adapt.

You can check the following article for more in-depth advice: https://www.thoughtworks.com/insights/blog/composition-vs-inheritance-how-choose.

If you already know UML, you can safely skip over this section.