DEV Community

Cover image for Open-Closed Principle (OCP)-Part-2
bappasaha
bappasaha

Posted on

Open-Closed Principle (OCP)-Part-2

đŸ”Ĩ02A-Open-Closed Principle (OCP)

The Open-Closed Principle (OCP) is one of the five SOLID principles of object-oriented design. It states that software entities (classes, modules, functions, etc.) should be open for extension but closed for modification. This means that you should be able to add new functionality to existing code without altering its source code.

Key Concepts

  • Closed for Modification:

    • Existing code should not be changed when adding new features. This helps avoid introducing bugs and maintains the stability of the system.
    • New features getting added to the software component should not have to modify the existing code.
  • Open for Extension:

    • New functionalities can be added through new code, allowing the system to grow without modifying existing components.

Real-World Analogy

A practical analogy to understand OCP is the Nintendo Wii [Joy Stick] tool gaming console:

  • The Wii console comes with a basic controller and allows for various accessories (like the Wii Zapper and steering wheel) to be added without modifying the console itself.
  • This design ensures that users can enhance their gaming experience without needing to alter the core system.

Benefits of OCP

  1. Maintainability: Reduces the risk of bugs by keeping existing code untouched.
  2. Scalability: Facilitates easy addition of new features as requirements evolve.
  3. Reusability: Encourages the reuse of existing modules and classes in different contexts.

Implementation Example in Java

To illustrate OCP in practice, consider a scenario where you need to compare areas of different shapes:

Without OCP

class Square {
    int height;
    int area() { return height * height; }
}

class OpenOpenExample {
    public int compareArea(Square a, Square b) {
        return a.area() - b.area();
    }
}
Enter fullscreen mode Exit fullscreen mode

This approach requires modification if a new shape (like Circle) is introduced.

With OCP

By using an interface:

interface Shape {
    int area();
}

class Circle implements Shape {
    int radius;
    int area() { return (int)(Math.PI * radius * radius); }
}

class Square implements Shape {
    int height;
    int area() { return height * height; }
}

class OpenClosedExample {
    public int compareArea(Shape a, Shape b) {
        return a.area() - b.area();
    }
}
Enter fullscreen mode Exit fullscreen mode

In this design, you can add new shapes without modifying existing code, adhering to the Open-Closed Principle.

Conclusion

The Open-Closed Principle encourages developers to design systems that are robust and adaptable.

By focusing on extending functionality rather than modifying existing code, developers can create more maintainable and scalable applications.

In future sessions, we will explore practical coding examples that demonstrate OCP in action.

đŸ”Ĩ02B-āĻ“āĻĒ⧇āύ-āĻ•ā§āϞ⧋āϜāĻĄ āĻĒā§āϰāĻŋāĻ¨ā§āϏāĻŋāĻĒāϞ: āϕ⧋āĻĄ āωāĻĻāĻžāĻšāϰāĻŖ

āĻĒāϰāĻŋāϚāĻŋāϤāĻŋ

āφāĻŽāϰāĻž āĻāĻ•āϟāĻŋ āϕ⧋āĻĄ āωāĻĻāĻžāĻšāϰāĻŖ āĻĻ⧇āĻ–āĻŦ āϝāĻž āĻāχ āύ⧀āϤāĻŋāϰ āĻŦāĻžāĻ¸ā§āϤāĻŦāĻžāϝāĻŧāύāϕ⧇ āϚāĻŋāĻ¤ā§āϰāĻŋāϤ āĻ•āϰāĻŦ⧇āĨ¤

āĻĒā§āϰ⧇āĻ•ā§āώāĻžāĻĒāϟ

āϧāϰāĻŋ, One State āĻāĻ•āϟāĻŋ āĻŦā§€āĻŽāĻž āϕ⧋āĻŽā§āĻĒāĻžāύāĻŋ āϝāĻž āĻŽā§‚āϞāϤ āĻ¸ā§āĻŦāĻžāĻ¸ā§āĻĨā§āϝ āĻŦā§€āĻŽāĻžāϰ āϏāĻžāĻĨ⧇ āϜāĻĄāĻŧāĻŋāϤāĨ¤ āϤāĻžāĻĻ⧇āϰ āĻŦā§€āĻŽāĻž āĻ—āĻŖāύāĻž āĻāĻ•āϟāĻŋ Java āϞāĻžāχāĻŦā§āϰ⧇āϰāĻŋāϤ⧇ āϕ⧋āĻĄ āĻ•āϰāĻž āĻšāϝāĻŧ⧇āϛ⧇āĨ¤

