Private Method Anti(?)-Pattern

06 May 2008

Some (actually quite a long) time ago, Szczepan asked if private methods are an anti-pattern and I've been promising him ever since to post a reply. The reasoning behind his statement was derived from the fact that TDD purists often maintain that untestable code is very likely bad code. Private methods are hard to test and it therefore seems to follow naturally that they, too, are a sign of bad code. While I'm sure that this is true in some cases, I think there are a lot of good reasons to have private methods or classes.

Implementation vs. Behavior

Many developers focus too much on implementation details when they write tests. Ask yourself what you really care about a class: implementation details or behavior? It turns out that in most cases, one is only interested in the latter. So when writing tests, we should focus more on the public API of a class and not about its internal structure.

Modularization vs. Encapsulation

In summary, I agree with Szczepan when he says that there is probably a lot of code out there in which private methods could be factored out into public classes or methods which would, in turn, increase code modularity. Often, however, encapsulation and a lean public API might be favored over modularization. More importantly, modularization might not always be needed, and therefore complicate and bloat the codebase unnecessarily. If modularization is still required at a later stage, internal code can be refactored and made public without breaking existing code.

Are You Over-Mocking?

Stubbing and mocking techniques and tools, especially Mockito, are great and make perfect sense in many situations (e.g. faking a network connection, a database, a service etc.). Breaking up a public method that consists of n private methods into n public methods of n new classes only so that we can test that the methods are indeed invoked, however, introduces unwanted complexity and completely breaks encapsulation principles, without yielding any real benefits.

Don't Defend Yourself!

Private methods and classes are also a good thing because they allow to code non-defensively, which will make code simpler. As soon as logic is offered to the world as a public method, one needs to ensure that the implementation also caters for unexpected scenarios. If the implementation is private, on the other hand, it is easy to determine that a certain variable will never be null, for example, and can thus be safely ignored.

Public APIs are Contracts

The API of a class (i.e. it's non-private methods) represents a contract with whoever is going to use it. Sure, as long as the class is used only within a single source repository this might not be a big issues, because powerful refactoring tools make it easy to change the contracts. But what happens if code is being used externally - maybe because other people find it useful, too? It won't be possible to change public method signatures that easily anymore, because other code will have been built on top of them.

Reduce Public API complexity

Private methods and classes can greatly reduce the complexity of a public API. Compare the Java API and its source code, for example. You'll realize that a lot of complexity is encapsulated in private methods and classes, which is a good thing, because it keeps the public APIs complexity low(er(-ish)).

To sum up...

Although these are very much thoughts-in-progress, I think that in summary:
  • We focus too much on implementation details and not enough on externally observable behavior of a class when writing tests
  • We often create code that is unnecessarily modular, because we are test-obsessed
  • We often mock too much (probably as a consequence or mutual reaction of the above two points)
  • We often create APIs that expose too much and therefore break encapsulation