はじめに
こんにちは、未経験エンジニア3年目の嶋田です。
今回は、単一責任の原則(Single Responsibility Principle、以下SRP)についてまとめたいと思います。
Railsのプロジェクトを進める中で、実装をしながら自分のコードがどんどん汚くなり、リファクタリングが必要になった際、先輩エンジニアから「単一責任の原則」という考え方を教えてもらいました。
この原則を知ってから、コードを改善するための重要な観点として意識し始めたのですが、理解して適用することに苦労しました。
この記事では、自分の経験を踏まえ、SRPについて整理し、具体的な適用例を備忘録としてまとめてみました。
同じように設計で悩む方の参考になれば幸いです。
目次
単一責任の原則(SRP)とは
**単一責任の原則(Single Responsibility Principle)**は、SOLID原則の一つで、クラスが「一つの責任」に集中すべきであることを定義します。
定義
クラスは「変更する理由」が一つだけであるべき
具体的には、クラスが複数の責任を持つと、以下のようなリスクが発生します。
- 責任ごとの変更が互いに影響し、デバッグや開発が困難になる
- クラスが肥大化し、理解が難しくなる
- テストが複雑化し、管理コストが増加する
責任が曖昧なコードの例
以下は、SRPが適用されていないコード例です。
1つのクラスに複数の責任が含まれていて、変更や保守が難しくなっています。
class UserManager
def initialize(user)
@user = user
end
def authenticate(password)
# ユーザー認証
end
def update_profile(params)
# プロフィール更新
end
def send_notification(message)
# 通知を送信
end
end
このクラスには以下の責任が含まれています。
- ユーザーの認証
- プロフィールの更新
- 通知の送信
一見便利に見えますが、以下の問題が発生しやすいです。
- 変更が影響を及ぼすリスク:例えば、通知機能の変更が認証機能に影響を与える可能性がある
- 可読性の低下:責任が増えるにつれて、コードが複雑化する
- テストの困難さ:テストケースが増え、メンテナンスが難しくなる
SRPを適用したリファクタリング
1. 責任を分割したクラス設計
上記のコードをSRPに基づいてリファクタリングし、責任を分割した設計に改善します。
class UserAuthenticator
def initialize(user)
@user = user
end
def authenticate(password)
# ユーザー認証
end
end
class UserProfileUpdater
def initialize(user)
@user = user
end
def update(params)
# プロフィール更新
end
end
class NotificationSender
def initialize(user)
@user = user
end
def send(message)
# 通知を送信
end
end
2. 各クラスの責任範囲
クラス名 | 責任 |
---|---|
UserAuthenticator | ユーザー認証処理を担当 |
UserProfileUpdater | ユーザープロフィールの更新 |
NotificationSender | ユーザーへの通知送信処理を担当 |
SRP適用後のメリット
このリファクタリングを行ったことで、以下のようなメリットがあります。
-
変更に強い設計
例えば認証処理を変更しても、通知処理やプロフィール更新処理に影響を与えない -
可読性の向上
各クラスが持つ責任が明確になるため、新しい開発者がコードを理解しやすくなる -
テストの容易さ
責任ごとにテストを作成できるため、単体テストが簡単かつ独立して行うことができる
まとめ
単一責任の原則(SRP)は、コードの保守性と拡張性を高めるための重要な設計指針です。
今回を振り返ると、以下の点がポイントでした。(実際コードを書くときにスラスラと意識しながらできるようになりたいです…🥲)
- クラスを1つの責任に集中させることで、変更や拡張に強くする
- 複数の責任を持つクラスを分割し、それぞれ独立させる
- 具体的な課題に対してもSRPを意識することで、設計の質を向上させる
私自身まだまだ勉強中なので、何か問題がありましたらぜひコメントで教えてください!
単一責任原則はSOLID原則のひとつに過ぎないので、他の原則についても学びを深め、自分のものにして綺麗なコードが書けるように頑張りたいです。
最後まで読んでいただき、ありがとうございました!