Ruby on Rails

Railsのデザインパターンまとめ

更新情報
2021年4月15日
目次、参考文献を追加しました

この記事はRails Advent Calendar 2020の24日目の記事です。今月中旬に見てみたら24日だけ空いていたので参加を申し込みました。よろしくお願いいたします。

Railsアプリケーションのディレクトリ構成としては、大きくmodelsとcontrollers、viewsがあります。ここにコードを書いていくことになります。

実装が進むにしたがって問題になりやすいのが、Fat ModelやFat Controllerといったコードの肥大化に関する問題です。これは適切にデザインパターンを導入することで防ぐことができます。

この記事では、Railsにおけるデザインパターンとはなにか、その必要性やデザインパターンの一覧について書いていきます。

著者
ぜに/Hiroki Zenigami

Webエンジニア&プロダクトマネージャ←プログラミング教育で起業←東大院←熊本高専。 共著に「現場で使えるRuby on Rails 5」。

目次

Railsにおけるデザインパターンとは

Railsにおけるデザインパターンとは、モデルやコントローラ、ビューに頻出する実装パターンを、オブジェクト設計の原則にもとづいて抽象化したパターンのことです。

デザインパターンにしたがうことで、設計上の問題を防ぐことができます。

例:Formオブジェクト

たとえばFormオブジェクトというデザインパターンがあります。これはユーザからの入力を整形・検証して永続化するという役割を持ちます。この処理はコントローラに書かれがちですが、このことはFat Controllerにつながりやすいです。

Formオブジェクトを導入することで、Fat Controllerの問題を防げます。またFormオブジェクト単体として再利用性が上がったり、テストが書きやすくなるといった利点もあります。

デザインパターンはモデルやコントローラ、ビューにおける設計上の問題を防ぐことができます。

なぜデザインパターンが必要か

デザインパターンは、アプリケーションが大きくなるにしたがって起こりがちな設計上の問題を防ぐために必要になります。

代表的な問題がFat ModelやFat Controller、Fat Viewです。Railsはデフォルトでモデルやコントローラ、ビューを用意しています。用意されたこのファイル群だけにコードを記述していくと、オブジェクト指向設計の原則を守るのは難しいです。つまりコードが肥大化してしまいます。

こうなると拡張性や再利用性がなく、またテストも書きづらくなります。これを防ぐために、オブジェクト指向設計の原則に基づいてクラスを分割していく必要があります。

このクラス分割について、これまで開発者によって頻出パターンを抽象化されたのがデザインパターンです。Railsアプリケーションにデザインパターンを導入することで、Fat Modelをはじめとする設計上の問題を防ぐことができます。

前提

まず、デザインパターンを導入するときの前提として、オブジェクト指向設計の原則を忠実に守る必要があります。たとえばSOLIDの原則などです。原則を守りつつ、まずはRailsが用意したモデルやコントローラ、ビューのレイヤーにコードを書いていきます。このとき純粋はRubyオブジェクトを積極的に活用します。

こうしてコードを書いていた結果、パターンが現れたときに適切なデザインパターンの導入を検討します。デザインパターンの導入ありきにならず、まずはオブジェクト指向設計の原則と向きあうことが前提となります。

これについては@joker1007氏の『俺が悪かった。素直に間違いを認めるから、もうサービスクラスとか作るのは止めてくれ』でも詳しく書かれていますのであわせてお読みください。

デザインパターンは、オブジェクト指向設計の原則を守った上ではじめて導入します。

Railsのデザインパターン一覧

Railsのデザインパターンについて、各責務とディレクトリ名、関連Gemがあればそれを書いています。このブログに別途記事を書いているパターンについては、記事へのリンクも貼っています。

Decoratorオブジェクト

モデルに対するビューのロジックをカプセル化する責務をもちます。ビューにはモデルに関連するロジックがよく登場しますが、ビューからモデルにアクセスすると肥大化の原因になり、また再利用性がなくテストも書きづらくなります。Decoratorオブジェクトでこの問題を防ぐことができます。

項目
ディレクトリapp/decorators
関連するGemactive_decorator

Deliveryオブジェクト

