SOLID: The Open-Closed principle (OCP)

 Open for extension, closed for modification

Described in its SOLID Principles by Uncle Bob as:

"You should be able to extend the behavior of a system without having to modify that system."

Just as in the case of the SRP, OCP is about minimizing the impact of changes in your software. Whether we are talking about re-usability within your code or the use of that code by others, it is a great advantage to be able to extend the features of your app without the need of modifying the whole thing.

For example, imagine a feature which sends a notification email every time a new post is published in my blog. With a high level of coupling, I risk sending the notification after post publishing has failed. 

How do we accomplish it? Avoiding dependence upon specific implementations. Or better said, by using generic or abstract classes or interfaces that will be later defined in the final classes. 

What is the difference between using an interface or an abstract class? 

  • Interfaces:
    • They don't modify the hierarchy tree
    • It is possible to implement more than one interface
    • It is frequently used to decouple code
  • Abstract class
    • It allows the use of Template-Method Pattern (pushing the logic of the business to the model). That means defining the header of the functions (making them abstract), defining them later on in the Final Child Class. In essence, it's like creating a Template which will be filled in by the child Final Class. 
    • It allows following the principle of Tell, don't ask. This method states that, instead of requesting data to the objects, we need to tell them what to do and request the result. For example:
I also wrote a previous post about Interfaces and Abstract Classes where there's a little bit more information.
 
ASK Pattern would look like:

 
Class User {
private $roles = ["ADMIN", "STUDENT"];
}

Class Login {
If (in_array("ROLE_ADMIN", $this->user->getRoles()) {
return new RedirectResponse($this->urlGenerator->generate(self::ADMIN_ROUTE));
}
}


We would refactor it to TELL pattern as follows:

 
Class User {
public function isUserAnAdmin()
    {
        return in_array("ROLE_ADMIN", $this->user->getRoles());
    }
}

Class Login {
If ($this->user->isUserAnAdmin()) {
return new RedirectResponse($this->urlGenerator->generate(self::ADMIN_ROUTE));
}
}

    • We use it when code is not too complex in order to avoid the need to sort of jump between abstract classes and child classes.
Here finishes the last post of the week! And remember, the important thing is to be able to identify the these principles with examples, even if you don't implement them in your coding strategies right away. First, make it work, then, make it beautiful. You want to have duplicated code rather than a poorly designed abstraction leading to later mistakes. 

Happy weekend and happy coding everyone! 

Comments

Popular posts from this blog

SOLID: The Single-Responsibility Principle (SRP)

Symfony HTTP client

Inheritance: Abstract classes and interfaces