Background
On page 100 PPP Robert Martin says
"Closed for modification"
Extension of the module behavior does not lead to changes in the source or binary code of the module. The binary executable version of the module, whether it is a link library, DLL or Java.jar, remains untouched.
Also on page 103, he discusses an example written in C, where a design without OCP leads to recompilation of existing classes:
Thus, we not only need to change the source code of all witch / case statements or else chains, but we also need to change the binaries (by recompiling) of all modules that use any Shape data structure. Modifying binary files means that all DLLs, shared libraries, or other types of binary components must be redistributed.
Itβs good to remember that this book was published in 2003, and many examples use C ++, which is a language known for long compilation periods (if header file handlers are not processed well - Remedy developers mentioned in one presentation that Alan Wake is complete assembly takes only about 2 minutes).
Therefore, when discussing binary compatibility on a small scale (i.e. within a single project), one advantage of OCP (and DIP) is faster compilation time, which is less true for modern languages ββand machines. But on a large scale, when the library is used by many other projects, especially if their code is not under our control, the benefits of having to release new versions of the software still apply.
Example
As an example of an open source library that follows OCP in binary compatibility, take a look at JUnit. There are dozens of test frameworks that rely on JUnit @RunWith and Runner annotations to run them with the JUnit test runner - without having to change JUnit, Maven, IDE, etc.
Also recently added JUnit @ Annotations rules allows test scripts to connect to JUnit standard user behavior that would previously require a special test runner, Another example of OCP at the library level.
For comparison, TestNG does not comply with OCP, but it contains special JUnit checks to run TestNG and JUnit tests differently. A representative line can be found from the TestRunner.run () method:
if(test.isJUnit()) { privateRunJUnit(test); } else { privateRun(test); }
As a result, even the tough TestNG tester has more features in some aspects (for example, supports parallel parallel tests), other test environments do not use it, because it is not expanded to support other testing systems without changing TestNG, (TestNG has a way to connect custom test runners , using - testrunfactory , but AFAIK allows you to use only one type of runner for each package.Thus , unlike JUnit, in one project it would be impossible to use many different rk testing.
Conclusion
However, in most cases, OCP is used in an application or library, in which case the base module and its extensions are packed inside the same binary file. In this situation, OCP is used to improve source code support, and not to prevent redeployment and new releases. The possible benefit of having to recompile an immutable file still exists, but since compilation time is so small in most modern languages, this is not very important.
The thing should always be kept in mind that after OCP is expensive, as this makes the system more complex. Robert Martin talks about this on PPP p. 105 and the completion of the chapter. OCP should be used with caution, only for the most likely changes. You should not proactively introduce hooks in line with OCP, but you should only insert hooks after this happens if necessary. Thus, it is hardly possible to find a project in which all new functions would be added without changing existing classes - unless someone does this as an academic exercise (my intuition says that it will be very difficult and the resulting code will not be clean) .