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.
Here are the rules:
@object.collaborator.valueis not allowed).
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.
Despite the large number of private methods we wrote, keeping classes short proved easy. It forced us 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.
Limiting methods to five lines per method is the most interesting rule.
end are all lines. In an
if block with two branches, each branch could only be one line.
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
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.
The four method arguments rule was particularly challenging in Rails, and particularly in the views.
View helpers such as
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.
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:
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
class DashboardsController < ApplicationController before_filter :authorize def show @dashboard = Dashboard.new(current_user) end end
<%= render 'profile' %> <%= render 'groups', groups: @dashboard.group %> <%= render 'statuses/form', status: @dashboard.new_status %> <%= render 'statuses', statuses: @dashboard.statuses %>
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
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.
We’ve been experimenting with Google Hangout for meetings such as daily standups with remote team members and interviews with remote candidates.
We concluded this experiment was a success.
It’s nice to have a recurring calendar invite to open, click “Join Hangout” and start talking.
Google Hangout is sometimes choppy over wifi. The settings need to change when we switch from laptop to monitor, so we often are without sound for a few seconds before changing the “FaceTime Camera (Built-In)” setting to “FaceTime HD Camera (Display)”.
We’ve noticed in longer meetings, we sometimes need to refresh the page if sound starts to get choppy, presumably to clear some buffering.
We’ve noticed during Hangouts that the sound captured by a Macbook Air’s internal microphones is often muffled. We generally have Macbook Pros for better performance of test suites, but there are a few of us who have Airs. We have started to fall back to phone calls for sound in those cases.
Overall, it’s always better to see someone’s face.
Written by Dan Croak.
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:
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.
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.
Written by Joe Ferris.
You’ve probably heard by now that we’ve launched a learning community for passionate Rails developers called Prime.
Since Prime is a subscription service, one of metrics we’re interested in is churn, defined as the percentage of total customers who cancel. Over the last 30 days, Prime’s churn has been 18%.
Estimates of what a “good” churn is vary. One broad survey of SaaS companies with less than $10M in revenues showed a median churn of 20%, while some blog posts insist that anything over 8% should be panic-inducing.
To gain some perspective and get advice, I reached out to a friend and former podcast guest, Brennan Dunn.
Brennan is creator of a successful SaaS app called Planscope, author of several excellent ebooks, and overall “good at making money on the internet” kind of guy.
Below, you’ll find a recording of our 40-minute chat. In it, we dig into Prime’s current stats (including subscriber count and revenue growth), and Brennan’s suggestions for how to improve the site. What started off as recommendations for reducing churn turned into a broader discussion of how to position the entire service. If you run a subscription service of your own, you’ll likely learn a thing or two from Brennan’s battle-tested advice.
Check it out!
If our discussion left you with further questions for Brennan, leave them in the comments below and perhaps we can convince him to respond.