āϕ⧋āĻĄ āĻ¸ā§āύāĻŋāĻĒ⧇āϟ

āĻāĻ–āĻžāύ⧇ āĻāĻ•āϟāĻŋ āϕ⧋āĻĄ āĻ¸ā§āύāĻŋāĻĒ⧇āϟ āϰāϝāĻŧ⧇āϛ⧇ āϝāĻž āĻĒā§āϰāĻŋāĻŽāĻŋāϝāĻŧāĻžāĻŽ āĻĄāĻŋāϏāĻ•āĻžāωāĻ¨ā§āϟ āĻ•ā§āϝāĻžāϞāϕ⧁āϞ⧇āĻļāύ āĻĻ⧇āĻ–āĻžāϝāĻŧ:

class InsurancePremiumDiscountCalculator {
    public double calculatePremiumDiscountPercent(HealthInsuranceCustomerProfile profile) {
        if (profile.isLoyalCustomer()) {
            return 10.0; // Loyal customer discount
        }
        return 0.0; // No discount
    }
}
Enter fullscreen mode Exit fullscreen mode
  • HealthInsuranceCustomerProfile āĻ•ā§āϞāĻžāϏ⧇ āĻāĻ•āϟāĻŋ isLoyalCustomer() āĻĒāĻĻā§āϧāϤāĻŋ āϰāϝāĻŧ⧇āϛ⧇ āϝāĻž āϏāĻ¤ā§āϝ (true) āĻĢ⧇āϰāϤ āĻĻ⧇āϝāĻŧ āϝāĻĻāĻŋ āĻ—ā§āϰāĻžāĻšāĻ• āĻāĻ•āϜāύ āĻŦāĻŋāĻļā§āĻŦāĻ¸ā§āϤ āĻ—ā§āϰāĻžāĻšāĻ• āĻšāϝāĻŧ, āĻ…āĻ¨ā§āϝāĻĨāĻžāϝāĻŧ āĻŽāĻŋāĻĨā§āϝāĻž (false) āĻĢ⧇āϰāϤ āĻĻ⧇āϝāĻŧāĨ¤

āύāϤ⧁āύ āĻšā§āϝāĻžāϞ⧇āĻžā§āϜ

āϧāϰāĻŋ, One State āϕ⧋āĻŽā§āĻĒāĻžāύāĻŋ āĻāĻ•āϟāĻŋ āύāϤ⧁āύ āĻ—āĻžāĻĄāĻŧāĻŋ āĻŦā§€āĻŽāĻž āϕ⧋āĻŽā§āĻĒāĻžāύāĻŋ āĻ…āϧāĻŋāĻ—ā§āϰāĻšāĻŖ āĻ•āϰ⧇ āĻāĻŦāĻ‚ āϤāĻžāĻĻ⧇āϰ āĻŸā§āϝāĻžāĻ—āϞāĻžāχāύ āĻĒāϰāĻŋāĻŦāĻ°ā§āϤāύ āĻ•āϰ⧇: "āφāĻĒāύāĻžāϰ āĻ¸ā§āĻŦāĻžāĻ¸ā§āĻĨā§āϝ āĻāĻŦāĻ‚ āĻ—āĻžāĻĄāĻŧāĻŋ āĻŦā§€āĻŽāĻžāϰ āϜāĻ¨ā§āϝ āϏāĻŦāĻ•āĻŋāϛ⧁"āĨ¤ āĻāĻ–āύ āφāĻŽāĻžāĻĻ⧇āϰ āĻ—āĻžāĻĄāĻŧāĻŋ āĻŦā§€āĻŽāĻžāϰ āĻĄāĻŋāϏāĻ•āĻžāωāĻ¨ā§āϟāĻ“ āϏāĻŽāĻ°ā§āĻĨāύ āĻ•āϰāϤ⧇ āĻšāĻŦ⧇āĨ¤

