Certain concepts in programming seem to suffer from a poor understanding among many programmers. Private methods are one of those concepts. Mistaken and confused advice on this topic abounds online.
In this post I’ll attempt to clear up some misconceptions regarding private methods as well as give my own conception of what private methods are for and when to use them.
The wrong answers you’ll find online
Before I describe my conception of private methods, I’ll discuss some of the wrong answers you can easily find online in hopes of inoculating you against their wrongness.
As of this writing, if I google for “purpose of private methods” and click on the first result, the following Stack Overflow answer comes up highlighted:
Private methods are useful for breaking tasks up into smaller parts, or for preventing duplication of code which is needed often by other methods in a class, but should not be called outside of that class.
It can’t be said that the reason for the existence of private methods is to break up tasks into smaller parts or prevent duplication, because both those things can be achieved with public methods.
Except for the last part which says “should not be called outside of that class” (which we’ll get to shortly), this answer is wrong.
Here’s another wrong answer, from the top answer on the second link on Google:
Private methods are typically used when several methods need to do the exact same work as part of their responsibility (like notifying external observers that the object has changed), or when a method is split in smaller steps for readability.
This is basically the same answer as the first, and it’s of course wrong for the same reason.
The real purpose of private methods
I’ve been making heavy use of private methods for years. To the best I’ve been able to determine, here’s why I do it.
- Private methods help reduce the size of an object’s API
- Private methods indicate what’s safe to refactor
Let me explain why each of these things is good.
Private methods help reduce the size of an object’s API
Complexity is the enemy of understandability. The simpler I can make my code, the easier it will be to understand, and therefore the cheaper my code will be to maintain.
Let’s imagine I have an object with 8 methods, all public. That means there are 8 different ways other parts of my program could potentially use my object, and 8 different ways that my object interfaces with rest of my program. All 8 of these interfacings are things I have to understand in order to understand my program.
You could loosely say that in the above scenario, I have an “understandability cost” of 8.
Now let’s imagine a different object which has only 2 public methods. It has some other methods too, but those are private. Now there are only two possible ways the rest of my program could use my object. This scenario has an “understandability cost” of 2.
I know that my “understandability cost” metric is silly and quite imprecise but I hope it illustrates the point. The smaller each object’s public API, the easier it will be to understand my object’s relationship with everything else.
Now let’s talk about refactoring.
Private methods indicate what’s safe to refactor
Every public method is susceptible to being called from some outside entity. If a method is being called from somewhere, I can’t delete the method or change its signature without also having to change every place where the method is called. The only thing I can do is refactor its contents.
Since private methods can’t be called outside the same class (not without some irresponsible hackery at least), I know that I’m free to refactor as much as I want and I won’t inadvertently break any outside code. It’s true that other parts of the same object might call my private methods and thus be affected by my refactorings, but it’s super valuable to know that I won’t have to look any farther than that.
Private methods aren’t a code smell
If you google around about private methods for more than about 30 seconds, you’ll find a number of posts exploring the question of whether private methods are a code smell.
Don’t buy it. The arguments that private methods are a code smell fall apart under the least bit of scrutiny. Every argument I’ve seen applies equally to public methods.
Here are the arguments I’ve seen:
- Private methods indicate that the class is doing too many things (SRP principle violation)
- Private methods have too many dependencies because they directly access or modify internal state
Both the above arguments could apply just as much to public methods. Public methods could indicate the class is doing too many things. Public methods can access internal state just like private methods.
When to use private methods
My rule for when to use private methods is very simple. If it can be private, it is private. In other words, I make all methods private by default, and only make them public if they need to be in order for my program to work.
Testing private methods
I wrote a whole separate blog post about testing private methods. The common question is: “should private methods be tested”?
My answer is yes, private methods should be tested, but only indirectly through their public methods.
In order for the public/private idea to work, private methods have to be private from all outside code, including test code. When tests directly call private methods, the private methods can’t be refactoring without also changing the tests, throwing away one of the main benefits of testing: the ability to refactor with confidence.
The two benefits of private methods are that they a) help reduce the size of an object’s API and b) indicate what’s safe to refactor.
Private methods aren’t a code smell.
If a method can be made private, it should be made private. Making a method public when it doesn’t need to be brings no advantage and only creates a liability.
Do test private methods, but only indirectly through their public interfaces.