【Clean Architecture】第8章 オープン・クローズドの原則
「Clean Architecture」の学習記録。
「第8章 オープン・クローズドの原則」のまとめ。
原則
オープン・クローズドの原則(OCP)とは、ソフトウェアの振る舞いは既存の成果物を変更せず拡張できるようにすべき、という原則。
具体例
例として、財務情報をウェブページに表示するシステムが存在するとする。
追加機能として、画面の内容をプリンターで印刷できるようにしなければならない。
このとき、よくできたアーキテクチャなら既存コードにの修正は必要最低限に抑えられる。
方法としては、
- まず変更する理由が異なるものは、単一責任の原則(SRP)で適切に分割する
- それらの依存関係を依存関係逆転の原則(DIP)で適切にまとめる
処理をクラスに分割して、それぞれのクラスをコンポーネントにまとめる。
以下はコンポーネントを表す図。
通常の矢印は使用、白抜きの矢印は実装や継承を表す。
矢印の向かっている先が、自分自身を変更したときに影響を及ぼしたくないコンポーネントである。
- 例えばPresenterを変更したときに、Controllerを変更する必要をなくしたい。
- Viewを変更したときに、Presenterを変更する必要をなくしたい。
- 他の全てを変更したときに、Interactorを変更する必要をなくしたい。
この中でOCPに最も適しているのはInteractorである。
なぜこのコンポーネントが特権的な位置づけになるかというと、ビジネスルールを含んでいるからである。
Interactorはアプリケーションの最上位レベルの方針を含んでおり、中心となる関心事を処理している。
その他のコンポーネントは周辺の関心事を処理している。
レベルの概念に基づいて保護の階層が出いている。
- Interactorは最上位レベルの概念なので最も保護される
- Viewは最下位レベルの概念なので、保護レベルは最も低くなる
これがアーキテクチャレベルにおけるオープン・クローズドの原則である。
- アーキテクトは、いつどのような理由でどのように変更するかを考えて機能を分割する。
- 分割した機能をコンポーネントの階層にまとめる。
- 上位レベルにあるコンポーネントは、下位レベルのコンポーネントが変更されたとしても変更する必要はない。
方向の制御
本書のクラス図では、インタフェースが存在することで依存性が逆転している。
例えばInteractorコンポーネントからDatabaseコンポーネントへの依存関係を逆転させている。
※インタフェースがないと、InteractorからDatabaseへ依存してしまう。
情報の隠蔽
また、インタフェースは依存するコンポーネントの内部を知りすぎないようにする役割もある。
あらゆる変更からInteractorを保護することが最優先だが、Interactorの変更からも例えばControllerを保護したい。
そのために、ContollerからInteractorへInterfaceを介してアクセスすることで、Interactorの内部を知りすぎないようにできる。