通知に関するロジックをカプセル化する責務をもちます。RailsにはデフォルトでActionMailerというしくみがあります。ただ、最近はメール以外にもSlackやLINEなどのチャットツールに通知することもよくあります。こういった通知に関する処理をラップするのがDeliveryオブジェクトです。

項目
ディレクトリapp/deliveries
関連するGemactive_delivery

Formオブジェクト

ユーザからの入力を整形・検証して永続化する責務をもちます。ユーザからの入力を処理するのはコントローラの役割です。ただ、複雑な処理や複数の場所で行われる処理をコントローラに書くと、コードの肥大化といった問題の原因になります。Formオブジェクトで、この処理をカプセル化することができます。

項目
ディレクトリapp/forms
関連するGem-

loading...

Interactorオブジェクト

ビジネスロジックをカプセル化する責務をもちます。Interactorオブジェクトは、アプリケーションの一つのみのビジネスロジックをもちます。ビジネスロジックを一つしかもたないため、再利用性があり、テストも書きやすいです。二つ以上の処理はInteractorオブジェクトを組み合わせることで実現します。

同じような役割としてServiceオブジェクトがあります。ただServiceオブジェクトは定義があいまいで、オブジェクト指向設計の原則が守られづらいという問題があります。Interactorは役割が明確で、またGemによるルールのおかげもあり設計の原則を守りやすいという利点があります。

項目
ディレクトリapp/interactors
関連するGeminteractor

loading...

Policyオブジェクト

ビジネスルールをカプセル化する責務をもちます。たとえばユーザの役割に応じて処理を実行する権限をもつかどうかを判断したりします。Policyオブジェクトがないと、コントローラやビューがルールに関するロジックであふれてしまうことになります。

項目
ディレクトリapp/policies
関連するGempundit

Queryオブジェクト

ActiveRecord::Relationに対して結合や絞り込み、ソートなどの操作を行い、Relationを返す責務をもちます。Relationに対する複雑な操作や再利用性のある操作を分割することで、再利用ができるなどの利点を得られます。ActiveRecord::Base継承クラスのスコープ経由で呼び出すことで、依存関係が明確になり、また返却されるクラスも自明になるという利点があります。

項目
ディレクトリapp/queries
関連するGem-

loading...

Validatorオブジェクト

ActiveRecord::Base継承クラスのレコードを検証する責務をもちます。複数の場所で利用される検証ロジックを書くことで、再利用性などの利点を得られます。

項目
ディレクトリapp/validators
関連するGem-

Valueオブジェクト

値オブジェクトをカプセル化する責務をもちます。住所やメールアドレス、あるいは商品のレビューにおける星の数といった値オブジェクトを書くことで、再利用性などの利点を得られます。

項目
ディレクトリapp/values
関連するGem-

関連記事

loading...

View Componentオブジェクト

ビューをコンポーネント単位でカプセル化する責務をもちます。再利用性のあるビューを、ビジネスロジックごとカプセル化することで、再利用性などの面で利点を得られます。

項目
ディレクトリapp/view_components
関連するGemview_component

デザインパターンのスキルを身につける

Railsのデザインパターンは、いろんな開発の現場にとって重要なスキルです。実際の現場で開発することで、より高いスキルを身につけることができます。ただ、他の現場に出会うには準備が必要になります。

少しでも他の現場が気になるなら、あらかじめ転職サイト・副業サイトに登録しておくといいです。次の記事で、登録しておくべきサイトについて説明しています。

まとめ

RailsアプリケーションのFat ModelやFat Controllerといった設計上の問題は、デザインパターンを導入することで防ぐことができます。ただ、その前提としてオブジェクト指向設計について学び、その原則にしたがって設計する必要があります。

原則を守った上でデザインパターンを導入することで、アプリケーションが大きくなっても秩序のあるコードベースを保つことができます。

著者
ぜに/Hiroki Zenigami

Webエンジニア&プロダクトマネージャ←プログラミング教育で起業←東大院←熊本高専。 共著に「現場で使えるRuby on Rails 5」。

関連記事関連書籍人気記事
applis
エンジニアとしてのんびり暮らす
お問い合わせ
ご意見・ご質問やお仕事のご依頼などは下記よりお願いいたします
お問い合わせ
© applis