Your Private Methods are None of my Business

A common sloppy mistake I see programmers making is to forget to declare a method as private when it’s only being used inside a class. This seems to happen more in Ruby, or maybe it just bothers me more because we don’t have interfaces. Rails ActiveRecord validation callbacks are a classic example where people often forget to do this.

It’s trivially easy in Ruby to call the private methods of another object if you really want to. There’s no intimidating ugly barbed-wire fence around them like there is in a language like C#, but there’s a fence nonetheless. And that fence is there not, as in other languages to aggressively prevent people from doing the wrong thing, but to politely suggest that they should not.

So polite. So very Ruby. Why would the author of a class want to make such a suggestion? Because that private method is part of the internal workings of the class, and they want to retain the right to change those internal workings without upsetting anyone. It’s all about encapsulation, and that encapsulation becomes extremely important as soon as you want to change that class.

Every time you code an object, you’re designing an API. The smaller that API, the safer it will be for someone to change that class. When I’m working in a class with a lot of public methods, I feel exposed, naked. The class is wandering around with its belly hanging out: “Look at my hairy gut! Give us a tickle!”.
Hairy-Belly-Man

When I want to change a class, the first thing I worry about is ‘how many classes will be affected if I make this change’? By marking a method as private, you are clearly telling me that I’m safe – that I’m inside the encapsulation boundary of the class and can refactor with impunity.

So in Ruby our classes may not wear iron-clad chastity belts like the statically-typed languages, but that doesn’t mean they shouldn’t preserve some modesty and keep themselves covered up as much as possible. Or am I just an old-fashioned prude?

Published by Matt

I write software, and love learning how to do it even better.

Join the Conversation

8 Comments

  1. Good point Matt! Most people even hardcore TDD programmers like myself tend to forget about protected and private methods … The best way to remember them I guess is to feel the pain, like renaming a method and getting insulted by people impacted by your change 😉

    Question, how do you test private & protected methods?

    To be as DRY as possible, I wrote this (source code extracted from http://github.com/garnierjm/dry-report/tree/master/spec/spechelper.rb)


    def changescopeofmethodtopublic(clazz, method)
    eval("class #{clazz}
    public(:#{method.to
    s})
    end")
    end

    then before calling a private / protected method:


    changescopeofmethodtopublic(DontRepeatYourself::SimianRunner, :parameterexcludes)

    I did that because the way I TDD is with very small methods (3-4 lines max) and very long and expressive names (viva La Autocompletion!). Sometimes I stub these small methods to go straight to the behavior I want to implement. Most of the times, it’s a 5-10 minutes job to write the specs for these tiny methods and make them pass …

Leave a comment

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