āύāϤ⧁āύ āĻ•ā§āϞāĻžāϏ āϝ⧋āĻ— āĻ•āϰāĻž

āφāĻŽāϰāĻž āĻāĻ•āϟāĻŋ āύāϤ⧁āύ āĻ•ā§āϞāĻžāϏ āϝ⧁āĻ•ā§āϤ āĻ•āϰāĻŋ: VehicleInsuranceCustomerProfileāĨ¤ āĻāϟāĻŋ HealthInsuranceCustomerProfile āĻāϰ āĻŽāϤ⧋ āĻāĻŦāĻ‚ āĻāϰ isLoyal() āĻĒāĻĻā§āϧāϤāĻŋ āϰāϝāĻŧ⧇āϛ⧇āĨ¤

class VehicleInsuranceCustomerProfile {
    public boolean isLoyal() {
        // Logic to determine loyalty
    }
}
Enter fullscreen mode Exit fullscreen mode

āϏāĻŽāĻ¸ā§āϝāĻž

āĻāĻ–āύ āφāĻŽāĻžāĻĻ⧇āϰ InsurancePremiumDiscountCalculator āĻ•ā§āϞāĻžāϏāϟāĻŋ āĻĒāϰāĻŋāĻŦāĻ°ā§āϤāύ āĻ•āϰāϤ⧇ āĻšāĻŦ⧇, āĻ•āĻžāϰāĻŖ āĻāϰ calculate āĻĒāĻĻā§āϧāϤāĻŋ āĻŦāĻ°ā§āϤāĻŽāĻžāύ⧇ āĻļ⧁āϧ⧁āĻŽāĻžāĻ¤ā§āϰ HealthInsuranceCustomerProfile āĻ…āĻŦāĻœā§‡āĻ•ā§āϟ āĻ—ā§āϰāĻšāĻŖ āĻ•āϰ⧇āĨ¤

OCP āϞāĻ™ā§āϘāύ

  • āύāϤ⧁āύ āĻŦ⧈āĻļāĻŋāĻˇā§āĻŸā§āϝ āϝ⧋āĻ— āĻ•āϰāĻžāϰ āϜāĻ¨ā§āϝ āφāĻŽāĻžāĻĻ⧇āϰ āĻŦāĻŋāĻĻā§āϝāĻŽāĻžāύ āϕ⧋āĻĄā§‡ āĻĒāϰāĻŋāĻŦāĻ°ā§āϤāύ āĻ•āϰāϤ⧇ āĻšāĻšā§āϛ⧇, āϝāĻž āĻ“āĻĒ⧇āύ-āĻ•ā§āϞ⧋āϜāĻĄ āĻĒā§āϰāĻŋāĻ¨ā§āϏāĻŋāĻĒāϞ⧇āϰ āĻŦāĻŋāϰ⧁āĻĻā§āϧ⧇ āϝāĻžā§ŸāĨ¤
  • āϝāĻĻāĻŋ āφāĻŽāϰāĻž āĻŦāĻžāĻĄāĻŧāĻŋāϰ āĻŦā§€āĻŽāĻžāĻ“ āϏāĻŽāĻ°ā§āĻĨāύ āĻ•āϰāϤ⧇ āϚāĻžāχ, āϤāĻžāĻšāϞ⧇ āφāĻŦāĻžāϰ āϕ⧋āĻĄ āĻĒāϰāĻŋāĻŦāĻ°ā§āϤāύ āĻ•āϰāϤ⧇ āĻšāĻŦ⧇āĨ¤

āĻĄāĻŋāϜāĻžāχāύ āĻĒ⧁āύāĻ°ā§āĻ—āĻ āύ

