Good Practices and Style Guides in Ruby on Rails

I’ve been working on a big project, with a lot of legacy code from versions like 2.9 or 3.2. After enrolling the team I found out that they where not using any style convention or following any style guide. I’ve tried to ask them to use a style guide to ensure the code is properly formatted and easiest to read and understand. I found out a great opposition in this task, they seem to be pretty convinced that anyone should be able to read something like:

this_hash = {[“is”] => :a, total: “mess”}

After reading this comment my next question was: Why someone will create a hash like this one with an array as a key. No one was able to answer me. But anyway I found out that I’m actually able to read this and understand the code. The problem was that I don’t want to be able to understand this kind of things in a code that should be easy, DRY and clean.

When I started this career I decided that good practices was the first thing I needed to know, and keeping that in mind I will share with you what I’ve been reading about this topic:

http://it-ebooks.info/book/267/
https://github.com/styleguide/ruby
http://www.zenspider.com/Languages/Ruby/QuickRef.html

And some easter eggs:

Scalability – the Human Factor

The larger and more complex a system, the more it has to be broken down into small logical parts, to make it easily understandable. Each part should be it’s own “world”, providing tightly-controlled access to its state. Correct understanding of the code is the first step to accurate time- and complexity- estimation of new changes.

Good vs Bad Laziness – Code for the Common Case

Bad laziness is where you want writing code to be easy, but don’t spend enough time making the code easy to read – by humans that is. Code will be read by humans more often that it is written by them, so you want to optimize for the common case, i.e. readability. To be effective as a team-player, you must communicate to other developers through readable code. You are not only writing for the computer.

Learn how to be a lazy and impatient reader of code – this will make you a better writer of readable code.

Descriptive Naming

Names should say something about one more more of the following:

  • What a thing is (applies mostly to variables, classes, modules, interfaces)
  • What a thing does (especially methods, but also classes, etc)
  • The purpose of the thing

Avoid using meaningless variable names (e.g. one-letter) unless the scope of variable is very small and very little is done with it.

Avoid accessing arrays using hard-coded indexes, except to store the values into well-named variables. E.g.:

# hard to read
fields = fetch_fields()
process_name(fields[0])
process_address(fields[1])

# ok - for languages that can't auto-splat an array
fields = fetch_fields()
name = fields[0]
address = fields[1]
process_name(name)
process_address(address)

# better, with auto-splat
name, address = fetch_fields()
process_name(name)
process_address(address)

If you really want to access by index, put the index numbers into well-named constants, then access via the constants.

Tips for Refactoring

If you have a long method, write down in plain English what the method does. Then use those descriptions to write small methods that the original method can call.

When adding new logic, ask yourself whether it’s the current class’s (or module, etc) responsibility. If it doesn’t feel right, look for another class to add it to, or create a new class.

Limit the Number of States

The more states a method has to deal with, the harder it is to test. A method should not use a large number of instance variables or local variables. Each new variable-access you introduce has a multiplicative effect on the total number of states the method can be in. If there are too many states, you should break the logic into smaller methods.