The purpose of private methods and when to use them

by Jason Swett,

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.

Wrong answer: “private methods are for breaking up tasks into smaller parts”

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.

Wrong answer: “private methods are for removing duplication”

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.

  1. Private methods help reduce the size of an object’s API
  2. 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 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 (Single Responsibility 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.

Takeaways

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.

9 thoughts on “The purpose of private methods and when to use them

  1. John Pitchko

    Your second point about safe refactoring helped me understand. Private methods are a safe way to decompose a large method into a collection of smaller ones. Thank you.

    Reply
  2. Henrik

    I think you have missed the point with the “wrong answers” you have found from the web.

    “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.

    I read the answers multiple times and neither says “the reason for the existence of private methods is to break up tasks into smaller parts”. Have you omitted some information from the answers?

    The answers are not in contradiction with the points you are describing in ‘The real purpose of private methods’. However, I think the main point of public/private is to understand separation of public interface and internal (private) implementation. Internal implementation can be safely refactored, if the public interface is properly tested.

    Again with the ‘private methods aren’t a code smell’ I think you are not providing enough information from the ‘wrong arguments’. If the ‘wrong argument’ said “do not use private methods, it indicates code smell, use public method instead” then I agree with you. But if the argument was like “many long private methods might indicate too many responsibilities within a class” then I disagree.

    As for the second argument “Private methods have too many dependencies because they directly access or modify internal state” cannot be understood without context. It seems like the context was to compare private methods vs private static methods.

    Reply
  3. Janis Rullis

    Haha! Thanks man! This was bothering me for years because all those regular answers just didn’t make sense. Knew about the scope but it didn’t hit me till now that the limited scope is great because it assures that all the calls are only in this class*. Duh :D.
    No need to go over the whole code base and change all the calls.

    * Those who uses them via reflectors are violators and cannot raise complains.

    Reply
    1. Morten Bork

      The article original premise is precise. The wrong answer is online. And it is right in this very article.

      Oh, the author is correct that you can have too many responsibilities in a public method.
      Very true.
      However having a private method shows that you already identified two responsibilities.

      Also the article is correct that you should test your code. Visibility is however not an indicator of if you should test it.

      You should always test your code.

      But private methods are a royal pain to test.
      Because you have to call them through the public API.

      So if you adjust your public API.
      You must be prepared to also adjust your private test cases.
      (As you cannot guarantee a modification in one won’t cause a problem another place in that class’ API.

      The only way to avoid this, but keep the practice of a private method is to move the content of a private method behind an interface, and dependency inject the method into the private method.

      But now, you have a private method, with one line of code…

      Just move it into your public method as a single line of code, to increase readability.

      This is why private methods are code smell.

      They are “half way” code components. A programmer was just too lazy to make his program testable.

      That is it. Please present any counter argument to this. Any at all.

      Reply
      1. Naofumi

        Thank you Morten. I really enjoyed your comment.

        I personally test private methods quite often and so I’d like to provide my perspective.

        > But private methods are a royal pain to test.
        > Because you have to call them through the public API.

        I totally agree on this, and this is why I often test my private methods.

        It’s easier to test when you work at a lower level. Testing through the orifice of a public API can be annoying and any errors will be harder to debug. Your perspective about malleability of the code was new to me, but it strongly rings true.

        > The only way to avoid this, but keep the practice of a private method is to move the content of a private method behind an interface, and dependency inject the method into the private method.

        Again totally agree on this, but maybe not in Ruby. In Ruby, calling a private method is simply a matter of doing the following. This makes it so easy to write tests for private methods, so instead of refactoring the code to use DI, you can just do this.

        “`
        [object].send(:method_name)
        “`

        In my opinion, this solves the issue well enough.

        An additional benefit is that with DI, there’s no way to ensure that another dev won’t inject that new interface into another one, since they are basically public. If you use private methods, it will shout “don’t use me” (although with Ruby, you technically can), so it maintains the original intent to prevent usage outside of the original class.

        So in summary, I would definitely be more careful about using private methods in languages that do not give use access to Ruby’s “sharp knives”. In Ruby though, I think private methods are almost always great!

        Reply

Leave a Reply

Your email address will not be published. Required fields are marked *