āφāĻŽāϰāĻž āφāĻŽāĻžāĻĻ⧇āϰ āĻĄāĻŋāϜāĻžāχāύāϟāĻŋ āĻĒ⧁āύāĻ°ā§āĻ—āĻ āύ āĻ•āϰāĻŋ:

  1. CustomerProfile āύāĻžāĻŽā§‡ āĻāĻ•āϟāĻŋ āύāϤ⧁āύ āχāĻ¨ā§āϟāĻžāϰāĻĢ⧇āϏ āϤ⧈āϰāĻŋ āĻ•āϰāĻŋāĨ¤
  2. āĻāχ āχāĻ¨ā§āϟāĻžāϰāĻĢ⧇āϏ⧇ āĻāĻ•āϟāĻŋ āĻŽāĻžāĻ¤ā§āϰ āĻĒāĻĻā§āϧāϤāĻŋ āĻĨāĻžāĻ•āĻŦ⧇: isLoyalCustomer()āĨ¤
  3. āωāĻ­āϝāĻŧ HealthInsuranceCustomerProfile āĻāĻŦāĻ‚ VehicleInsuranceCustomerProfile āĻ•ā§āϞāĻžāϏ āĻāχ āϏāĻžāϧāĻžāϰāĻŖ āχāĻ¨ā§āϟāĻžāϰāĻĢ⧇āϏāϟāĻŋ āĻŦāĻžāĻ¸ā§āϤāĻŦāĻžāϝāĻŧāύ āĻ•āϰāĻŦ⧇āĨ¤
interface CustomerProfile {
    boolean isLoyalCustomer();
}

class HealthInsuranceCustomerProfile implements CustomerProfile {
    public boolean isLoyalCustomer() {
        // Logic for health insurance loyalty
    }
}

class VehicleInsuranceCustomerProfile implements CustomerProfile {
    public boolean isLoyalCustomer() {
        // Logic for vehicle insurance loyalty
    }
}
Enter fullscreen mode Exit fullscreen mode

āύāϤ⧁āύ āĻ•ā§āϝāĻžāϞāϕ⧁āϞ⧇āϟāϰ āĻ•ā§āϞāĻžāϏ

āĻāĻ–āύ InsurancePremiumDiscountCalculator āĻ•ā§āϞāĻžāϏ⧇āϰ āĻĒāĻĻā§āϧāϤāĻŋ āĻĒāϰāĻŋāĻŦāĻ°ā§āϤāύ āĻ•āϰāĻŋ:

class InsurancePremiumDiscountCalculator {
    public double calculatePremiumDiscountPercent(CustomerProfile profile) {
        if (profile.isLoyalCustomer()) {
            return 10.0; // Loyal customer discount
        }
        return 0.0; // No discount
    }
}
Enter fullscreen mode Exit fullscreen mode

āϏ⧁āĻŦāĻŋāϧāĻž

  • āĻāĻ–āύ āφāĻŽāϰāĻž āϝāĻĻāĻŋ āĻŦāĻžāĻĄāĻŧāĻŋāϰ āĻŦā§€āĻŽāĻžāϰ āϜāĻ¨ā§āϝ āĻāĻ•āϟāĻŋ āύāϤ⧁āύ āĻ•ā§āϞāĻžāϏ āϤ⧈āϰāĻŋ āĻ•āϰāĻŋ, āϝ⧇āĻŽāύ HomeInsuranceCustomerProfile, āĻāϟāĻŋ āĻļ⧁āϧ⧁āĻŽāĻžāĻ¤ā§āϰ CustomerProfile āχāĻ¨ā§āϟāĻžāϰāĻĢ⧇āϏāϟāĻŋ āĻŦāĻžāĻ¸ā§āϤāĻŦāĻžāϝāĻŧāύ āĻ•āϰāĻŦ⧇āĨ¤
  • āφāĻŽāĻžāĻĻ⧇āϰ InsurancePremiumDiscountCalculator āĻ•ā§āϞāĻžāϏ⧇ āϕ⧋āύ⧋ āĻĒāϰāĻŋāĻŦāĻ°ā§āϤāύ āĻ•āϰāϤ⧇ āĻšāĻŦ⧇ āύāĻžāĨ¤

āωāĻĒāϏāĻ‚āĻšāĻžāϰ

