クリーンアーキテクチャ
https://3.bp.blogspot.com/-CgJf2Y1UHQM/WqiiY7eeVLI/AAAAAAABK6k/MevmdrMwvpwgKoUwkaMhuz6ehoHRnJTBACLcBGAs/s400/toy_tsumiki_boy.png
🌅 基本のレイヤー4層
考え方の基本であって、必ず四層に分かれている必要はない
大事なことは書こうとしている実装の責務がどこに属するのかを意識しておくこと
そして、実装間の依存の方向を1方向に揃えておくこと
https://blog.cleancoder.com/uncle-bob/images/2012-08-13-the-clean-architecture/CleanArchitecture.jpg
🍅 Enterprise Business Rules
属するもの
Entity: 何にも依存しないコアになる実装
アプリケーションであることに依存しないビジネスロジックを書く
言い換えると人に役を割り当てたときその人だけで完結することのできる処理
例: 渡されたデータをルールに沿ってチェックしOKかどうかを判別する
Entity の他には何にも依存しない実装になる
🍅 Application Business Rules
属するもの
UseCase: ビジネスロジックを提供する実装の interface
UseCaseImpl: ビジネスロジックの実装
アプリケーションであることに依存するビジネスロジックを書く
言い換えると人に役を割り当てられない処理を書く
例: ログイン (= ログインという概念はアプリケーションであることに依存している)
Entity に依存 (= インスタンスを生成) することができる
Interface and Adapters の層にある interface を使用できる
データの永続化に関わる処理はここには書かない
🍅 Interface and Adapters
属するもの
Repository: データ永続化のための抽象層の interface
RepositoryImpl: Repository の実装
Gateway: データの永続化を行わない抽象層の interface
GatewayImpl: Gateway の実装
Presenter: データを表示するための変換を行う層
Controller: 入力を解析して UseCase に伝え、結果を出力する層
データの入出力や永続化に関わる処理や外部ライブラリの機能を抽象化する
抽象化とは例えばデータの永続化手法が MySQLからファイルに変わったとしても変わらないプログラムの処理の流れを抽出すること
Application Business Rules の層に提供するのが役割
Frameworks and Drivers の層にある interface や ライブラリなど一通りのものに依存して良い
データベースのトランザクションはRepositoryの内部で完結させておかないと抽象化が不完全なものとなる。
Repository がの永続化がデータベースに対して行われるかどうかは「重要でない詳細」になる。
🍅 Frameworks and Drivers
属するもの
Infrastructure / Driver: 実際に特定の仕組みを使うための層であり、使用しようとしているライブラリ自身がこの層に属する。操作が複雑な場合はこの層に薄いラッパーを配置しても良い
Interface and Adapters で抽象化した仕組みを具体的に提供する層
基本的にはこの層のみ、特定のライブラリやフレームワークに依存して良い
MySQL や PostgreSQL のドライバや ORM
Webアプリケーションフレームワーク
WebAPI クライアント
など
🌌 運用のコツ
Clean Architechture はベースになる考え方なので規模やチームやスキルに応じて、ルールを調整して運用して良い。
🌠 個別ライブラリの使用に関する特例
ライブラリは Interface and Adapters の層において、抽象化することが基本になる。
しかしながらあまりに小規模なライブラリや、絶対に置き換えが発生しないことが予見される言語の標準ライブラリなどは 例外として、各層に直接依存しても良いと決めることもできる。DIコンテナのライブラリなどもそういう扱いで導入できる。ただし一度依存すると後で抽象化し直すことはできなくはないが難しいので決定には注意したい。
🌠 DIコンテナを併用する
上記の特例を活用して、DIコンテナを活用することで、ググッと学習コストや導入コストが減り、責務や粒度を意識したコードでありつつも運用が楽になることが見込める。PureCA で組み上げてもいいが初期化の処理の記載が冗長になりうるので、学習目的など特別な事情がなければおすすめしたい。TypeScript だと InversifyJS や tsyringe など 参考