概要
本記事はクリーンアーキテクチャについての自身の理解を表明する、みたいな記事ですので、本記事を参考にクリーンアーキテクチャについて学ぼうというのはあまりお勧めしません。
クリーンアーキテクチャについて
開発のしやすさ、保守のしやすさ等、機能追加や機能修正といったことをよりやりやすく、安全にするためのシステム構造です。以下のことを提供しています。
- フレームワークに依存しないこと
- ビジネスルールはそれ単体でテストが実行可能であること
※ビジネスロジックと置き換えてもそう大差変わらない、と思う - UIに依存しないこと
- データベースに依存しないこと
- 外部機関に依存しないこと
https://blog.cleancoder.com/uncle-bob/2012/08/13/the-clean-architecture.html
円の一番外側はWeb、Devices、DBといった、サーバとは分離された別サービスであり、その内はビジネスロジックたるUseCaseを扱う部分であるControllersで、その内はUseCasesです(最内のEntitiesはよくわかりません)。依存関係の向きを表す矢印が外から外から内へと伸びているように、このような依存関係を構築します。また、右下に小さく図示されているのは、UseCaseがControllerからのリクエストを受け入れること、UseCaseがデータをHTML、JSONに変換するPresenters(フロントエンドのフレームワークがやっていそうなこと?)に送ること、を示している。
実装でのクリーンアーキテクチャの使用
このクリーンアーキテクチャをどうやって真似るのかについて説明します。
登場人物を以下の通り。
- UseCase: 必要に応じてRepositoryから実装を拝借するビジネスロジックの実装部分
- Controller: 必要に応じてUseCaseから実装を拝借して何かしらのレスポンスをクライアントに返す部分
- Router: 外部との接続点とControllerを紐づける部分
- DB: データベース
- Repository: データベース処理を記述する部分
依存性の注入
説明に依存性の注入とやらを使用するので、これを先に説明しておきます。依存関係を外部からもらうことを依存性の注入と呼び、Constructor Injection(引数からインスタンスや関数をもらうアレ)がそれに該当します。
クリーンアーキテクチャ関係なしに何が嬉しいのかというと、依存関係を内部に持たないのでそれ単体で使いやすいということです。わかりやすいところで言うとモックを使えるというところです。引数で依存関係のあるインスタンスや関数を受け取るので、これをモックに置き換えることで単体テストが容易になります。また、モックだけでなく、その関数の要望に適しているものであればどんなインスタンスでも関数でも付け替えることができます。
この依存性の注入とインターフェース(UIではない)を使うことで依存関係をいじることができます。
依存方向の調整
では、いよいよクリーンアーキテクチャを真似る方法について説明します。
- UseCaseはControllerを使ってその機能を使用されます。例えばログイン機能がUseCaseにあって、これをControllerが使うという形です。これは何もしなくても良いところです。
- ControllerはRouterを使ってその機能を使用されます。例えばログイン機能がController(UseCaseの機能を拝借している)にあって、これをRouterが使うという形です。これも何もしなくても良いところです。
- DBはRepositoryを使ってその機能を使用されます。例えばデータ作成機能がDBにあって(Create)、これをRepositoryが使うという形です。これも同様です。
- RepositoryはUseCaseを使ってその機能を使用されます。例えばユーザ登録機能がRepositoryにあって、これをUseCaseが使うという形です。クリーンアーキテクチャでは、Gateway(Repository)はUseCaseに依存する構造ですが、使う側が依存する側、使われる側が依存される側ですので、依存の方向が違っています。ここを変えることが真似するということです。
依存方向の逆転
やり方は単純です。ただ、依存方向の逆転と書いてはいますが、さすがにRepositoryがUseCaseに依存する関係を作るのは困難です。ですので、インターフェースを使って依存方向をちょっと変えます。
具体的にはUseCase→Repositoryインターフェース←Repositoryという感じに変えます。インターフェースとは端的に言いますと、仮決めのRepositoryみたいなものです。これを使用することでUseCase側はこの仮決めのRepositoryに依存しますが、実際のRepositoryには依存しません。また、Repositoryは仮決めのRepositoryに依存します。
おわりに
というわけでこんな感じです。最初に述べたようにクリーンアーキテクチャについてほとんど理解せずこのような記事をあげているわけですが、書いているうちに理解が深まったらいいな〜、という動機から書いている記事ですので、整合性は正直どうでも良いです。クリーンアーキテクチャについてはよくわかりませんでしたが、依存性の注入やインターフェースは便利だな〜、という感想です。
以上、おわり。