August 14, 2014

I am a fan of the SOLID principles, I think if you use them as guidance when you’re doing OOP you can deliver flexible, testable and scalable solutions.

That said, one of the principles that I haven’t quite got totally to grips with is the Open-Closed Principle.

I was talking with a colleague and they had a very different interpretation than I did. Let’s have a look at each of them.

My Interpretation #

Take this class as an example (stolen from the Laracasts video).

class AreaCalculator { public function calculate(Square $square) { return $square->length * $square->height; } }

This class calculates the area of a Square , but it’s currently not very flexible and it violates the OCP because we’d have to modify the internals of the class every time we need to extend this class to calculate the areas for other shapes. Like this:

class AreaCalculator { public function calculate($shape) { if ($shape instanceof Square) { return $shape->length * $shape->height; } if ($shape instanceof Circle) { return 2 * $shape->radius * 3.14; } } }

Every time we want to calculate the area of a different shape, we need to modify the internals of the class. So to avoid breaking the OCP and to make this class never have to break the OCP again, I would do the following:

interface ShapeInterface { public function area(); } class Square implements ShapeInterface { public function area() { return $this->length * $this->height; } } class AreaCalculator { public function calculate(ShapeInterface $shape) { return $shape->area(); } }

This makes sense to me. I now consider this class to be open for extension, but closed for modification. Because we just need to implement an interface and we’re done.

My Colleague’s Interpretation #

You start with the same class:

class AreaCalculator { public function calculate(Square $square) { return $square->length * $square->height; } }

As far as I can understand, his interpretation of OCP is that the class already exists so you cannot modify the internals because it is closed for modification, but open for extension, you have to extend it to add functionality, like so:

class AreaCalculator { public function calculate($shape) { return $shape->length * $shape->height; } } class CircleAreaCalculator extends AreaCalculator { public function calculate($shape) { return 2 * $shape->radius * 3.14; } }

And if you do that for each new shape then you never have to modify the internals of any existing classes, thereby ensuring you don’t break existing functionality.

So what do people think? Which interpretation (if any) do you think is correct? What’s your interpretation?

35 Kudos