A problem with the way we declare private methods in Ruby is the fact that when a class gets larger and more private methods are added to it, we lose sight of whether we are looking at a private, protected or public method. This is because the private declaration is a few hundred lines above the method you are looking at. Some people use another level of indentation on private methods to loudly proclaim their privateness, but this just doesn’t do it for me. About half of us here at thoughtbot (ok, just a couple of us) prefer setting private methods explicitly by providing a symbol to the private call:
class Archive
def import
download
decompress
cleanup
end
def download
# ...
end
private :download
def decompress
# ...
end
private :decompress
def cleanup
# ...
end
private :cleanup
def another_public_method
# doing really cool stuff
end
end
The main advantage of this approach is that you always know the method’s visibility, not that it really matters in Ruby, but I digress. Some may say that it’s tedious to write, or that it clutters your class. If you believe that it is tedious to write, we have $EDITORs at our disposal.
Help me help you
Here’s what I did to make vim mark a method as private. Just place your cursor
below a method, and type <Leader>p
to privatize it:
function! Privatize()
let priorMethod = PriorMethodDefinition()
exec "normal iprivate :" . priorMethod . "\<Esc>=="
endfunction
function! PriorMethodDefinition()
let lineNumber = search('def', 'bn')
let line = getline(lineNumber)
if line == 0
echo "No prior method definition found"
endif
return matchlist(line, 'def \(\w\+\).*')[1]
endfunction
map <Leader>p :call Privatize()<CR>
But the advantages are twofold. For one, you always know if a method is private.
It also helps clean up your code because it affords you the opportunity to
decrease the vertical separation between the private method and the first time
it is invoked. When you are reading a method that calls the private method, it
is much easier to scroll a few lines down to see its definition (or just zt
in
vim) than it is to do a search for the method name, read the definition, and
then come back to the context where it was called.
A familiar pattern
Vertical distance in code is not a new concept. For example, it is good form to always declare local variables as close as possible to their first use, increasing legibility and decreasing ambiguity. Similarly, when we write unit tests it is important to keep any setup or fixtures close to where you exercise the code, so that your assertions or examples have a clear context. If we follow this pattern elsewhere, sometimes unconsciously, why not follow it for private methods as well?