0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

Railsでファットモデル・ファットコントローラーを避ける設計(Service Object)

0
Posted at

はじめに

Railsで開発をしていると、機能追加のたびにControllerやModelへ処理を書き足していき、気づけば1ファイルがかなりの行数になっていたという経験はありませんか。

いわゆる「ファットコントローラー」「ファットモデル」と呼ばれる状態です。

こうした状態への対策として「Skinny Controller, Fat Model」という考え方がよく紹介されます。ただ、この言葉をそのまま受け取って「Controllerを薄くするためにModelへ全部書けばいい」としてしまうと、今度はModelが肥大化するだけになってしまいます。

実際には、ControllerやModelだけで処理を抱え込まず、責務に応じて適切な場所へロジックを分割することが大切です。

この記事では、ファットモデル・ファットコントローラーを避けるための代表的な設計パターンの一つであるService Objectについて整理してみます。

Service Objectとは

Service Objectは、特定のユースケースに関する処理を専用のクラスへ切り出すための設計パターンです。

例えば、

  • 注文を作成する
  • 決済を行う
  • 会員登録とメール送信をまとめて行う

のように、複数のモデルや外部サービスをまたぐ処理を書くときによく利用されます。

Controllerに書くには複雑で、複数のModelや外部サービスにまたがる処理を切り出したい場合に向いています。

一般的には app/services 配下にクラスを作成し、call メソッドを入り口として実装することが多いです。

実装例

# app/services/create_order_service.rb
class CreateOrderService
  def initialize(user, params)
    @user = user
    @params = params
  end

  def call
    order = @user.orders.create!(@params)

    # 外部決済サービスとの連携など
    PaymentService.new(order).call

    OrderMailer.completed(order).deliver_later

    order
  end
end

Controller側はシンプルになります。

def create
  @order = CreateOrderService.new(current_user, order_params).call
  redirect_to @order
end

※ 実際には外部サービスとの連携では、失敗時のデータ整合性や例外処理、リトライ処理なども考慮する必要がありますが、この記事ではService Objectの役割を分かりやすくするため省略しています。

Service Objectは特定のフレームワーク機能に依存せず、通常のRubyクラスとして実装できるため、比較的導入しやすい設計パターンです。

その他の設計パターン

Railsでは、ファットモデルやファットコントローラーを避けるために、Service Object以外にもさまざまな設計パターンがあります。

パターン 主な用途
Service Object ユースケース単位の業務処理をまとめたいとき
Concern 複数のModelやControllerで共通する機能や処理を切り出したいとき
Form Object フォーム入力や複数モデルのバリデーション・保存をまとめたいとき
Query Object 検索条件やJOINが複雑になり、scopeだけでは見通しが悪くなったとき
Policy Object 認可ロジックを分離したいとき
Decorator / Presenter View表示用のロジックをModelから切り離したいとき
PORO(Plain Old Ruby Object) ActiveRecordを継承しない通常のRubyクラスとして、ドメインロジックを切り出したいとき

今回はService Objectに絞って紹介しましたが、他の設計パターンについても、機会があれば整理して記事にしてみたいと思います。

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?