giant robots smashing into other giant robots

Written by thoughtbot

calebjthompson

Sandi Metz’ rules for developers

Back in January, Sandi Metz introduced her rules for developers in a Ruby Rogues podcast episode episode. Around the time Sandi’s rules were published, the team I am on was starting a new project. This post details the experience of that team applying Sandi’s rules to the new application.

The rules


There are four lights.
There are four rules.

Here are the rules:

  1. Classes can be no longer than one hundred lines of code.
  2. Methods can be no longer than five lines of code.
  3. Pass no more than four parameters into a method. Hash options are parameters.
  4. Controllers can instantiate only one object. Therefore, views can only know about one instance variable and views should only send messages to that object (@object.collaborator.value is not allowed).

When to break these rules

Paraphrasing Sandi, “You should break these rules only if you have a good reason or your pair lets you.” Your pair or the person reviewing your code are the people who you should ask.

Think of this as rule zero. It is immutable.

100-line classes

Despite the large number of private methods we wrote, keeping classes short proved easy. It forced us to consider what the single responsibility of our class was, and what should be extracted.

This applied to specs as well. In one case, we found a spec file ran over the limit which helped us realize we were testing too many features. We split the file into a few, more focused, feature specs.

That made us realize that git diffs wouldn’t necessarily show us when we exceed 100 lines.

Five lines per method

Limiting methods to five lines per method is the most interesting rule.

We agreed if, else, and end are all lines. In an if block with two branches, each branch could only be one line.

For example:

def validate_actor
  if actor_type == 'Group'
    user_must_belong_to_group
  elsif actor_type == 'User'
    user_must_be_the_same_as_actor
  end
end

Five lines ensured that we never use else with elsif.

Having only one line per branch urged us to use well-named private methods to get work done. Private methods are great documentation. They need very clear names, which forced us to think about the content of the code we were extracting.

Four method arguments

The four method arguments rule was particularly challenging in Rails, and particularly in the views.

View helpers such as link_to or form_for can end up requiring many parameters to work correctly. While we put some effort into not passing too many arguments, we fell back to Rule 0 and left the parameters if we couldn’t find a better way to do it.

Only instantiate one object in the controller

This rule raised the most eyebrows before we started the experiment. Often, we needed more than one type of thing on a page. For example, a homepage needed both an activity feed and a notification counter.

We solved this using the Facade Pattern. It looked like this:

app/facades/dashboard.rb:

class Dashboard
  def initialize(user)
    @user = user
  end

  def new_status
    @new_status ||= Status.new
  end

  def statuses
    Status.for(user)
  end

  def notifications
    @notifications ||= user.notifications
  end

  private

  attr_reader :user
end

app/controllers/dashboards_controller.rb:

class DashboardsController < ApplicationController
  before_filter :authorize

  def show
    @dashboard = Dashboard.new(current_user)
  end
end

app/views/dashboards/show.html.erb:

<%= render 'profile' %>
<%= render 'groups', groups: @dashboard.group %>

<%= render 'statuses/form', status: @dashboard.new_status %>
<%= render 'statuses', statuses: @dashboard.statuses %>

The Dashboard class provided a common interface for locating the user’s collaborator objects and we passed the dashboard’s state to view partials.

We didn’t count instance variables in controller memoizations toward the limit. We used a convention of prefixing unused variables with an underscore to make it clear what is meant to be used in a view:

def calculate
  @_result_of_expensive_calculation ||= SuperCalculator.get_started(thing)
end

Great success!

We recently concluded our experiment as a success, published results in our research newsletter, and have incorporated the rules into our best practices guide.

Written by Caleb Thompson.

jferris

Ruby Science: You down with OCP?

Yeah, you know me.

We just pushed the latest update to Ruby Science, including five new chapters. Previous purchasers and Prime subscribers can grab the update on Learn.

New chapters this week discuss:

  • Using the Single Responsibility Principle to create readable, reusable classes.
  • Applying the Open/Closed Principle to reduce churn and prevent breakage while keeping objects easy to change.
  • Applying the Dependency Inversion Principle to create flexible, reusable objects.
  • Using the Law of Demeter to prevent application dependencies from becoming a tangled mess.
  • Choosing Composition Over Inheritance to make simpler, more flexible software.

The book is a work in progress, and is currently 230 pages long. Your purchase gets you access to the current release of the book, all future updates, and the companion example application.

Get your copy of Ruby Science today.

Now Available For Free With Learn Prime

We recently launched a service to help subscribers become better developers, called Learn Prime.

For just $99/month, you get ongoing access to everything we teach, including books like Ruby Science. You’ll even get access to all our in-person and online workshops. Get access to exclusive subscriber content and use the forum to ask thoughtbot your toughest Ruby, Rails, and refactoring questions.

Subscribe now.

Written by .

calebjthompson

Strong parameters as documentation

Besides moving attribute whitelisting to the controller rather than the model, Rails 4’s move to Strong Parameters over attr_accessible provides great documentation about the data with which records are being created.

    Your music is bad and you should feel bad    
strong_parameters are good and you should feel good

Here is an example of a controller many of us have written, using strong_parameters:

class CommentsController < ApplicationController
  respond_to :html

  def create
    @comment = Comment.create(comment_params)
    respond_with @comment
  end

  private

  def comment_params
    params.
      require(:comment).
      permit(:body).
      merge(user: current_user, commentable: commentable)
  end

  def commentable
    # find and return a commentable record
  end
end

Notice how the comment_params method tells you at a glance what object’s parameters this controller/action cares about (comment), the specific data being used (body), and the extra information being added. After glancing at the method, you hardly have to concern yourself with the rest of the class: everything just makes sense.

strong_parameters will be standard in Rails 4.0, but they can be used now in Rails 3.*.

Written by Caleb Thompson.

Episode 44: I feel the opposite of burnt out

In this week’s podcast, Ben Orenstein is joined by Chad Fowler, author, speaker, and CTO of 6wunderkinder. Ben and Chad discuss Chad’s recent move to Berlin and 6wunderkinder, what a CTO does, getting back to coding, the early Ruby community, who Chad wants to hire, predicting success of new hires, and what makes a truly good developer, favorite interview questions, how Chad’s interviewing process has changed over time, how age and experience can change your perspective, how Chad built a great team, and what he might write about in the future. They also discuss Chad’s new tattoo, his regrets, meditation, therapy, gaining control over your mind, and much, much more.

jferris

Ruby Science Redesigned

We just pushed a new design for Ruby Science. Previous purchasers and Prime subscribers can grab the update on Learn.

The new design includes a new layout, which is much more appropriate for a book. We updated the typeface and font size to improve the experience when reading the book on a screen as opposed to a printed page. The margin size is also greatly reduced, making it easier to zoom in on a laptop screen and bring the text right to the edges.

Before and After

Get your copy of Ruby Science today.

Now Available For Free With Learn Prime

We recently announced the launch of our subscription service: Learn Prime.

For just $99/month, you get ongoing access to everything we teach, including books like Ruby Science. You’ll even get access to all our in-person and online workshops. Get access to exclusive subscriber content, as well as access to our private Campfire room, where you can get live help from thoughtbot designers and developers.

Subscribe now.