Monday, April 5, 2010

Killing the private (and protected)

Recently on one forum I've found topic which released from memory my C++ days. That was topic about using "private" modifier on methods. The question there was about cases where to use it and why. Everybody knows when you are programming on C++ (as the most glaring example) one of "good practices" is "less client can do - better". Of course that's not in sense of functionality provided to client, but in mind of something which is not explicitly provided. In C++, I believe, the main reason for that is fragility of runtime, which can be easily killed if someone accidentally will do something wrong, which can also cause physical damage to person who is responsible for doing that (worth mentioning, in Java situation is slightly different, it's hard (but still possible, of course) to kill the application by "accidental coding"). And a consequence of such “good practice” is the basic rule – “make private as much as you can”.

That rule makes a good job in protecting object’s invariant and supporting encapsulation, but it has some disadvantages as well. First, it indicates that author most probably haven’t ever unit-tested that method and, second, which is more important for the topic, client of such code loses freedom of modification of library if he needs to (btw, some other techniques, like final classes, static members, “default” access modifier are doing the same thing). In the most it affects developers who use languages similar to Java. The way how Java developer works assumes that he spends lots of time in libraries’ code – understanding how they work, looking possible ways of customization, etc. The most of IDE now days are brilliant and I feel no difference in browsing my own code or library code. Moreover, if I don’t have source code, IDE will kindly decompile class for me. As a consequence of such close interaction with the library code, the situation when you want to fix/change/hack something in library is not very rare. For me that happens at least several times per year. And the one of the worst things I can see in that case is method I want to “modify” is private and I can’t change its behaviour by inheritance or implementation of other strategy. In that situation author of library had decided what is safe for me and what is not. I appreciate that, but would prefer to make decision myself.
Some can say that with loss of “private” modifier we are loosing benefits of encapsulation. I wouldn't be so sure about it. The same effect can be easily archived using other methods, like combination if pure Interfaces and Factories. And it works even better – client would never know instance of which class he is using, all he knows is just an interface.
The real problem of removing “private” is that we need to use something instead. The closest candidate is “protected” (I will not cover “default”, etc modifiers for simplicity reasons). Problem of “protected” is that such method is considered as part of interface. Commonly it is used as technique for implementing Template Method pattern. But the same effect can be achieved using Strategy, which provides less coupling, is more flexible in implementation, etc (see here) and as a result you will have class just with “public” methods.
All in all, I suppose, that ideal approach is to build systems based on interfaces and appropriate patterns, which will exclude the most of need for “private” and “protected” method modifiers. In that case, actually, I even do not worry about them J But ideal case usually never happens. As a general approach for other cases, I would suggest to avoid private as much as you can and use appropriate patterns instead. Also, it’s good to avoid protected as well, but if you can’t then state clearly, that these methods are not part of the interface and if client is going to override them, he is doing it on his own risk.

5 comments:

phil pirj said...

Hmmm! "physical damage"!
I would personally like to commit heavy physical damage to developers using 'private' instead of 'protected' in Eclipse and related projects, almost completely disallowing overriding of their poor code. Death to loosers!
Greets to Nata! Howdy?

Stas said...

Just curious, do you see much of poor code there? :)
All is cool! How are you?

phil pirj said...

Eclipse? Sure. I never digger deeper than I needed to, but these private methods are far than enough to commit murder (or suicide, depending on how accessible the author is).

I'm fine, too!
Spending my days working for uncle Fritz. Here are my funny and not so funny attempts to work on my own:
http://peerj.livejournal.com/32670.html

lauren said...

The declaration of a method to be private or not should be done with caution that can this need to be overriden in any of possible cases in future.If its very very specific then it can be private
e signature

Stas said...

@lauren. Very true. Should be considered really carefully. If there is no very good reason to do that, I would not put private.