and what hides behind it This is a second post (check the Single-responsibility principle ) on principles and what common foundation they all have. here SOLID Bertrand Meyer, 1988 Here is what Bertrand Meyers writes in his book “ ” where this principle originates from: Object Oriented Software Construction A class is closed, since it may be compiled, stored in a library, baselined, and used by client classes. But it is also open, since any new class may use it as parent, adding new features. When a descendant class is defined, there is no need to change the original or to disturb its clients. So he proposed using an . Not good at all. implementation inheritance Robert Martin, 1996 Poor Robert Martin is often blamed for what actually Bertrand Meyer proposed. No wonder, look what he wrote in his paper “ ”: The Open-Closed Principle 1. They [Modules, as well as classes] are “Open For Extension”.This means that the behavior of the module can be extended. That we can make the module behave in new and different ways as the requirements of the application change, or to meet the needs of new applications. 2. They are “Closed for Modification”.The source code of such a module is inviolate. No one is allowed to make source code changes to it. I realize that a good part of readers have read no further than that and stigmatized Robert Martin for using implementation inheritance. Well, it’s just an unfortunate naming. What follows is the elaboration of what he meant. And he’s quite clear about that: Abstraction is the Key. He demonstrates a simplistic example of a class depending directly on a concrete class: Client Server Client{ doSomeWork(){ ( Server())->run();}} class public function return new Obviously, when class will have to be replaced, is affected. So the moral of the story: introduce abstractions and let your clients depend on them, instead of concrete implementations. And it’s all about the , resulting in a bit of abstractions and quite a few of composable, loosely coupled and highly coherent implementations. Server Client correct decomposing of the problem space On a module level, this principle is applied best with an approach David Parnas described back in 1972. It enforces , while the Open-closed principle suggests extracting abstractions, thus enabling loose coupling. high cohesion Robert Martin, , , , 2003 2004 2013 2014 All the following years he has been striving to make clear his point of extending the behavior not via inheritance, but via swapping implementation of useful abstractions. Not very successfully: in 2017, . some still don’t get it Class parameterization I’ve listed two ways of introducing new classes without modifying existing code. The first one is using inheritance, which is discouraged, and the second one is extracting new interfaces so that they can be injected in a class. The third way is class parameterization, if I can call it so. It’s very close to introducing new abstractions, but it’s about injecting data instead of behavior. Consider the following example. I have a class that calculates employers’ salary. There could be different strategies, and this is reflected as the following (an example is simplified to stress the point): SalaryService{ = 0.07; class const TAX **private $salaryStrategy**; **public function** \_\_construct(SalaryStrategy $salaryStrategy) { $this->**salaryStrategy** \= $salaryStrategy; } **public function** calculate() { **return** $this->**salaryStrategy**\->calculate(**self**::**_TAX_**); } } So when a new strategy emerges, I won’t need to modify a class. It means that OCP is not violated with respect to this requirement. But then you’re told that a tax changed — so you need to reflect it in a code. Would it be a violation of the Open-closed principle? Sure, since you need to modify existing code. What options do you have? Simple constant doesn’t represent any behavior, it represents data. Though you still can inject it via an argument, say, constructor parameter: SalaryService SalaryService{ ; ; class private $salaryStrategy private $tax **public function** \_\_construct(SalaryStrategy $salaryStrategy, $tax) { $this->**salaryStrategy** \= $salaryStrategy; $this->**tax** \= $tax; } **public function** calculate() { **return** $this->**salaryStrategy**\->calculate($this->**tax**); } } Violation of the Open-closed principle The code above doesn’t violate OCP in the context of a newly emerged requirement. Basically, there is no such thing like just “violation of the Open-closed principle”. It can be violated only for some set of requirements. So the first version of could have been aligned with the Open-closed principle for years, right until the moment when the tax changed. SalaryService Every time you need to implement new requirement and you modify existing code, it’s OCP violation. Of course, you can’t find out all your abstractions in advance — just because you can’t find out all the requirements in advance. So violating the Open-closed principle is OK — only if you’re extracting new abstractions, of course. Summing it up If any behavior, which is a part of some class, can change, then its implementation should hide behind an interface. This has a name already — it is . But it can’t come up purely mechanically, by extracting a couple of interfaces. It all starts with . loose coupling domain decomposing