SOLID Design Principles

0% completed

Previous
Next
Real World Analogies and Code Example

In the previous lesson, we learned the definition of the Open/Closed Principle (OCP). Now, in this lesson, we’ll explore a real-world coding example to understand how this principle is applied.

Initial Code Example Without OCP

Let’s start with a code example where all methods and logic are placed within a single class. This approach violates the Open/Closed Principle because adding new functionality will require us to modify the existing class.

Python3
Python3
. . . .

In this example, the Invoice class is responsible for generating invoices and applying discounts. If we need to add a new type of invoice later (like an international invoice), we would have to modify this class.

Extending the Code: Why It Doesn’t Follow OCP

Now, suppose we want to add the functionality to generate international invoices. Without applying the Open/Closed Principle, we’ll have to modify the existing Invoice class like this:

Python3
Python3
. . . .

Here, we’ve introduced an if-else block to handle different invoice types. This is a clear violation of the Open/Closed Principle. Each time we add a new invoice type, we will need to modify the generateInvoice() method, making the code more difficult to maintain and prone to errors.

Refactoring the Code to Follow OCP

Let’s refactor the code so that it follows the Open/Closed Principle. We’ll separate the logic into different classes so that new types of invoices can be added without modifying the existing code.

First, we’ll create an interface for generating invoices:

Python3
Python3
. . . .

Next, we’ll create separate classes for each type of invoice:

Python3
Python3
. . . .

Finally, we modify the Invoice class to delegate invoice generation to an object of type InvoiceGenerator:

Python3
Python3
. . . .

How This Follows OCP

Now, the Invoice class follows the Open/Closed Principle because it no longer needs to be modified when we want to introduce new types of invoices. Instead, we simply create a new class that implements the InvoiceGenerator interface.

For example, if we wanted to add a detailed invoice, we could do so without touching the existing code:

Python3
Python3
. . . .

The existing Invoice class remains unchanged, while we can easily extend the system by adding new invoice types through new classes.

Wrap Up

In this lesson, we saw how the Open/Closed Principle applies to real-world code. Initially, the Invoice class was tightly coupled to the invoice generation logic, forcing us to modify it whenever new functionality was added. By refactoring the code to follow OCP, we made it possible to extend the system by adding new types of invoices without modifying the core logic. This step-by-step approach ensures that our code is flexible, maintainable, and future-proof.

.....

.....

.....

Like the course? Get enrolled and start learning!
Previous
Next