🐥
【SOLID原則】単一責任の原則 - SRP
SOLID原則とは、ソフトウェア設計の5つの原則の頭字語を取ったものです。ソフトウェアをより理解しやすく、より柔軟に、よりメンテナナンス性の高いものにするために考案されました。
- 単一責任の原則(Single Responsibility Principle)
- オープン・クローズドの原則(Open/closed principle)
- リスコフの置換原則(Liskov substitution principle)
- インターフェース分離の原則(Interface segregation principle)
- 依存性逆転の原則(Dependency inversion principle)
今回はSOLID原則のひとつ、単一責任の原則についてです。
単一責任の原則
個々のモジュール(関数やクラス)は、一つの責任だけを持つべきという原則です。責任は、そのシステムを使うアクター(ユーザやステークホルダー)に対して持ちます。
例えば、次のようなEmployeeクラスがあったとします。
これは単一責任の原則に違反しています。
class Employee {
/** 経理部門が規定、報告先はCFO */
const calculatePay = () => {}
/** 人事部門が規定、報告先はCOO */
const reporyHours = () => {}
/** データベース管理者が規定、報告先はCTO */
const save = () => {}
}
これは複数のアクターに対してのメソッドが存在している状態です。それぞれのメソッドをひとつのクラスに入れると、開発者はすべてのアクターを結合することになります。この結合が原因でCFOチームの何らかの操作が、COOチームの使うものに影響を及ぼしてしまうことがあります。
各メソッドで使われる共通メソッドがあった場合は、仕様の変更を入れる度に影響が出ます。その都度、アクターごとに条件分岐を入れたくなったりとコードが複雑になります。
また、部門ごとに開発チームが分かれていてる場合、同時に同じ箇所を変更していたらソースコードのコンフリクトが起こる可能性があります。
解決策
アクターの異なるコードは分割すべきです。
それぞれのメソッドを別のクラスに移動します。
class PayCalculator {
const calculatePay = () => {}
}
class HourReporer {
const reporyHours = () => {}
}
class EmployeeSaver {
const saveEmployee = () => {}
}
これで3つのクラスはお互いに相手のことを知らない状態になりました。
単一責任の原則に従い、アクターに対する責務を一つにすることで、各モジュールは凝集度が高くなり、機能の修正や仕様変更に強い設計が出来るようになります。
ちなみに凝集度が高いとは、責務・データ・振る舞いの関連が強いということです。
参考
Discussion