After learning about the Single Responsibility Principle, we have the Open-Closed Principle which is the second principle in SOLID.
A class should be open for extension but closed for modification.
The open-closed principle suggests that when a new functionality is to be implemented we should create another class or object rather than modifying existing code and tests to comply with the new requirements.
In a restaurant POS, the computation of the total invoice for a transaction can be different because of discounts. Let’s say that the restaurant has two ways to compute the invoice of a transaction i.e without any discount and with a senior citizen’s discount. The owner now said that he will now distribute promo codes for his customers. A new computation has to be created for this feature.
In the sample above, we added a new discount type and modified the invoice builder class in order to have a section in the code where the computation of the invoice with a promo code is done. This would work but whenever we need to change something we need to refer to the same class. Also, whenever we need to add a new type of discount we will have to modify the same class/method thus adding more lines and complexity to the class.
By creating an interface for the computation of the invoice, we can easily implement new invoice computations without changing existing codes. Extending rather than continuously modifying grants us a cleaner and more maintainable code. If the computation for the invoice with a promo needs to be changed because the owner said that it has to be computed differently from now on, then we can easily access that class to change it.
If you noticed, the open-closed principle and the single responsibility principle works together. It may not be always the case but if we practice the single responsibility principle, we can easily comply with the open-closed principle and vice versa. In the sample, what we did was to have separate responsibilities in the computation of the bill based on the different discounts offered by the restaurant.
In the sample, we were able to practice the open-closed principle by implementing an interface. Another way to achieve the open-closed principle is through polymorphism. By implementing the open-closed principle we become more confident that we can easily deal with new requirements, we can say that our code is maintainable and we can test our code easier.
Whenever a new feature is required, don’t modify existing code, extend it.