はじめに
クリーンアーキテクチャって最近流行ってるけどよく分からない。理解しようとすると結構学習コストがかかりそうだし、必要になったタイミングで改めて勉強しよう...と思っている人いると思います(自分がそうでした)
そんな人向けに、この記事さえ読めばなんとなくクリーンアーキテクチャの本質が分かるようになる記事を書いてみました。
自分なりの解釈も混じっている部分もありますがご了承ください。
クリーンアーキテクチャとは
クリーンアーキテクチャとはビジネスロジック(ドメイン)を中心に置き、インターフェースの層や技術を外側に配置する設計アプローチです。
Robert C. Martin (Uncle Bob)氏が考案しました。
ヘキサゴナルアーキテクチャ(ポート&アダプタ)の影響を受けており、根幹の考えは両者とも同じです。
ポートとアダプタというと、UsecaseのPortという表現はまさにそのように感じます。
両者のアーキテクチャに言えることですが、外部のフレームワーク(Expressなど)やデータベースといった「技術的な詳細」を最外層へ追いやり、一番大切なビジネスロジックを中心に配置します。
依存方向が肝となり、ビジネスロジックは技術的な詳細に依存してはいけません。技術の詳細がビジネスロジックに依存するようにします。
外側から中心という一方向に依存するようにコントロールすることで、変更に強くテストも容易な持続可能なソフトウェア開発が可能になります。
一言で言うと、こんな感じになるかと思います。
- 変更に強いソフトウェア設計法
- ドメイン(ビジネスロジック)が技術から独立したアーキテクチャ
- ビジネスロジック中心の設計法
- 層分けされた依存性逆転の設計法
じゃんけんアプリで例えてみる
正直今までの説明だと抽象的すぎてイメージしにくいかと思うので、具体例を出してみます。
例えばじゃんけんアプリで例えてみましょう。
じゃんけんでは「パーはグーに勝つ」というビジネスルールがあります。
このビジネスルールは、じゃんけんがじゃんけんとして成り立つ上でとても大切なルールです。
DBがMySQLからMongoDBに変わろうが、「パーはグーに勝つ」というルールは影響を受けてはいけません。
クリーンアーキテクチャは技術の詳細とビジネスロジックが疎結合のため、このような技術的な詳細の変更がビジネスロジックに影響を与えることなく変更することができます。
クリーンアーキテクチャが重要視していること
クリーンアーキテクチャは、特段新しい考えやアプローチではありません。
関係性の分離やSOLID原則を特に尊重した設計方針なのです。
個人的にはSOLID原則のうち以下の二つが特に強く現れていると思います。
- 依存性逆転(DIP)の原則
- ドメイン層(ビジネスルールなどが配置される)が技術的な詳細に依存しないようにする上でこの原則を使う
- 単一責任の原則
- 各層が一つだけの責任を持つためにこの原則を使う。Enterprise Business Rules層(ドメイン層)はビジネスルールを担当し、Frameworks & Drivers層(インフラ層)は技術の詳細を担当するなど
特に、依存性逆転の原則はクリーンアーキテクチャの本質でもあるので、あらかじめ理解しておいてください。
ドメイン駆動設計と相性が良い理由
「ドメイン駆動設計 アーキテクチャ」と調べると、必ずと言って良いほどクリーンアーキテクチャやヘキサゴナルアーキテクチャ、オニオンアーキテクチャが登場します。なぜでしょうか?
ドメイン駆動設計は、ビジネスの核心となるドメインを理解し、その知識を基にソフトウェアを設計するアプローチです。
しかし、システムである以上、フレームワークやデータベースなど技術的な詳細を利用・差し替え・バージョン更新していく必要があります。
重要なドメインオブジェクトは、これらの影響を受けずに守り抜きたいですよね。
クリーンアーキテクチャやヘキサゴナルアーキテクチャ、オニオンアーキテクチャは、ビジネスロジックを中心に考え、依存関係の方向をコントロールすることで、技術的な詳細を外側に追いやります。つまり、ドメイン駆動設計で構築したドメインオブジェクトを守りやすくなります。このため、これらのアーキテクチャとの相性が良いとされています。
もちろん、xxxアーキテクチャのような言葉は重要ではなく、本当に大事なのはそれらが大切にしている思想です。
よくある誤解 - 図の通りの完璧な層を分けること
クリーンアーキテクチャについて調べると必ずと言っていいほど見かけますよね。
右下の矢印の図は処理の流れを具体的に表現しています。
中心に向かっている矢印の向きが大事だ...というのは色々な記事で言及されていると思います。
しかしこの図をみる上で注意しなければならないことがあります。
それは、「必ず図通り、全部の層に分ける必要がある」という誤解です。
私も最初そのように思っていたのですが、実際にRobert C. Martin (Uncle Bob)氏の記事を見るとそうではないと言及されています。
Only Four Circles?
No, the circles are schematic. You may find that you need more than just these four. There’s no rule that says you must always have just these four.
DeepL日本語訳
4つの円だけ?
いいえ。この4つ以外にも必要なものがあるかもしれません。常にこの4つだけでなければならないというルールはありません。
つまり、この図の通り全部の層に分ける必要もなく、依存関係をしっかりコントロールすることが重要だということです。
この図があまりにも有名になりすぎてしまったため、誤解している人も多いのではないのかと思います。
また、ディレクトリ構成やパッケージ構成も図の通りに分ける必要がありません。
エンジニアがそのパッケージ構成を見た際に、「このアプリケーションは何ができるのか?」が伝わるような構成にします。
例えば、勤怠システムであれば、そのリポジトリの中身の構成を見たときに「これは勤怠システムなんだな」と分かるような構成にします。
層を意識した構成よりも、ユースケースを中心にした構成を考えると「このアプリケーションは何ができるのか?」が伝わりやすいです。
個人的には層で分けた構成もそれはそれで良いと思っており、チームや自分で意思決定した構成であれば何でも良いと考えています。
詳しくは「叫ぶアーキテクチャ」と調べてみてください。
ただ、せっかくフレームワーク非依存なので、叫ぶアーキテクチャを実践してみたいですね。
私がクリーンアーキテクチャを必要とした背景
私も最初は名前だけしか聞いたことがなく、興味もありませんでした。しかし、下記の経緯を経てクリーンアーキテクチャが必要だと感じるようになりました。
- 会社のミッションを実現したいと思った
- そのためには、ユーザーにとって本当に価値のあるプロダクトを長期的に届ける必要があると認識した。
- 本当にユーザーにとって価値のあるプロダクトを作るには、複雑で難しいドメインを深く分析し、プロダクトに反映させる必要があると感じた
- 上記を達成するには、ドメイン駆動設計が最適であることに気づいた
- ドメイン駆動設計によって表現された多様なドメインオブジェクトを、システムを運用していく中で避けられない技術的な詳細による変化の影響から守りたいと考えた
- そのためには、技術的詳細や外部の変化によるドメインオブジェクトへの影響を最小限にすることができるアーキテクチャを選択したいと思った
- 上記を実現できるアーキテクチャとして、ヘキサゴナル、オニオン、クリーンアーキテクチャなどが挙げられることを知った
- ぶっちゃけどれでも良いが、より細かく何をどこに置くか具体的でイメージしやすいクリーンアーキテクチャを選択した
最初は形から入りましたが、依存性逆転の原則や関心の分離を無意識に行えるようになりました。
ヘキサゴナルアーキテクチャや依存性逆転の原則、依存性の注入などを先に学んでおくと導入はスムーズだと思います。
まとめ
- クリーンアーキテクチャはビジネスルールを中心に置き、技術的な詳細は外側に追いやる設計
- ビジネスルールが技術的詳細に依存してはならない。技術的詳細がビジネスルールに依存しなければならない
- それを実現するために依存性逆転の原則(DIP)が関わってくる
- 同心円の図の通り層を再現する必要はない。依存関係を適切にコントロールすることが重要
- ヘキサゴナルアーキテクチャや依存性逆転の原則を先に学んでおくと理解がスムーズ