Open-Closed Principle (OCP)
Learn about the Open-Closed Principle (OCP) and its benefits. Extend functionality without modifying code, ensuring maintainability and reusability.
Usage
π Guideline
Open-Closed Principle: Classes should be closed for modification but open for extension.
The Open-Closed Principle dictates that you shouldn't need to change existing code to add more functionality to a class. Instead, you should be able to extend its behavior without modifying its implementation.
π οΈ How to Apply
- Abstraction: Abstract classes and interfaces can define a common contract for different implementations, allowing new functionality to be added by implementing these abstractions. π
- Inheritance: Use inheritance to create specialized classes that extend a base class, enabling additional functionality to be added without modifying the existing code. π§¬
- Polymorphism: Utilize polymorphism to accept different implementations of a common interface, promoting extensibility. π
- Composition: Exctend objects using composition rather than modifying existing classes directly, allowing new behavior to be added by combining different components. π§
- Dependency Injection: Inject dependencies into classes to allow for flexible component replacement and avoid hard dependencies. π
Pros and Cons
π Pros
- Enhanced Modularity: Promotes modularity by containing changes within specific classes or modules, reducing the impact on other parts of the codebase. π§©
- Maintainability: The principle promotes a design that minimizes modifications to existing code, making it easier to maintain and reducing the risk of introducing bugs. π οΈ
- Reusability: By following the Open-Closed Principle, code becomes more reusable as new functionality can be added by extending existing classes or implementing abstractions. β»οΈ
π Cons
- Increased Complexity: Adhering to the Open-Closed Principle may introduce additional layers of abstraction and complexity, which can be challenging to manage in certain scenarios. π€
- Potential Overengineering: Applying the principle too rigidly can lead to over-engineering, resulting in unnecessary abstractions and reduced development speed. π§
Examples
β Bad
class Order {
// ...
calculateTotal() {
// calculate total order cost
}
applyDiscount() {
// apply discount based on user type
}
generateInvoice() {
// generate invoice for the order
}
}
β Good
interface Order {
calculateTotal(): number;
}
class RegularOrder implements Order {
calculateTotal() {
// calculate total order cost
}
}
class DiscountedOrder implements Order {
calculateTotal() {
// calculate total order cost with discount
}
}
class OrderInvoice {
generate(order: Order) {
// generate invoice for the order
}
}
References
𧱠SOLID Principles
SOLID is an acronym for five other class-design principles:
- Single Responsibility Principle (SRP)
- Open-Closed Principle (OCP)
- Liskov Substitution Principle (LSP)
- Interface Segregation Principle (ISP)
- Dependency Inversion Principle (DIP)
π Related principles
- Single Responsibility Principle: Encourages classes to have a single responsibility, aligning with the Open-Closed Principle for better code maintainability. π―
- Liskov Substitution Principle: Focuses on substitutability, supporting the Open-Closed Principle by allowing seamless extension with subclass objects. π
- Interface Segregation Principle: Suggests smaller and more focused interfaces, complementing the Open-Closed Principle's emphasis on abstraction and extension. π¦
- Dependency Inversion Principle: Promotes depending on abstractions, aligning with the Open-Closed Principle's goal of extending functionality without modifying existing code. π§
- Don't Repeat Yourself (DRY): DRY principle reduces code duplication, helping adhere to the Open-Closed Principle by minimizing unnecessary modifications. β»οΈ