Fact-checked by Grok 2 weeks ago

Open–closed principle

The Open–closed principle (OCP) is a foundational guideline in , asserting that software entities—such as classes, modules, and functions—should be designed to be open for extension while remaining closed to modification. This means developers can add new functionality by extending the entity's behavior (e.g., through or interfaces) without altering its , thereby minimizing the introduction of errors and enhancing . Formulated by in his 1988 book , the principle emphasizes the use of and polymorphism to achieve this balance, enabling systems to evolve predictably as requirements change. As one of the five SOLID principles popularized by in the early 2000s, the OCP promotes modular, reusable code that supports long-term adaptability in large-scale software projects. In practice, it is realized through techniques like abstract classes, virtual methods, and dependency inversion, which allow extensions via new implementations rather than edits to core logic. While originally rooted in Meyer's vision of reusable libraries, the principle has influenced modern , such as the and template method patterns, and remains relevant in languages like , C#, and for building robust, scalable applications.

Definition and Principles

Core Definition

The open–closed principle () states that software entities—such as classes, modules, functions, and other components—should be open for extension but closed for modification. This formulation, popularized in object-oriented design , originates from Bertrand Meyer's foundational work on modular , where modules are described as both open (available for extension, such as by adding new operations or data elements) and closed (ready for immediate use with a stable, well-defined ). Being "open for extension" means that the behavior of a software entity can be augmented or specialized through the addition of new code, without requiring changes to its existing implementation. This allows developers to introduce new functionality in response to evolving requirements while preserving the integrity of the original code. In contrast, being "closed for modification" ensures that the entity's existing remains unaltered once it is in use, thereby maintaining its , reliability, and across different contexts. The is inherently abstract, serving as a high-level guideline rather than a rigid rule, and it applies across various programming paradigms beyond strict object-orientation, such as functional or modular designs. By promoting designs that favor extension over direct alteration, the principle contributes to software , reducing the risk of introducing bugs or regressions when accommodating changes. It forms one of the five core tenets of the principles for object-oriented .

Fundamental Goals

The Open–closed principle () asserts that software entities, such as classes and , should be open for extension but closed for modification. A primary goal of the OCP is to promote software stability by minimizing regressions introduced by changes to existing code. When are closed to modification, developers avoid altering verified components, which reduces the risk of unintended side effects and cascading changes that could destabilize the system. This approach ensures that once a module has been tested and deployed, it remains reliable without requiring re-verification for every new addition. Another key objective is to enable extensibility, allowing systems to accommodate future requirements without compromising existing functionality. By supporting extensions through mechanisms like or polymorphism, the OCP facilitates the addition of new behaviors in isolated ways, preserving the of core logic while adapting to evolving needs. This goal addresses the inevitability of software evolution, ensuring that growth occurs without disrupting proven features. The OCP also aims to reduce and increase in system design. It encourages the creation of abstractions that allow dependent to interact through interfaces, minimizing direct dependencies and enabling loosely coupled extensions that maintain high internal focus within each module. Lower coupling prevents ripple effects from changes, while enhanced cohesion keeps related responsibilities tightly grouped, fostering modular architectures. Overall, adherence to the OCP supports long-term and in evolving systems. By prioritizing designs that resist modification while inviting extension, it promotes reusability and reduces the overall effort required for ongoing development and adaptation in complex, long-lived software projects. This contributes to more robust systems capable of handling growth without proportional increases in complexity or error rates.

Historical Origins

Bertrand Meyer's Formulation

Bertrand Meyer introduced the open-closed principle (OCP) in 1988 as part of his foundational work on object-oriented programming in the book Object-Oriented Software Construction. In this text, Meyer positioned the OCP within the principles of object-oriented analysis and design, where it serves as a guideline for constructing modular, extensible software systems that prioritize long-term adaptability over rigid implementation. The principle emerged from Meyer's observations on the challenges of software maintenance, advocating for designs that minimize the need to alter verified code when accommodating new requirements. Meyer articulated the OCP succinctly: "software entities (classes, modules, functions, etc.) should be open for extension, but closed for modification." This formulation underscores the dual nature of software modules—they must remain stable and unchanging in their core behavior (closed) while allowing new functionality to be added through external mechanisms (open). In Meyer's view, achieving this is essential to prevent the propagation of errors during evolution, as modifications to existing code often introduce unintended side effects in interdependent components. Central to Meyer's framework is the role of abstraction in enabling the OCP, where concrete implementations are hidden behind abstract specifications, such as classes or interfaces, to foster reusable components. By designing with abstraction, developers can extend systems via inheritance or deferred features without recompiling or altering the original modules, thereby supporting the creation of libraries and frameworks that are both reliable and versatile. This approach aligns with Meyer's emphasis on software reusability, ensuring that components remain intact and testable even as the system grows. The OCP's emphasis on extension over modification directly addresses the issue of fragile code in object-oriented design, as Meyer described it—a common pitfall where changes ripple through the system, undermining reliability. By enforcing to modifications, the principle safeguards the invariants of existing entities, allowing extensions to integrate seamlessly and reducing the fragility inherent in procedural or tightly coupled architectures. This contributes to Meyer's overarching goal of building software as a collection of robust, that evolve independently.

