Encapsulate what varies
It’s all about letting one part of the system vary independently of another part.
This principle has two aspects that roughly dcorrespond to SRP and OCP principles.
-
Make changes local. Everything which is supposed to change in the future should be encapsulated in a single module. This means cross-cutting concerns are avoided as much as possible.
-
Introduce abstractions. Sometimes the varying concept is one which varies at runtime rather than by maintenance. In this case, there has to be an abstract base class or an interface which encapsulates the varying concepts.
Program to an interface, not an implementation
Implementation reuse is only half the story. Inheritance’s ability to define families of objects with identical interfaces is also important. Why? Because polymorphism depends on it.
When inheritance is used properly, all classes derived from an abstract class will share its interface. This implies that a subclass merely adds or overrides operations, and does not hide operations of the parent class.
All subclasses can then respond to the requests in the interface of the abstract parent class, making them subtypes of the abstract class.
There are two benefits to manipulating objects solely in terms of the interface defined by abstract classes:
- Clients remain unaware of the specific types of objects they use, as long as the objets adhere to the interface that client expect.
- Clients remain unaware of the classes that implement these objects, they only know about the abstract clas(es) defining the interface.
This so greatly reduces implementation dependencies between subsystems that it leads to the principle: _PRogram to an interface, not an implementation.