クリーンアーキテクチャ本とは
皆さんご存知こちらの名著のこと。割と古い本のはずだけど最近あちこちでオススメされてる(自分の観測範囲だけ?)。
本の構成は以下のようになっている。
- 第Ⅰ部 イントロダクション
- 1章 設計とアーキテクチャ
- 2章 2つの価値のお話
- 第Ⅱ部 構成要素から始めよ: プログラミングパラダイム
- 3章 パラダイムの概要
- 4章 構造化プログラミング
- 5章 オブジェクト指向プログラミング
- 6章 関数型プログラミング
- 第Ⅲ部 設計の原則
- 7章 単一責任の原則
- 8章 オープン・クローズドの原則
- 9章 リスコフの置換原則
- 10章 インターフェース分離の原則
- 11章 依存関係逆転の原則
- 第Ⅳ部 コンポーネントの原則
- 12章 コンポーネント
- 13章 コンポーネントの凝集性
- 14章 コンポーネントの結合
- 第Ⅴ部 アーキテクチャ
- 15章 アーキテクチャとは?
- 16章 独立性
- 17章 バウンダリー: 境界線を引く
- 18章 境界の解剖学
- 19章 方針とレベル
- 20章 ビジネスルール
- 21章 叫ぶアーキテクチャ
- 22章 クリーンアーキテクチャ
- 23章 プレゼンターとHumble Object
- 24章 部分的な境界
- 25章 レイヤーと境界
- 26章 メインコンポーネント
- 27章 サービス: あらゆる存在
- 28章 テスト境界
- 29章 クリーン組み込みアーキテクチャ
- 第Ⅵ部 詳細
- 30章 データベースは詳細
- 31章 ウェブは詳細
- 32章 フレームワークは詳細
- 33章 事例: 動画販売サイト
- 34章 書き残したこと
- 35章 アーキテクチャ考古学
この本で特に重要なのは第Ⅲ部〜第Ⅴ部にかけての部分なので、この要点まとめシリーズでは7章〜29章の要点と自分の所感を1章ずつ記事にまとめていく。
第Ⅲ部 7章 単一責任の原則
SRPとは
単一責任の原則(SRP, Single Responsibility Principle)が言わんとするのはどのモジュール・関数もたった一つのことを行うべきということではなく、あくまで 「モジュールを変更する理由はたった一つだけであるべきである」 ということ。
ここでいう「変更の理由」とは、そのソフトウェアのユーザーやステークホルダーを指す。ユーザーは一人とは限らず、複数人がシステムを変更したいと望む場合もあるため、これらシステムの変更を望む人達をひとまとめにしたグループのことを アクター と呼ぶ。するとSRPはより正確には以下のように言い換えられる。
「モジュールはたった一つのアクターに対して責務を負うべきである。」
給与計算システムの例で考える
これを説明するために本文中で紹介されている給与計算システムの例が分かりやすかったので紹介する。この例では給与計算システムに従業員クラスが存在し、そこに以下2つのメソッドが実装されている状況で何が起こるかを考えている。
- 給料を計算するメソッド: calculatePay
- 計算ロジックは経理部門が規定する
- 計算結果の報告先はCFO
- 労働時間を計算するメソッド: reportHours
- 計算ロジックは人事部門が規定する
- 計算結果の報告先はCOO
このような設計では、給与計算と労働時間の計算の両方で同じように所定労働時間を算出している場合などに、開発者はコードの重複を排除するためこの計算をregularHoursメソッドに切り出そうと考えるはずである。
その後ある時CFOチームで所定労働時間の計算方法を変えたくなったため、regularHoursメソッドに手を加えたとする。するとその修正について何も知らされていないCOOチームは知らぬ間に数字がずれていることに気付かず、後になって大問題が発覚するというわけだ。
このような事故が起こった原因は、アクターが違う処理(この例でいうとregularHourメソッドが担当している処理)をメソッドに切り出して共通化しまったことにあるというわけだ。なので具体的な実装の観点でSRPを言い換えるなら、 「アクターが異なる処理はメソッドやモジュールに切り出して共通化してはいけない」 という風に言えそうである。
自分はこの給与計算システムに関する説明を最初に読んだ時、
「テストコードがどのアクター目線でも網羅的に書かれていてCIで全てのテストケースをチェックする体制ができていればこういう事故はある程度機械的に防げるのでは?」
という想いが一瞬頭をよぎったが、冷静に考えると問題はそこではなく、一つのアクター目線で修正を加える際に常に他のアクターの事情も考慮しなればならないという時点でまず開発効率が落ちるということだと思う。
Facadeパターンによるコード分割
SRPを説明する例としてもう一つ、複数のアクターが別々の理由で一つのソースファイルを変更したい状況(CTOチームとCFOチームがEmployeeクラスを共通で利用しており、そのクラスを変更したいような場合)の解決策についても触れられている。ここでも、アクターの異なるコードは分割すべき の原則に従うことになる。
やることとしては、
- Employeeクラスが持つメソッドを全て削除し、このクラスには最低限のデータ構造のみもたせる
- Employeeクラスが持っていた個々のメソッドの処理内容を対応するサービスクラスに実装し直す
- Employeeクラスが元々備えていたメソッドを呼び分けるためのEmployeeFacadeクラスを用意。このクラスの各メソッドで、実際に実行したい処理を担うサービスクラスをインスタンス化して処理を移譲する
これでEmployeeクラスが多方から修正されることを防ぎ、かつクラスを小さく保つことができるようになる。
参考
- Clean Architecture 達人に学ぶソフトウェアの構造と設計 (Robert C. Martin)