Instruction 3

Heads up... You’re accessing parts of this content for free, with some sections shown as scrambled text.

Heads up... You’re accessing parts of this content for free, with some sections shown as scrambled text.

Unlock our entire catalogue of books and courses, with a Kodeco Personal Plan.

Unlock now

In the last demo, you implemented the first principle in SOLID, the Single Responsibility principle. You refactored the system by breaking it down into four specialized types, each with its own clearly defined focus, instead of having it juggle multiple operations.

Now, it’s time to learn about the second SOLID principle: Open-Closed. Here’s how it’s defined:

Software entities, including classes, modules and functions, should be open for extension but closed for modification.

This means you should be able to expand the capabilities of your types without having to alter them drastically to add what you need.

When you want to add new functionality to a system while keeping the existing functionality intact, you shouldn’t be forced to change what already exists to introduce new capabilities. This might sound a bit more complicated than it is. It happens that you’ve already implemented this in lesson two, “Polishing OOP Concepts”, for different reasons.

The Contacts app started by defining a single type for contacts, ContactCard. Later, you received the requirement to introduce Company contacts, which were different from normal contacts and had special requirements regarding creating connections. You defined a new type to hide the implementation details of how the two types of contacts differ and how exactly to manage adding related contacts.

In lesson three, “Design Patterns”, you learned about the factory pattern, which is ideal for hiding the implementation details of the constructor. I’m sure that made you rethink the need for those child types and whether the base class on its own is enough.

With the current requirements of person and company contacts, things look fine. Some information in the constructor is enough to differentiate between each, such as a small if condition in the addRelatedContact(:). But imagine if your next requirement is about adding public services, emergency contacts, public payphones and other types of contacts.

If you relied on a single type, you’d be in clear violation of the Open-Closed principle for a simple reason: To implement these new types of contacts, you’d have to add a significant amount of code to the existing ContactCard class, which is already stable, to make it compatible with the new types.

The one drawback with the current implementation of the base class is the isCompany property. To add new types, you’ll still need to define new properties, update the implementations of addRelatedContact(:) to consider those properties, etc. This will create a mess.

However, there’s a better way to implement this flexible growth while maintaining isolation between types.

In the next demo, you’ll update the implementation of ContactCard and its subclasses to better follow the Open-Closed principle, making it easy to implement new card types when you need to.

See forum comments
Download course materials from Github
Previous: Demo 1 Next: Demo 2