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!”.
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?
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.tos})
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 …
I agree in general, but in every particular case I end up too lazy to write specs that do things like model.send(:methodname) instead of model.methodname.
On the subject of testing private methods, I’m with Michael Feathers and Pat Maddox: If you feel the need to do it, you probably have a concern you need to separate into another class.
The picture is fucking disgusting.
@me – so is your language! Code that isn’t sufficiently encapsulated can be rather distateful too, IMO – that’s the point! 🙂
Don’t listen to that jerk, the picture is beautiful! 🙂
I agree, the picture is disgusting. I’m about to puke my lunch!
You HOT>.. I’d lick that furry body all night long!