āφāĻŽāϰāĻž āĻĻ⧇āϖ⧇āĻ›āĻŋ āĻ•āĻŋāĻ­āĻžāĻŦ⧇ āĻĄāĻŋāϜāĻžāχāύ āĻĒ⧁āύāĻ°ā§āĻ—āĻ āύ āĻ•āϰ⧇ āĻ“āĻĒ⧇āύ-āĻ•ā§āϞ⧋āϜāĻĄ āĻĒā§āϰāĻŋāĻ¨ā§āϏāĻŋāĻĒāϞ āĻ…āύ⧁āϝāĻžāϝāĻŧā§€ āĻ•āĻžāϜ āĻ•āϰāĻž āϝāĻžāϝāĻŧāĨ¤ āĻĒā§āϰāĻĨāĻŽā§‡ āĻĄāĻŋāϜāĻžāχāύāϟāĻŋ OCP āĻ…āύ⧁āϏāϰāĻŖ āĻ•āϰāĻ›āĻŋāϞ āύāĻž, āĻ•āĻŋāĻ¨ā§āϤ⧁ āĻĒ⧁āύāĻ°ā§āĻ—āĻ āύ⧇āϰ āĻŽāĻžāĻ§ā§āϝāĻŽā§‡ āĻāϟāĻŋ OCP-āϰ āϏāĻžāĻĨ⧇ āϏāĻžāĻŽāĻžā§āϜāĻ¸ā§āϝāĻĒā§‚āĻ°ā§āĻŖ āĻšāϝāĻŧ⧇ āωāϠ⧇āϛ⧇āĨ¤

āĻāĻ–āύ āĻĄāĻŋāϜāĻžāχāύāϟāĻŋ āĻ­āĻŦāĻŋāĻˇā§āϝāϤ⧇āϰ āĻāĻ•ā§āϏāĻŸā§‡āύāĻļāύ⧇āϰ āϜāĻ¨ā§āϝ āφāϰāĻ“ āĻļāĻ•ā§āϤāĻŋāĻļāĻžāϞ⧀ āĻāĻŦāĻ‚ āĻ•āĻžāĻ°ā§āϝāĻ•āϰ⧀āĨ¤

āĻāϟāĻŋ āĻ›āĻŋāϞ āĻ“āĻĒ⧇āύ-āĻ•ā§āϞ⧋āϜāĻĄ āĻĒā§āϰāĻŋāĻ¨ā§āϏāĻŋāĻĒāϞ⧇āϰ āĻāĻ•āϟāĻŋ āωāĻĻāĻžāĻšāϰāĻŖāĨ¤

đŸ”Ĩ02C-Key Takeaways from the Open-Closed Principle Code Example

Introduction

We will summarize the key takeaways from the previous code example that illustrated the Open-Closed Principle (OCP).

Principal Benefits of the New Design

  1. Ease of Adding New Features
    • The primary benefit of adhering to the Open-Closed Principle is the ease with which new features can be added to the system.
    • This ease translates into cost savings for development and testing.

Cost Savings Explained

  • If we do not follow OCP, adding new features often requires modifying existing code.
  • Each modification increases the time spent on testing and quality assurance to ensure that no new bugs are introduced into the existing codebase.
  • In contrast, when following OCP, testing new code is simpler and less time-consuming than running a full regression test suite on existing code.
  • This principle is well-known among QA testers, who emphasize its importance in maintaining software quality.

Additional Benefits

  1. Decoupling of Components
    • By redesigning our system to conform to OCP, we inadvertently achieved a higher degree of loose coupling between components.
    • This decoupling aligns with the Single Responsibility Principle (SRP), as each component now has a clearer purpose and responsibility.

Interconnectedness of SOLID Principles

  • It is crucial to understand that the SOLID principles are intertwined and interdependent.
  • They are most effective when applied together, providing a holistic approach to software design.

Cautionary Note

  • Do Not Follow OCP Blindly:
    • While OCP is beneficial, blindly applying it can lead to an excessive number of classes, complicating your overall design.
    • For instance, if you need to fix a bug and believe that modifying existing code is necessary for an effective fix, do so without hesitation.
    • Avoid overhauling your design solely for bug fixes unless you notice recurring issues that could be mitigated by a redesign.

Subjective Application of OCP

  • Deciding when and where to apply the Open-Closed Principle is subjective rather than objective.
  • Use your judgment based on the specific context of your project.

Conclusion

  • Re-designed code to make it follow OCP
  • Following OCP can lead to cost benifits in the long run.
  • OPC and SRP can work together to achieve a better design.
  • Do not apply the OCPblindly and introduce unwanted complexity to your code.

The lessons learned from our code example related to the Open-Closed Principle. Understanding these key takeaways will help you apply OCP effectively in your future designs.

Top comments (0)