Rails tips: Null Objectパターンでリファクタリング(翻訳)

概要

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

Rails tips: Null Objectパターンでリファクタリング(翻訳)

Null Objectパターンによるリファクタリングは、指定されたオブジェクトが存在するかどうかをチェックして、存在しなかった場合に指定の属性やメソッドのデフォルト値を返す操作に適用できます。このような操作ではif条件が必要になることが多く、そのままではコードが少々読みづらいうえにテストも少しばかりやりにくくなります。Null Objectパターンを使うことでコードが非常にシンプルになり、テストも簡単になります。

Null Objectパターンを使うメリットをわかりやすく示すため、次のような事例を考えてみましょう。UserPostという2つのクラスがあり、UserクラスのオブジェクトはPostクラス上で操作を行います。

class User < ActiveRecord::Base
  has_many :posts

  def latest_post_title
    post = posts.order('created_at DESC').first

    if post.present?
      post.title
    else
      "No posts yet"
    end
  end
end

「単一責任の原則」からほど遠いコードです。ここでは以下の操作を行っています。

  1. 最新のpostをフェッチする
  2. postが存在するかどうかをチェックする
  3. postが存在する場合はposttitleを表示する
  4. postが存在しない場合は適切な情報を表示する

こんなときはNull Objectパターンの出番です。まずは新しいオブジェクトを作成しましょう。

class NoPost
  def title
    "No posts yet"
  end
end

シンプルなロジックを備えた、ごくシンプルなRubyオブジェクトができました。それではUserモデルで以下を行ってリファクタリングしましょう。

  1. クエリを別のメソッドに切り出す
  2. NoPost Null Objectを用いて、最新のpostの代入を別のメソッドに切り出す
  3. メソッドの責務を「最新のposttitleを返す」シンプルな責務に変える

Userクラスにこれらを実装すると、以下のように明快かつ読みやすいクラスに変わりました。

class User < ActiveRecord::Base
  has_many :posts

  def latest_post_title
    lastest_post.title
  end

  private

  def latest_post
    find_latest_post || NoPost.new
  end

  def find_latest_post
    posts.order('created_at DESC').first
  end
end

User#latest_post_titleの内容が明快になり、if条件も消滅しました。もうひとつ重要な点は、このNull Objectに適切な名前をつけて、何がしたいのかが名前からわかるようにすることです。


Railsでお困りの方にお知らせ

知りたいことがありましたら、twitter または連絡用フォームにてお気軽にお問い合わせください。

Railsパターンの電子書籍を無料でダウンロード

もっと稼ぎたい方や会社をさらに発展させたい方へ: テスティングのスキルの重要性にお気づきでしょうか?テストを正しく書き始めることが、唯一のファーストステップです。無料でダウンロードいただける私の書籍『Introduction Rails patterns』をどうぞお役立てください。

関連記事

Railsの`Object#try`がダメな理由と効果的な代替手段(翻訳)

肥大化したActiveRecordモデルをリファクタリングする7つの方法(翻訳)

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

この記事の著者

hachi8833

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

hachi8833の書いた記事

夏のTechRachoフェア2019

週刊Railsウォッチ

インフラ

ActiveSupport探訪シリーズ