このチュートリアルでは、ClinicSync プロジェクトで行った2つのリファクタリングについて解説します。このアプリケーションは、私のRuby on Rails MBAの一環として開発された医療クリニック管理システムです。目的は、サービスオブジェクト(Service Objects) を活用して、コードの可読性、保守性、拡張性を向上させることです。
サービスオブジェクトとは?
サービスオブジェクト は、モデルやコントローラー、ビューに属さない ビジネスロジックを整理するためのシンプルなクラス です。
これは、単一責任の原則(Single Responsibility Principle, SRP) を実践する方法の1つであり、システムの各部分に明確な役割を与えることができます。
サービスオブジェクトを使うべきタイミング
次のような場合にサービスオブジェクトの導入を検討しましょう:
- ロジックが複雑でコントローラーに収まりきらないとき
- 機能が特定のモデルに自然に属さないとき
- 同じロジックを複数箇所で再利用したいとき
- よりクリーンでテストしやすいコードを目指したいとき
サービスオブジェクトの基本構造
class ExampleService
def self.call(params)
new(params).call
end
def initialize(params)
@params = params
end
def call
# メインのロジックをここに記述
end
end
リファクタリング①:AuthorizeUser
サービス
目的:
コントローラーに繰り返し書かれていたユーザータイプの判定処理を外部化する。
リファクタリング前:
def require_admin
unless user_signed_in? && current_user.is_a?(Admin)
redirect_to root_path, alert: "You are not authorized to access this page."
end
end
リファクタリング後:
def require_admin
unless user_signed_in? && AuthorizeUser.call(current_user, Admin)
redirect_to root_path, alert: "You are not authorized to access this page."
end
end
作成されたサービス:
class AuthorizeUser
def self.call(user, user_type)
user.is_a?(user_type)
end
end
メリット:
- ロジックの重複排除(DRY)
- 保守性の向上
- クリーンで再利用可能なコード
リファクタリング②:AuthenticateUser
サービス
目的:
ユーザー認証処理を SessionsController
から分離する。
リファクタリング前:
if (user = User.authenticate_by(params.permit(:email_address, :password)))
start_new_session_for user
redirect_to home_path_for(user), notice: "Logged in successfully."
else
redirect_to new_session_path, alert: "Try another email address or password."
end
リファクタリング後:
user = AuthenticateUser.call(params[:email_address], params[:password])
if user
start_new_session_for user
redirect_to home_path_for(user), notice: "Logged in successfully."
else
redirect_to new_session_path, alert: "Try another email address or password."
end
作成されたサービス:
class AuthenticateUser
def self.call(email_address, password)
User.authenticate_by(email_address: email_address, password: password)
end
end
メリット:
- コントローラーの簡素化
- ソーシャルログインや二要素認証などの拡張が容易
- 責務の明確な分離
まとめ
この2つの小さなサービスオブジェクトにより、プロジェクトは:
- よりクリーンに
- テストしやすく
- 拡張しやすくなった
サービスオブジェクトは、クリーンコードを実現し、Railsアプリケーションを将来の拡張に備えるための強力な手法です。
作成者: [レオナルド・フラゴーゾ]