Ruby: 条件を切り出していい感じのメソッド名を付けよう(翻訳)

概要

原著者の許諾を得て翻訳・公開いたします。

Ruby: 条件を切り出していい感じのメソッド名を付けよう(翻訳)

シンプル(かつ効果の高い)リファクタリング手法のひとつといえば、メソッドへの切り出しがあります。切り出したメソッドに名前を付ける手法は、コードの背後に潜むアイデアを示すうえで有用なツールです。

次のようには書かないこと

条件にステートメントをごちゃごちゃ書く。

class BrightonCoffeeShop
  def initialize(name)
    @name = name
  end

  def good?
    if @name == 'Starbucks' || @name == 'Costa' ||
       @name == "Barry's Caff"
      false
    elsif @name == 'Coffee@33' || @name == 'Small Batch'
      true
    else
      false
    end
  end
end

この実装が、nameが不明な場合にfalseを返すことはもう見え見えです。あなたがこの喫茶店で満足にくつろげるようにする唯一の方法は、わけのわからないルールを排除することです。

次のように書くこと

「メソッドの切り出し」リファクタリング手法を用いて、ロジックをprivateメソッドに移動し、コードのコンセプトを的確に表すメソッド名を付ける。

class BrightonCoffeeShop
  def initialize(name)
    @name = name
  end

  def good?
    clean? && local? && excellent_coffee?
  end

  private

  def clean?
    !filthy?
  end

  def excellent_coffee?
    ['Coffee@33', 'Small Batch'].include?(@name)
  end

  def filthy?
    @name == "Barry's Caff"
  end

  def local?
    !national_chain?
  end

  def national_chain?
    ['Starbucks', 'Costa'].include?(@name)
  end
end

そうすべき理由

メソッドを切り出して定義することで、メソッドに名前を付けます。上の#good?メソッドは、よい喫茶店かどうかを判断するための基準を示します。この新しいprivateメソッドは、クラスのドキュメントとしても機能します。

修正前のコードでは、「よい」喫茶店と「よくない」喫茶店のリストしかなく、このリストがどのように形成されたのかという知識も示されていませんでした。

このクラスに対する初歩的なリファクタリングとして、GOODBADという配列にそれぞれよい名前と悪い名前のリストを詰め込み、喫茶店のnameをそれでチェックするという方法もないわけではありません。しかしその方法では、その喫茶店がよい理由も悪い理由も見えなくなってしまうでしょう。しかもその理由こそが、このコードで最も重要な部分なのです。

修正後のコードでは、#clean?(清潔)や#local?(地元)といったポジティブな評価基準だけではなく、#filthy?(不潔)や#national_chain?(全国チェーン)といったネガティブな評価基準についても切り出しました。このおかげで、#good?メソッドのネガティブバージョンをprivateメソッドに用意しなくても済みます。少々やりすぎに思える部分かもしれませんが、このクラスでは満足の行く喫茶店に対する肯定的な評価の方を強く重視しているのですから、これによって有用なコンテキストが付け加えられます。

リファクタリングの手法が何であれ、リファクタリング前には最初の実装をカバーするよいテストをしっかり書いて、機能がうっかり変わらないようにしておきましょう。

そうするべきでない理由があるとすれば

上よりももっとシンプルな例であれば、このリファクタリングを行うまでもないかもしれません。しかしそれでもドキュメント作成の有用な手法でもあり、条件のロジックを明確化できます。

上よりもさらに複雑な場合(喫茶店に対して良否以外にも多くの要件を課すなど)は、個別の喫茶店をサブクラス化する形でリファクタリングするとよいかもしれません。

はてブより

http://b.hatena.ne.jp/entry/365471498/comment/tkmkg8m

関連記事

Rubyのクラスメソッドがリファクタリングに抵抗する理由(翻訳)

Rails tips: テストから共通機能を切り出すリファクタリング(翻訳)

デザインも頼めるシステム開発会社をお探しならBPS株式会社までどうぞ 開発エンジニア積極採用中です! Ruby on Rails の開発なら実績豊富なBPS

この記事の著者

hachi8833

Twitter: @hachi8833、GitHub: @hachi8833 コボラー、ITコンサル、ローカライズ業界、Rails開発を経てTechRachoの編集・記事作成を担当。 これまでにRuby on Rails チュートリアル第2版の半分ほど、Railsガイドの初期翻訳ではほぼすべてを翻訳。その後も折に触れてそれぞれ一部を翻訳。 かと思うと、正規表現の粋を尽くした日本語エラーチェックサービス enno.jpを運営。 実は最近Go言語が好き。 仕事に関係ないすっとこブログ「あけてくれ」は2000年頃から多少の中断をはさんで継続、現在はnote.muに移転。

hachi8833の書いた記事

週刊Railsウォッチ

インフラ

ActiveSupport探訪シリーズ