Let's state the principle: "software entities (classes, modules, functions, etc.) should be open for extension, but closed for modification" (see https://en.wikipedia.org/wiki/Open%E2%80%93closed_principle).
Here are my personal thoughts on how to achieve that.
Let's consider a "set-theoretical" approach. If we view a class as a set A of lines of code. Then we must not modify the content of A. This represents the closure aspect.
However, to extend the functionality of A, we will need to modify certain parts of A.
Therefore, we must (1) extract those parts from A as external sets, such as B, C, and so on.
Next, (2) establish relationships R_1, R_2 ... between the parts of A where code was extracted and the new sets B and C.
At this point, we have two options:
- Extending the functionality by modifying B, C, etc., would contradict the Open-Closed Principle for B, C, etc.
- Extending the functionality by introducing new sets (classes) such as B', C', etc., and defining relations R_1, R_2, etc., in a manner that allows seamless switching between B and B', C and C', etc.
Mathematically, to enable the flexibility to switch between B and B', C and C', etc., the relations R_1, R_2, etc.,
must establish links between set A and families of sets {B, B', B'', ...}, {C, C', C'', ...}, and so forth. Like set-valued mappings.
For example, the relation "use an object b of extendable class B" is a solution. Because if we have inside A the line
b.method1();
where b is of type B, then we can always replace b with an object of type B', where B' extends B.
A more explicit relationship might be described as "use an object b of interface B" or "use an object b of abstract class B". In light of the above, an interface serves as a relationship to a family or hierarchy of interfaces and classes that implement it.
A specific type of relation is the mapping, or function. If we put inside A the line
method1();
To extend the functionality of method1(), it must relate not only to its own body but also to a family of methods named method1(). This can be achieved using the template method pattern.
Possibly, the last part involving the mapping concept could be refined to "use a method that can be overridden".
Some links:
https://www.cs.utexas.edu/users/downing/papers/OCP-1996.pdf
Niciun comentariu:
Trimiteți un comentariu