Influence on Software Design

The Open-Closed Principle (OCP) was integrated into the broader SOLID framework by Robert C. Martin in the early 2000s, forming the "O" in SOLID and repositioning it as a core tenet of object-oriented design that prioritizes extensibility without compromising stability. This adaptation built upon Bertrand Meyer's original formulation, synthesizing it with other principles to guide developers toward more maintainable architectures in evolving software landscapes. By embedding OCP within SOLID, Martin emphasized its role in reducing technical debt, enabling teams to add features through inheritance or interfaces rather than refactoring core logic, which has become a staple in modern programming paradigms. The principle's influence extends to agile methodologies, where it fosters modular designs that align with iterative development cycles and the need for frequent, low-risk updates. In agile environments, OCP encourages the creation of loosely coupled components, allowing teams to extend functionality in sprints without destabilizing validated code, thereby supporting and delivery practices. This reduces the ripple effects of changes, enhancing adaptability in dynamic projects and aligning with agile values of responsiveness to change over rigid planning. Furthermore, has reinforced the adoption of design-by-contract () and related Meyer-inspired techniques, where extensions preserve predefined invariants and preconditions, ensuring reliability in extensible systems. As part of Meyer's comprehensive approach to object-oriented construction, complements by enabling behavioral additions without violating established contracts, thus promoting verifiable and robust software evolution. The goals of the align with industry standards for software quality, such as the characteristics like and in ISO/IEC 25010:2011.

Implementation Strategies

Polymorphic Approaches

Polymorphic approaches to the open-closed principle utilize and polymorphism in object-oriented languages to extend software entities without modifying their . enables the creation of subclasses that inherit from a base , allowing new behaviors to be added or existing ones overridden solely through derivation, thereby preserving the integrity of the original . This strategy aligns with the OCP by isolating extensions to new code while keeping established modules unchanged. Runtime polymorphism, facilitated by virtual methods or interfaces, further supports this by enabling dynamic method resolution at execution time. When a client interacts with objects through a common supertype, the system automatically invokes the appropriate subclass-specific implementation without requiring alterations to the client logic or base class. This ensures flexibility in handling varying behaviors while maintaining against modifications. A representative scenario involves extending a shape-drawing system. A base Shape class declares an abstract draw method, which concrete subclasses such as Circle and Rectangle implement to render their geometries. To incorporate a new shape like Triangle, developers simply define a Triangle subclass that overrides the draw method; the existing renderer, which processes a collection of Shape objects polymorphically, requires no updates to accommodate this addition. By relying on supertypes for interactions, polymorphism decouples clients from specific implementations, establishing clear extension points where subclasses can introduce novel functionalities without disrupting dependent components. This enhances and in evolving systems.

Abstract Interfaces and Extension Points

Abstract interfaces serve as a foundational for adhering to the open-closed principle by defining behavioral contracts through method signatures without specifying details. These interfaces establish abstractions that classes can implement, enabling extensions via new implementations while keeping the interface itself unmodified and closed to changes. This approach promotes , as dependent components interact solely with the , allowing seamless substitution of concrete implementations to extend functionality. In contrast to polymorphic , which extends through subclassing and may introduce tighter , abstract interfaces emphasize and for more flexible extensions. The exemplifies the use of abstract interfaces to encapsulate interchangeable algorithms, where a context class delegates to objects implementing a common strategy interface. This allows new algorithms to be added by creating additional strategy classes without modifying the context, thereby supporting extension while closing the original code to alterations. For instance, a sorting context can switch between different strategies at by injecting the appropriate implementation, adhering to the principle's goals. Dependency injection facilitates OCP by externalizing the provision of dependencies, typically through constructors, setters, or interfaces, so that core classes remain unchanged when new implementations are introduced. This technique inverts control, allowing runtime configuration of extensions without recompiling or modifying the dependent modules. Frameworks like implement this by wiring components against abstractions, ensuring high-level modules depend on injectable interfaces rather than concrete classes. Plugin architectures achieve OCP by designing core systems around well-defined extension points, such as interfaces or APIs, where third-party modules can register and load dynamically without altering the main codebase. This modular approach, often seen in applications like IDEs, enables functionality growth through add-ons that implement predefined contracts, maintaining stability in the core while opening avenues for extension. The core application scans for plugins at startup and integrates them via these points, ensuring modifications are isolated to the plugins themselves.

