At the Forge - Checking Your Ruby Code with metric_fu

By combining automated testing with automated code analysis, you can make your Ruby code easier to test and easier to maintain.

One of my favorite tools that comes with metric_fu is Flay, also by Ryan Davis, which looks for duplicate code. One of the key principles of good coding is DRY (don't repeat yourself), and Flay makes it easy to find places where your code could use some extra DRY-ness. By running:

rake metrics:flay

you will get a nicely formatted report showing the places where your code has exact duplicates (which are embarrassing and problematic enough) and structural duplicates. So, if you have the same variable assignment in multiple controllers, Flay will find those for you and will point to the need for refactoring. For example, the simple project on which I hadn't yet run Flay had three methods, each of which contained the following identical code:

if params[:filename].blank?
  flash[:notice] = 'No file was attached. Please try again.'
  redirect_to :back

If this sort of code appears three times in the same controller, it means some refactoring is in order. In this particular case, I can remove the problem by putting this code into a separate method and then by defining a before_filter:

before_filter :check_for_blank_filename,
     :only => [:residence_file_action,

Here is the method, which looks (not surprisingly) just like the code that was duplicated:

def check_for_blank_filename
 if params[:filename].blank?
   flash[:notice] = 'No file was attached. Please try again.'
   redirect_to :back

Re-running Flay indicates that I now have made my code DRY-er than before, increasing its readability and making it easier to test. Sure enough, the Flay score for this controller dropped from 392 to 221. The measures are meaningful only relative to one another, but it seems undeniable that the code is now better, and the numbers reflect that.

Flay can find subtler similarities as well, indicating where two pieces of code look similar to one another. For example, I had the following two lines in my code, in separate locations:

(name, telephone, address, url, email, category_string) =
    line.split("\t").map { |f| f.strip }

(company, telephone, address, url, email, category_string) =
    line.split("\t").map{ |f| f.strip}

Flay noted that this code is almost identical and can be refactored to be a bit DRY-er. Would I actually change this code? Maybe and maybe not, but at least I'm more fully aware of it, which is important in and of itself. If and when I spend time refactoring this code, Flay will point to the first and most necessary areas that need attention.


Finally, I should mention Reek, a tool written by Kevin Rutherford, which also is invoked by metric_fu. Reek looks for “code smell” or code that doesn't follow commonly accepted style. This includes finding code duplication (similar to what Flay does), as well as long methods and poorly named variables. It also tries to find cases in which a method sends more messages to another object than to itself, which it calls feature envy, and methods that contain more than five lines of code, which are flagged as long.

For example, regarding code I mentioned above, which read:

(company, telephone, address, url, email, category_string) =
    line.split("\t").map{ |f| f.strip}

Flay noticed that this code was duplicated. But beyond that, a one-letter variable name is almost always a bad idea, because it reduces the readability of the code. Sure enough, Reek will flag this code as having an “uncommunicative name” for the variable f.

Even if I'm not totally sold on “Reek-driven development”, as Rutherford describes on the Reek home page, Reek is a useful way to find potential problems and provide additional feedback on the program that I'm writing.


Because of its dynamism and flexibility, Ruby offers programmers the chance to do things that might lead to maintainability problems down the road. Fortunately, the Ruby community has produced a set of excellent tools for automated testing and analysis that make it possible to produce high-quality code that is easy for others to follow, test and maintain. metric_fu puts many of these tools into a single package, making it easy to run a variety of tests on your code.


Geek Guide
The DevOps Toolbox

Tools and Technologies for Scale and Reliability
by Linux Journal Editor Bill Childers

Get your free copy today

Sponsored by IBM

Upcoming Webinar
8 Signs You're Beyond Cron

Scheduling Crontabs With an Enterprise Scheduler
11am CDT, April 29th
Moderated by Linux Journal Contributor Mike Diehl

Sign up now

Sponsored by Skybot