Doesnt private members and methods inherently violate the open-closed principle?
Given that private
, protected
and public
modifiers are supported.
I came across this many times in codebases where developers use private
modifiers for members and methods for whatever reason which in turn requires me to copy entire blocks of code to be able to extend it.
I feel like many people just use private
out of habit because its use cases are very nieche in my opinion and almost all the time protected
does the job as well.
Best Answer
Thought experiment: imagine a component designed to be OCP-compliant, with certain extension points and public members, so it can be reused in a black-box fashion in several use cases. Imagine also the component has some or several private members.
Now, imagine the private members were all made public - then the same component would still be as reusable as before. So this makes it clear private members - at least technically - don't contribute to the OCP.
That still does not mean they violate the OCP. Nevertheless you are right - in real-world components, sometimes developers miss occasions for opening a possible extension point to the client by keeping something private, which should be made public. Usually, this involves more than just exchanging the keyword
private
bypublic
, but sometimes this is all what appears to be needed.However, one should not jump to the conclusion that it is better to make every member public in a reusable component "just in case". The OCP is usually only one of many goals you have to aim for when designing reusable components. Other typical goals are
to keep the component maintainable and evolvable,
to keep the number of breaking changes low when creating a new version
to keep the API of a component as simple as possible, so another dev has only to learn and understand the 5 public methods to use it and can ignore the 95 private methods which they don't care for.
And that's why private members are required - to keep the the impact of changes low, and the whole component comprehensible for a client. That's especially important when you don't know all the clients who are potentially reusing your component - by making a method or field private, you signal to them
you don't have to know what this method does when you just want to use this component
this part of the code might become subject to change at a later point in time
don't fiddle around with this member from the outside, you may accidentally break some invariant.
Hence, the design of reusable, long-living components is often a trade-off. If one
is 100% sure a component's source code will never-ever become subject to change, not even for a bug fix, and
does not care whether a component is used by clients in an anticipated "correct" way, or if clients may shoot themselves in the foot
then one may use only public members. But as soon as you want to provide updates and new releases, you have to find a balance between private and public members.