Practical Examples

Basic Code Illustration

To illustrate the Open-Closed Principle (OCP), consider a basic arithmetic calculator that computes operations such as and on two numbers. A non-compliant implementation might use a single with conditional logic to handle each , as shown in the following :
[class](/page/Class) Calculator {
    double calculate([string](/page/String) [operation](/page/Operation), [double](/page/Double) a, [double](/page/Double) b) {
        if ([operation](/page/Operation) == "add") {
            return a + b;
        } else if ([operation](/page/Operation) == "subtract") {
            return a - b;
        }
        // Default or error handling
        throw new Unsupported[Operation](/page/Operation)Exception("Operation not supported");
    }
}
This design violates OCP because extending the calculator to support a new operation, such as , requires modifying the calculate to add another conditional branch (e.g., else if (operation == "multiply") { return a * b; }). Such modifications can introduce into existing functionality and make the code brittle as the number of operations grows. A compliant refactoring applies polymorphism by defining an abstract for operations, allowing extensions without altering the core . The refactored is as follows:
interface [Operation](/page/Operation) {
    double execute(double a, double b);
}

class Addition implements [Operation](/page/Operation) {
    double execute(double a, double b) {
        return a + b;
    }
}

class [Subtraction](/page/Subtraction) implements [Operation](/page/Operation) {
    double execute(double a, double b) {
        return a - b;
    }
}

class Calculator {
    double calculate([Operation](/page/Operation) op, double a, double b) {
        return op.execute(a, b);
    }
}
This adheres to OCP by keeping the Calculator class closed for modification—its calculate method remains unchanged regardless of new operations—while being open for extension through new implementations of the [Operation](/page/Operation) interface. To extend this design, follow these steps: First, create a new class that implements Operation, such as Multiplication with execute returning a * b. Second, instantiate the new class and pass it to the existing Calculator instance, e.g., calculator.calculate(new Multiplication(), 5, 3). The core Calculator class requires no updates, ensuring that additions do not affect previously tested code. This polymorphic approach, a fundamental strategy for OCP, promotes extensibility. Compared to the original, the refactored version reduces the core class length from handling multiple conditionals to a single call, improving ; extensions add minimal code in isolated classes rather than risking widespread changes, which scales better for dozens of operations.

Design Pattern Integration

The enforces the Open-Closed Principle by defining the skeleton of an algorithm in a base class while allowing subclasses to override specific steps, known as hooks, without altering the original structure. This approach ensures that extensions to the algorithm can be achieved through , keeping the base class closed to modification. The Factory pattern supports OCP by enabling the creation of objects through a factory method that defers instantiation to subclasses, avoiding the need to specify concrete classes in client code. New product types can thus be introduced by extending the factory hierarchy, extending functionality without modifying existing creator classes. Similarly, the Observer pattern aligns with OCP by permitting the addition of new subscriber classes without altering the publisher's code, as interactions occur via a common interface. This decoupling allows the system to scale with additional observers while maintaining the subject's integrity against changes. Collectively, these patterns enforce in larger systems by composing extensible abstractions, such as using to create observers that plug into methods, thereby forming modular architectures resilient to evolution. A high-level of this might depict a central class invoking a to instantiate Observer-compatible components, with arrows illustrating extension points from interfaces to implementations without crossing modification boundaries.

Advantages and Challenges

Key Benefits

Applying the Open-Closed Principle (OCP) significantly reduces the risk of introducing during software extensions, as it encourages adding new functionality through extension mechanisms rather than altering existing, tested code, thereby limiting the scope of changes and potential regressions. This stability is particularly valuable in large-scale systems where modifications to core modules could propagate errors across dependencies. The principle also enhances the reusability of software components across diverse projects, enabling modules to be extended via or interfaces without internal changes, which promotes and decreases code duplication efforts. By fostering such extensible structures, facilitates the integration of proven components into new applications, accelerating development and lowering long-term costs. Empirical studies demonstrate tangible impacts, such as a consolidation of results showing that principles, including , improve code maintainability and understanding, leading to reduced refactoring needs and more efficient development cycles in and general software contexts. One assessment found that applying these principles reduced by approximately 69%, contributing to scalable designs and decreased overhead.

