PHP Course : SOLID - Open-Closed
The second principle of SOLID is called Open-Closed, and helps developer to mature well designed code.
This is a confusing one, but I'll try to make it easy to grasp.
First of all, this principle states that entities should be open for extension, but closed for modification.
"Entities" are basically a class or a function.
- Okay thanks for the definition but it doesn't really make any sense, I don't even know what to do with it
Let me try to simplify this at first
When we say "open for extension", we are saying that it should be simple to change the behavior of a specific entity (a class, a method, a function).
When we talk about "closed for modification", we mean "changing the behavior without modifying the source code". This is why the term "extension" is important.
Now of course this principle is a goal to aim. It is very difficult to follow it perfectly.
In conclusion, the goal is to be able to change the behavior of a class without touching his code source, using an "extension" approach.
Let's imagine a Square
class that has a height and width property.
class Square
{
public $width;
public $height;
public function __construct($height, $width)
{
$this->height = $height;
$this->width = $width;
}
}
Now we want a way to calculate the surface area of that Square. Following the Single Responsability Principle, we will create a new class dedicated the calculating the area of a Shape. Let's do that.
class AreaCalculator
{
public function calculate($squares)
{
foreach ($squares as $square) {
$area[] += $square->width * $square->height;
}
return array_sum($area);
}
}
Okay, everything works fine and we follow SRP.
But then one day, you need to also calculate the area of a Circle
. So what do you do ? You create a Circle
class, sure:
class Circle
{
public $radius;
public function __construct($radius)
{
$this->radius = $radius;
}
}
Sure that's fine, but in order to calculate the area of Circles, you'll need to heavily modify the AreaCalculator
class. Not good, we just broke the Open Close Principle.
Take a look at the AreaCalculator
class. The variables are called $squares
, but we can easily change that to a generic name like $shapes
.
Now inside your foreach, how do you proceed? The quick and dirty way is to do a quick check like:
foreach ($shapes as $shape) {
if ($shape instanceof Circle) {
$area[] += $shape->radius * $shape->radius * pi();
} else {
$area[] += $shape->width * $shape->height;
}
}
This is bad. This if & else is a dead ringer that you broke the Open Closed Principle.
We just modified AreaCalculator
class, meaning it was open for modification, but it should have been closed for modification.
Imagine after that you now need to support Triangle
shapes, and then dozen other types of shapes. You'll get a very big if/else imbrication.
When you have a module that you want to extend or modify (that's what we want to do), separate the extensible behavior behind an interface, and flip the dependencies.
In our case, we see that each type of a shape has its own surface calculation method.
Square
, Circle
, Triangle
and all these classes are indeed Shapes. That means we can define an interface here!
interface ShapeInterface
{
public function area();
}
That's really all we need. A Shape must simply implements an area
method to calculate its surface area.
Then of course you need to implement this interface and the method.
class Square implements ShapeInterface
{
public $width;
public $height;
public function __construct($height, $width)
{
$this->height = $height;
$this->width = $width;
}
public function area()
{
return $this->width * $this->height;
}
}
class Circle implements ShapeInterface
{
public $radius;
public function __construct($radius)
{
$this->radius = $radius;
}
public function area()
{
return $this->radius * $this->radius * pi();
}
}
You should begin to see where we are going here π
In your Calculator class, it's going to be a lot easier.
class AreaCalculator
{
public function calculate($shapes)
{
foreach ($shapes as $shape) {
$area[] += $shape->area();
}
return array_sum($area);
}
}
Using the demonstrated approach, when we need to extend our application by providing a new kind of Shape
, we will be able to do just that and actually never even touch AreaCalculator
again. The class is Open-Closed. Open for extension. Closed for modification.
You also see that this principle works really well with the Single Responsability Principle. SOLID is designed to work all together, and the principles share many similarities.
I consider myself as an IT Business Artisan. Or Consultant CTO. I'm a self-taught Web Developper, coach and teacher. My main work is helping and guiding digital startups.
more about meBTC
18SY81ejLGFuJ9KMWQu5zPrDGuR5rDiauM
ETH
0x519e0eaa9bc83018bb306880548b79fc0794cd08
XMR
895bSneY4eoZjsr2hN2CAALkUrMExHEV5Pbg8TJb6ejnMLN7js1gLAXQySqbSbfzjWHQpQhQpvFtojbkdZQZmM9qCFz7BXU
2024 © My Dynamic Production SRL All rights Reserved.