OCP states that "a software artifact should be open for extension but closed for modification"
Software should be extendible without modifying existing code
A Thought Experiment
Scenario: System displaying financial summary on a web page
Goal: Extend the system to print the financial summary as a report
Ideally, the amount of changed code to implement the solution should be close to zero
Separate things changing for different reasons (SRP)
Organise dependencies between those things (DIP)
With SRP:
Inspect financial data
Produce reportable data
Formatted by either a web reporter process or print reporter process
With DIP:
Uni-directional relationship between components protects a component from changes in the other component
Forms a hierarchy of protection, higher-level components (Interactors) are protected from changes made in lower-level components (View)
Architects separate functionality based on how, why and when a component changes
Directional Control
The complexity in these diagrams are usually from added interfaces to ensure dependencies between components point in the right direction
Ex. FinancialDataGateway interface between the FinancialReportGenerator and FinancialDataMapper exists to invert dependency between the Interactor and Database components
Information Hiding
Ex. FinancialReportRequester interface exists to protect FinancialReportController from knowing too much about the internals of the Interactor
Otherwise, Controller would have transitive dependencies on the FinancialEntities
Transitive dependencies are a violation of the principle: "Software entities should not depend on things they don't directly use"
We want to protect the Interactor from changes to the Controller, but also protect the Controller from changes to the Interactor (both directions)
Conclusion
Goal of OCP is to make systems extendible without incurring a high impact of change
Achieved by partitioning the system into components and arranging them into a dependency hierarchy
Protects higher-level components from changes in lower-level components