Common Limitations

While the Open-Closed Principle (OCP) promotes extensibility through , its application can introduce overhead from over-, resulting in complex hierarchies that increase and maintenance difficulty. Excessive use of interfaces and abstract classes to achieve closure often leads to unnecessary layers, making the harder to navigate and debug without providing proportional benefits in flexibility. For instance, developers may create deep trees or multiple levels prematurely, complicating simple extensions and violating the principle of simplicity in . Retrofitting the into systems presents significant challenges, as existing codebases typically lack the necessary abstractions, requiring extensive refactoring to introduce extension points without disrupting functionality. In settings, this process involves identifying tightly coupled components and incrementally applying principles like , but it demands substantial time and resources, often spanning months for large systems, due to the risk of introducing regressions during modifications. An experience report on refactoring a system highlighted that while principles, including , improved , the effort involved careful testing and gradual changes to avoid breaking interdependent modules. In high-frequency or performance-critical systems, the indirection inherent in OCP implementations—such as virtual function calls for polymorphism—can impose measurable runtime overhead. Virtual calls require , which adds compared to direct function calls; studies have shown this overhead can reach 20-30% in certain scenarios, particularly when misses or frequent invocations occur. For example, in C++ applications, the resolution of s via vtables contributes to slower execution in loops or real-time processing, making full adherence to OCP impractical without compromising efficiency. Certain scenarios render full closure under OCP impossible, especially in performance-critical modifications where core algorithms must be altered for optimization, such as tuning low-level data structures or inline expansions that cannot be achieved through extension alone. In such cases, the need for direct modifications to existing code outweighs extensibility goals, as abstractions would exacerbate bottlenecks in resource-constrained environments like systems or high-throughput servers. This limitation underscores that is less suitable for domains prioritizing raw performance over long-term adaptability.

