C# Class Inheritance and the Open/Closed Principle – Does it Violate?

copen-closesolid

I typically make all my methods private unless and until they need to be overriden by a sub-class. At that point I modify the base class to make that particular method protected virtual. Is it accurate to say that this is a violation of the "Closed to Modification" principal? If so, that would imply that I should choose protected virtual as my default (similar to Java, in which methods are virtual by default). Is that really what the OCP recommends?

Personally, such an interpretation seems a bit daft to me, but I want to know if I am missing something.

Best Answer

First, I think there's a fundamental difference between initial development (here of a base class) and later stages of development.

If you find yourself in the initial development category, you will often need some refactoring to make the base class accommodate its first subclass (sometimes add a parameter, split a method, etc...), so regarding a need refactoring, I wouldn't worry about the OCP at such an early stage.

Further, we cannot and should not try to foresee all possible and potential future uses of something; doing that is an anti-pattern in itself.

Also, there's a fundamental difference between internal classes and externally exposed classes. In the case of internal classes, they may well be all versioned together (e.g. in the same DLL), so there is no reason to disallow refactoring to accommodate new sub classes as the design evolves.

However, for externally exposed APIs that have the maturity of a number of sub classes (or third party plugins) already implemented (which also can be expected to be added to in different versioning units (e.g. different DLLs), one should take the OCP seriously: a better design will accommodate more third party sub classing without changes.

However, regarding externally exposed API's, we're better off using interfaces instead of sub-classing anyway. Subclassing seriously limits an implementors options by comparison with interfaces, while also complicating the interactions & dependencies between producers and consumers. Using an interface, we simply avoid the issue of whether to mark a method as virtual or not. When we choose interfaces, designs become more decoupled, all of which is the more in the spirit of the OCP.

Related Topic