I think the way private methods are defined, is one of Ruby’s few weaknesses. The main problem being that they separate the private methods from the methods that use them. For example, I prefer this:
internal_method(1)
end
def two
internal_method(2)
end
def internal_method(n)
n
end
def three
other_internal_method(3)
end
def four
other_internal_method(4)
end
def other_internal_method(n)
n
end
To:
internal_method(1)
end
def two
internal_method(2)
end
def three
other_internal_method(3)
end
def four
other_internal_method(4)
end
private
def internal_method(n)
n
end
def other_internal_method(n)
n
end
Because the former keeps the internal_method code close to the methods that use it.
This issue is minimised if we keep classes small, but that’s not always as easy as it sounds.
I’m also not particularly convinced about most arguments for making methods private. It takes a much more far sighted developer than me, to be sure that a method that I currently only use internally, won’t be useful externally later.
I’d also be more convinced of the necessity to privatize methods if accessing private method was particularly hard, but it is not: send(:private_method)
It is also worth considering what is being written. If the code is part of a shared library (a gem for example), there is a more convincing argument for privatizing methods. However, if the Ruby code is written as part of a monolithic application (a Rails app for example), then I think the argument is far less convincing.
Surely the only good reason for using a private method, is where the logic is only valid within the context of the current object, and using it outside that context is likely to result in errors. That is, external use will break things.
For example where I do use private methods is in Rails controllers, where public methods could accidentally be exposed by a routing error causing security vulnerabilities and unexpected usage. If only the action methods are public, this vulnerability is greatly reduced.
In summary, I’d say that a method should only be private if using it externally breaks something. If calling it externally doesn’t break anything, why restrict its use unnecessarily.