References

  1. [1]
    [PDF] The Open/Closed Principle
    The open/closed principle was stated and discussed as one of the fundamental object oriented principles by Bertrand Meyer in: Object Oriented Software ...Missing: excerpt | Show results with:excerpt
  2. [2]
    The Open-Closed Principle
    The Open-Closed Principle (OCP) states: A component should be open to extension but closed to modification. A component can be anything from a single class to ...Missing: definition | Show results with:definition
  3. [3]
    Page not found - Bertrand Meyer's technology+ blog
    - **Status**: Insufficient relevant content.
  4. [4]
    [PDF] The Open-Closed Principle - Object Mentor
    They are “Open For Extension”. This means that the behavior of the module can be extended. That we can make the module behave in new and different ways as ...
  5. [5]
  6. [6]
    Solid Relevance - Clean Coder Blog - Uncle Bob
    Oct 18, 2020 · A Module should be open for extension but closed for modification. Of all the principles, the idea that anyone would question this one fills ...<|control11|><|separator|>
  7. [7]
    Open-Closed Principle [OCP] - Embedded Artistry
    Jul 13, 2022 · It originated from the work of Bertrand Meyer It means simply this: We should write our modules so that they can be extended, without requiring ...Evolution Of The Ocp · Applying The Ocp · Providing Hooks For External...<|control11|><|separator|>
  8. [8]
    [PDF] The Open-Closed Principle - Object Mentor
    Bertrand Meyer2 gave us guidance as long ago as 1988 when he coined the now famous open-closed principle. To paraphrase him: SOFTWARE ENTITIES (CLASSES, MODULES ...Missing: excerpt | Show results with:excerpt
  9. [9]
    Patterns in Practice: The Open Closed Principle - Microsoft Learn
    The Open Closed Principle is stated as: software entities should be open for extension but closed for modification.
  10. [10]
    Object-Oriented Software Construction: Meyer, Bertrand - Amazon.com
    Product information. Publisher, Prentice Hall Press. Publication date, January 1, 1988. Language, ‎English. Print length, 592 pages. ISBN-10, 0136290493. ISBN- ...
  11. [11]
    Some contributions - Bertrand Meyer's technology+ blog
    Feb 26, 2021 · Bertrand Meyer's technology+ blog ... Another contribution of OOSC1 (1988), section 2.3, reinforced in OOSC2 (1997) is the Open-Closed principle ...
  12. [12]
    Why SOLID principles are still the foundation for modern software ...
    Nov 1, 2021 · What is SOLID? SOLID is a set of principles distilled from the writings of Robert C. Martin in the early 2000s. It was proposed as a way to ...
  13. [13]
    ArticleS.UncleBob.PrinciplesOfOod - ButUncleBob.com
    In March of 1995, in comp.object, I wrote an article that was the first glimmer of a set of principles for OOD that I have written about many times since. You' ...
  14. [14]
  15. [15]
    Agile Design Principles - Today Software Magazine
    The OCP principle advocates design refactoring so that further modifications of the same type will no longer produce modifications on the existing code, which ...
  16. [16]
    ISO/IEC 25010:2011 - Systems and software engineering
    ISO/IEC 25010:2011 defines: The characteristics defined by both models are relevant to all software products and computer systems.
  17. [17]
    Evaluating Open Source Software Quality Models Against ISO 25010
    Oct 10, 2016 · Quality Assurance of IoT based Home Automation Application using Modified ISO/IEC 25010. Article. Full-text available. Feb 2021. Rohini Temkar ...
  18. [18]
    [PDF] The Open/Closed Principle
    Abstract interfaces directly support the Open/Closed Principle. They must be extended, but are closed to modification. Since they have no implementation ...Missing: "research | Show results with:"research
  19. [19]
    [PDF] Realizing the Open-Closed Principle
    The first principle in developing large software systems is the Open-Closed Principle (OCP). This principle seems asking for two conflict.
  20. [20]
    Strategy - Refactoring.Guru
    Open/Closed Principle. You can introduce new strategies without having to change the context. If you only have a couple of algorithms and they rarely change ...Strategy in Python · Strategy in C++ · Strategy in Go · Strategy in PHP
  21. [21]
    Inversion of Control Containers and the Dependency Injection pattern
    In this article I dig into how this pattern works, under the more specific name of “Dependency Injection”, and contrast it with the Service ...
  22. [22]
    The Open Closed Principle - Clean Coder Blog - Uncle Bob
    May 12, 2014 · In 1988 Bertrand Meyer defined one of the most important principles of software engineering. The Open Closed Principle (OCP).Missing: source | Show results with:source
  23. [23]
    The Open/Closed Principle with Code Examples - Stackify
    Mar 28, 2018 · The Open/Closed Principle is one of five design principles for object-oriented software development described by Robert C. Martin.
  24. [24]
    SOLID Principles with Real Life Examples - GeeksforGeeks
    Aug 23, 2025 · Let's understand Open/Closed Principle using an example: Imagine you have a class called PaymentProcessor that processes payments for an ...
  25. [25]
    Form Template Method - Refactoring.Guru
    Forming a template method is an example of the Open/Closed Principle in action. When a new algorithm version appears, you need only to create a new subclass ...
  26. [26]
    Factory Method - Refactoring.Guru
    Open/Closed Principle. You can introduce new types of products into the program without breaking existing client code.Factory Comparison · Factory Method in Python · Factory Method in TypeScript
  27. [27]
    Observer - Refactoring.Guru
    Open/Closed Principle. You can introduce new subscriber classes without having to change the publisher's code (and vice versa if there's a publisher interface).
  28. [28]
    Investigating the Impact of SOLID Design Principles on Machine ...
    Dec 21, 2024 · Open-Closed Principle (OCP): Classes should be open for extension but closed for modification, facilitating long-term maintenance. Liskov ...
  29. [29]
    (PDF) An Experimental Evaluation of The Effect of SOLID Principles ...
    This work shows the effect of object oriented design principles SOLID to the maintainability, complexity and flexibility of the code
  30. [30]
    [PDF] An Experimental Evaluation of the Effect of SOLID Principles to ...
    Open Closed Principle: An entity can allow its behavior to be modified without altering its source code. Modules that adhere to open-closed principle have ...
  31. [31]
    (PDF) Applying SOLID Principles for the Refactoring of Legacy Code
    Oct 15, 2024 · Applying SOLID Principles for the Refactoring ... reduction of architectural technical debt in an industry setting? Rationale: refactoring ...
  32. [32]
    Effect of SOLID design principles on quality of software An empirical ...
    The study reveals a reduction in coupling by approximately 69% and an ... The research indicates that employing SOLID principles leads to a scalable ...
  33. [33]
    When Using Solid Principles May Not Be Appropriate - Baeldung
    Feb 21, 2025 · SOLID principles are inappropriate for one-off projects, performance-critical apps, small applications, and dynamic environments where ...
  34. [34]
    Applying SOLID principles for the refactoring of legacy code
    These principles promote a structured approach to software design, aiming to make software more scalable, maintainable, and adaptable: in particular, the ...
  35. [35]
  36. [36]
    [PDF] Fast Static Analysis of C++ Virtual Function Calls
    Therefore, unless compilers are improved, the overhead due to virtual function calls is likely to increase as programmers make more extensive use of this ...