Ruby’s "private" Keyword is Not Heresy
Giles just wrote a post regarding the "private" keyword’s "unprofessionalism" (I’m having Christian Bale flashbacks) that included a conversation we had on Twitter. Unfortunately, Twitter isn’t exactly a great medium for expressing complex thought, so I figured I’d elaborate the issue a little bit without phrasing things for a 140-character limit.
Privacy is not Real
First let’s be honest, Ruby doesn’t actually have "private" methods, semantically speaking. It’s wildly easy to change the visibility of any method, or just call it directly without such a visibility change. It’s not 100% transparent, but it’s also completely trivial. The distinction between a private/public method is mostly an informational one, with a small bit of extremely minor syntax sprinkled in.
I can see how the visibility distinction matters in Java, and perhaps for that language, he might have a better case. But Ruby is not Java, and no, Ruby’s "private" is not meant to emulate Java’s "private". Private visibility in Ruby is not stopping you from doing anything, it’s simply a way to make you aware of your potentially bad actions. While I agree with Giles that nobody should force me to code a certain way, I’d say we’re on the wrong track if we don’t even have a mechanism to guide people in the right direction. The syntactic distinctions you get by using private in Ruby are meant to "guide" you by making it "more annoying", but it does not stop you. I think this is a good thing, and I don’t think it is unprofessional.
In any event, the point I was making in my Twitter responses to Giles was that the "private" keyword is used to give methods the same "DANGER AHEAD" notice he talked about:
Giles and I are basically in agreement that there is a place for such a warning. The only difference is that I believe the "private" keyword in Ruby is the perfect way to succinctly describe such a warning—more importantly, I believe it’s the entire point of having the keyword in the first place. His solution is to put the methods in separate files but keep them public. This works too, but there is no significant semantic difference in either approach. Remember, private methods can be generated in documentation just like public methods can, and the source is modifiable no matter what filename it lives in, so nothing’s really being hidden.
Personally, I think making use of the keywords make for cleaner code, in terms of logical organization of source, but that’s me. I see a "private" method as a much easier way to say "danger ahead" than move it to a separate file, or add extra source level comments all over the place. This is why I support the new "private_constant" proposal that’s being introduced in 1.9.3, because it adds the same reflective information that methods currently benefit from to constants (classes, modules included). I’d rather say "private_constant :Foo" and get that reflection in the REPL than document it manually with a source level comment. I don’t mind Giles’ approach, so long as he doesn’t think I’m a heretic for making use of Ruby’s functionality to achieve the same thing.
On a sidenote, I’m not sure where Giles got the complaint about indentation from. The private keyword does not mess with indention unless you choose to add extra useless indentation to your code. The following is perfectly valid (and how it’s meant to be used anyway):
class Foo def a; end private def b; end end
See. No extra indentation.