#1. リファクタリング前の問題
例えば、ユーザー登録処理を以下のようにコントローラーでまとめている場合を考えます。
# app/controllers/users_controller.rb def create @user = User.new(user_params) if @user.save # 登録成功後の処理 UserMailer.welcome_email(@user).deliver_later AccountCreationService.new(@user).create_default_account redirect_to root_path, notice: '登録完了' else render :new end end
問題点
- コントローラーが肥大化している
- メール送信やアカウント作成など、ビジネスロジックが分散している
- テストが書きにくい
#2. Service Objectでリファクタリング
コントローラーの処理を Service Object に切り出すことで、責務を整理できます。
# app/services/user_registration_service.rb class UserRegistrationService def initialize(params) @params = params end def call user = User.new(@params) return false unless user.save send_welcome_email(user) create_default_account(user) true end private def send_welcome_email(user) UserMailer.welcome_email(user).deliver_later end def create_default_account(user) AccountCreationService.new(user).create_default_account end end
コントローラーの変更後
def create if UserRegistrationService.new(user_params).call redirect_to root_path, notice: '登録完了' else render :new end end
- コントローラーは リクエストの受け取りとレスポンス返却だけ に集中
- ユーザー登録のビジネスロジックは Service Object に集約
#3. Presenter / Decoratorでビューを整理
ビューでの表示ロジックもモデルから分離できます。
例:ユーザーのフルネーム表示
# app/decorators/user_decorator.rb class UserDecorator < SimpleDelegator def display_name "#{first_name} #{last_name}".strip end end
コントローラーでの利用
def show @user = UserDecorator.new(User.find(params[:id])) end
- ビューでは
@user.display_name
で整形済みの名前を取得できる - モデルやビューがスッキリして、変更に強いコードになる
#4. Observerで副作用処理を分離
モデルに書かれていた副作用処理(メール送信など)も Observer パターンで整理できます。
# app/models/user.rb class User < ApplicationRecord after_create :notify_registration private def notify_registration UserMailer.welcome_email(self).deliver_later end end
- モデルの主要ロジックと副作用処理を分離
- Service Object と組み合わせるとさらに整理される
#5. リファクタリングの効果
Before | After |
---|---|
コントローラーが肥大化 | コントローラーは処理呼び出しのみ |
モデルに複雑なビジネスロジック | Service Object に集約 |
ビューで整形処理 | Presenter/Decorator に集約 |
副作用処理がモデルに混在 | Observer で分離 |
- テストが書きやすくなる
- 再利用性が向上
- 変更に強い構造 になる
#6. まとめ
Railsでデザインパターンを使ったリファクタリングは、以下のステップが基本です。
- コントローラーの肥大化を確認 → Service Object で切り出す
- ビューの表示ロジックを確認 → Presenter / Decorator で整理
- モデルの副作用処理を確認 → Observer で分離
- ファクトリーパターンでテストデータを整理
💡 ポイント
- 小規模アプリでは必須ではないが、中規模以上で効果絶大
- 「責務を1つにまとめる」 がリファクタリング成功のコツ