Last month we talked about RuboCop, which analyzes your Ruby code and
nitpicks it. One of its most difficult to follow suggestions is to keep your
lines of code no longer than 80 characters.
The creator of rubocop, bbatsov, explained his perspective on his
We should definitely have a limit – that’s beyond any doubt. It’s common
knowledge that humans read much faster vertically, than horizontally. Try to
read the source code of something with 200-character lines and you’ll come to
I’m totally on board with the short lines train. For me, it only gets tricky
when dealing with nested stuff (examples to follow) which add a lot of space to
the left of the first character of code. For example:
puts "OMG I only have 64 characters to express something on " \
"this line! And now it's more like 'these lines' haha"
Often strings are the first thing to get chopped up, as in that example.
The only approach I thought of to deal with that is to organize my code
differently to not use many nested namespaces. That’s probably not the worst
idea, honestly, but I’m writing this post to share an interesting style I
observed in the wild (read: on github) that takes a whole nother approach:
# Excerpted from:
module Net; module SFTP; module Operations
@sftp = sftp
end; end; end
Huh! That’s a style I hadn’t seen before. RuboCop has many complaints about it,
and I don’t totally love the style, but it’s a very novel and neat way to do it,
and it certainly frees up columns to spend on your code if you’re planning to
stick to an 80 character limit.
One possible alternative is to define your namespaced class using this
@sftp = sftp
If you do that, you get 2 extra characters on each line. Sweet!
One problem: it sort of doesn’t work, at least not in the same way.
If you just look at that example, and imagine that you’re the Ruby interpreter
trying to figure out what this code means, how are you supposed to know whether
Operations are supposed to be classes or modules? You have
to already know by them being previously defined. If they haven’t been defined
yet, you are well within your right to raise a
RuntimeException to complain
that this constant hasn’t been defined yet, rather than try to guess.
Both of the earlier longhand examples were explicitly explaining what the type
of each namespace constant is. That pattern works whether you’re defining the
module or class in that moment, or “opening” a previously defined module or
class to add something new to it. This shorthand, while optimal for line length,
only works when opening previously defined constants.
One downside of this approach is that, by relying on all of the namespaces being
predefined, it becomes harder to test this class in isolation (it’s probably
possible to do it through some gnarly stubbing but, harder). You’re
also introducing some requirements about the order in which the files from your
code need to be loaded, which feels kind of fragile.
One possible upside comes to mind. When you follow the typical pattern of
writing out all the namespace modules and classes, you introduce some room for
error: what if in one file you write
class Operations by mistake (instead of
module Operations)? You’ll get an error. That’s not too bad, honestly.
I think 80 is usually enough but if you’re doing too many contortions to stay
in that box, try like 90 or 100, you’re still a good person.