Design Patterns in Software Development
From small applications to large and complex systems, design patterns are used as reusable solutions to common problems. There are plenty of design patterns. Which one to use will depen on the type of software been developed and the problem currently facing.
On this article I am covering a couple of object-oriented principles that are extensively used software design patterns. Object composition and class inheritance are not design patterns by themselves. They are techniques that allow code reusability inside an application.
Object composition is an object-oriented technique for assembling objects in order to get more complex behaviours. It is based on classes that instantiate other objects as their instance properties. That allows to reuse logic between objects.
Composition requires objects to respect other object’s interfaces. Due to this, it requires to design interfaces that won’t block you from using with many objects. If done correctly, object composition allows for code reusability without breaking class encapsulation.
This style of code reusability is also known as black-box reuse, because the internal details of the objects been reused are not visible. It is a benefit as objects are like black boxes and we can control the visibility of their properties via interfaces.
The result of object composition is a cleaner software as classes remain small and there will be less likely to grow into unmanageable class hierarchies.
Class inheritance is an object-oriented mechanism that is used to extend existing functionality on a parent class into a new sub-class. It allows you to create new objects based on from existing ones.
When a class extends from a parent one, it is going to inherit all parent methods and properties. This means that a method defined on a parent class is going to be available on its subclasses. Subclasses are allowed to overwrite any parent method. However, it is important to understand the impacts of any change as a single method overwrite might have an impact on other functionality.
Class inheritance generate a hierarchy of classes that can extend from each other in order to reuse their logic. In a system based on class inheritance it is common to see a multilevel of inheritance.
Composition over inheritance
Class inheritance and object composition each have their advantages and disadvantages. However, there is a well-known object-oriented design principle which is: favour object composition over class inheritance.
Class inheritance is said to break encapsulation as the implementation of a parent class is been exposed to their subclasses. Class inheritance also creates a tied coupling between the classes and stablishes a dependency in the system. These dependencies can cause problems when the parent class gets an internal modification as it is impacting all its subclasses.
Class decoupling in a system will give you flexibility when adding new functionality or existing code gets rewritten.
Object composition is based on a “has a” relationship whereas Class inheritance is based on “is a” relation.
In object composition there are less dependencies in terms of implementation as the objects been reused keep their interfaces.
Ideally you shouldn’t have to create new components to achieve code reusability. If objects are well-designed, you should be able to get all the functionality you need by assembling existing objects through object composition.