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.
Flay

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
  return
end

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,
               :advertiser_file_action,
               :whitepage_listing_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
   return
 end
end

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.

Reek

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.

Conclusion

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.

______________________

Webinar
One Click, Universal Protection: Implementing Centralized Security Policies on Linux Systems

As Linux continues to play an ever increasing role in corporate data centers and institutions, ensuring the integrity and protection of these systems must be a priority. With 60% of the world's websites and an increasing share of organization's mission-critical workloads running on Linux, failing to stop malware and other advanced threats on Linux can increasingly impact an organization's reputation and bottom line.

Learn More

Sponsored by Bit9

Webinar
Linux Backup and Recovery Webinar

Most companies incorporate backup procedures for critical data, which can be restored quickly if a loss occurs. However, fewer companies are prepared for catastrophic system failures, in which they lose all data, the entire operating system, applications, settings, patches and more, reducing their system(s) to “bare metal.” After all, before data can be restored to a system, there must be a system to restore it to.

In this one hour webinar, learn how to enhance your existing backup strategies for better disaster recovery preparedness using Storix System Backup Administrator (SBAdmin), a highly flexible bare-metal recovery solution for UNIX and Linux systems.

Learn More

Sponsored by Storix