4 Simple Rules for Ruby

@ericturnerdev

github.com/etdev

by Eric Turner

Sandi Metz様

@sandimetz

そもそも、なぜルールをつける?

Rule #1: 

クラス内のコードが100行を超えてはならない。

100行

Single Responsibility Principle

(単一責任の原則)

クラスの行数を減らす方法

  • クラスを二つに分ける
  • メソッドのあるべき場所を考え直す
  • 不要なコードを削除する

Rule #2: 

メソッド内のコードが5行を超えてはならない。

5行

  def price(weight, discount = nil)
    if weight <= 10
      return_price = 1
    elsif weight <= 20
      return_price = 2
    else weight <= 30
      return_price = 3
    end

    if discount
      return_price
    else
      return_price - discount
    end
  end

  # => price(5, 0.2) = 0.8
  # => price(25) = 3

コード2-1

Refactorしよう。

def price(weight, discount = nil)

  return_price = weight/10 + 1

  if discount
    return_price
  else
    return_price - discount
  end
end

 # => price(5, 0.2) = 0.8
 # => price(25) = 3

コード2-2

def price(weight, discount = nil)
  return_price = weight/10 + 1
  discount ? return_price - discount : return_price
end

 # => price(5, 0.2) = 0.8
 # => price(25) = 3

コード2-3

def price(weight, discount = nil)
  (weight/10 + 1) - (discount || 0)
end

# => price(5, 0.2) = 0.8
# => price(25) = 3

コード2-4

Rule #3: 

4つより多い引数をメソッドに渡すようにしてはならない。

4つ

コード3-1

def price(weight, color, length, witdh, height, discount = nil)
  ...
end

コード3-2

def price(weight, color, length, options = {})
  width = options[:width]
  height = options[:height]
  discount = options[:discount]
  ...
end

コード3-3

class Car
  attr_accessor :color, :weight, :length, :width, :height
  ...
end

def price(car)
  ...
end

メソッドを書く時に、なんの情報を渡したらいいかしっかり考えよう。

Rule #4: 

コントローラーではただ

1つのオブジェクトだけをインスタンス化できる。

1つ

RailsアプリのDashboardページを作ってみよう

Facadeパターンを使おう

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

すると、Controllerはどうなる?

class DashboardsController < ApplicationController
  before_filter :authorize

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

Viewの方は?

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

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

メリット

  • Controllerがすごく簡単になります。

  • テストしやすくなります。

  • 値がおかしくなった時にちゃんとエラーを返す。

復習しよう

1. クラス内コード100行まで。


2. メソッド内コード5行まで。


3. メソッド引数4つまで。


4. アクションでインスタンス化1つまで。

 

おわり?

ちょっと待って。

実はもう1つルールがある。

Rule #0:

いい理由があればRule 1-4を守らなくていい。

守らなくていい。

リソース

  • https://robots.thoughtbot.com/sandi-metz-rules-for-developers
  • http://www.amazon.com/Practical-Object-Oriented-Design-Ruby-Addison-Wesley/dp/0321721330
  • http://tech.a-listers.jp/2013/05/20/sandi-metz/