Rubocop error sleuthing

By | March 2, 2016

So, let’s say you’re a Ruby coder who uses Rubocop, the static code analyzer that monitors your coding style, and though your program runs fine, “Oh Look!” Rubocop has thrown you an error! And worse, it’s a mysterious error with a cryptic message! And let’s say this happens while you’re off-line and you can’t use the internet for help. What do you do?

Well you could shut the machine off, get a drink, and deal with it when more resources are available. But if it’s gnawing at you, and a drink is turning into drinking, it may be better to flesh out the error.

To isolate the problem (I recently experienced), here’s a test method:

#!/usr/bin/env ruby
def test_method
  puts
  puts
  puts
  puts
  puts
  puts
  puts
  puts
  puts
  puts
  puts
end

Here’s the error that Rubocop threw on this method:

Rubocop_test/test.rb:3:1: C: Method has too many lines. [11/10]
def test_method
^^^

Clear as mud, right? What does [11/10] mean? I don’t know. Rubocop doesn’t like my method, but it doesn’t tell me how to fix it.

So, let’s find this “Method has too many lines.” message. We go to our Rubocop directory and look for it:

Brookss-MBP:rubocop-0.37.2 $ grep -nr “Method has too many lines.” .

./lib/rubocop/cop/metrics/method_length.rb:21: format(‘Method has too many lines. [%d/%d]’, length, max_length)

It appears on line 21 of a program at the address:

./lib/rubocop/cop/metrics/method_length.rb subordinate to the Rubocop directory.

Method has too many lines, and we can see in the format of the message a max_length argument in the square brackets.

“Too many?” “Max_length?” We have to look at the code in method_length.rb to see if there’s a relationship.

$ less -N ./lib/rubocop/cop/metrics/method_length.rb

methodtest

Well that didn’t quite answer it. Let’s see if we can find something about this class MethodLength.

$ grep -nr MethodLength .

./config/default.yml:975:Metrics/MethodLength:
./config/enabled.yml:904:Metrics/MethodLength:
./lib/rubocop/cop/metrics/method_length.rb:10: class MethodLength < Cop
./lib/rubocop/cop/variable_force.rb:98: # rubocop:disable Metrics/MethodLength, Metrics/CyclomaticComplexity
./lib/rubocop/cop/variable_force.rb:125: # rubocop:enable Metrics/MethodLength, Metrics/CyclomaticComplexity

And there it is:

$ Less -N ./config/default.yml

974
975 Metrics/MethodLength:
976 CountComments: false # count full line comments?
977 Max: 10
978

That’s what that “10” in the error message means. Counting the lines in my test method, looks like I have 11. That’s what the “11” in the error message means!

Clarity! So I can fix my problem by refactoring my method to have 10 or fewer lines.

It turns out that the subject of optimal method length (number of lines) has been hotly debated for years. The Ruby Style Guide specifies – and Rubocop implements:

Avoid methods longer than 10 LOC (lines of code). Ideally, most methods will be shorter than 5 LOC. Empty lines do not contribute to the relevant LOC.

See this thread Method Size – Best Practices on point at Ruby-Forum.com for a number of persuasive perspectives.

Any standard in a fluid medium will accumulate a range of opinions. The goal is clarity and simplicity, however, when the parts become so small that they lose context, or require too much contextual reconstruction for them to make sense, clarity loses to diminishing returns from the increased effort required to comprehend the entire process.

It seems a little naive to expect that all models of reality, and components of those models, will fit into 10 line by 80 byte chunks. But what other observation would you expect from a naive Ruby novice?

 

Leave a Reply

Your email address will not be published. Required fields are marked *