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)