概要
対象読者
- クリーンアーキテクチャについて学びたいけど何から学んだら良いか分からない方
- クリーンアーキテクチャを学んでみたもののメリットや採用する目的がいまいち分からない方
- 過去の自分
記事で説明すること
- なぜクリーンアーキテクチャという考え方が生まれたのか?
- クリーンアーキテクチャを採用することでどんなメリットがあるのか?
について解説します。
記事にしようと思った背景
新しく参加したインターン先ではクリーンアーキテクチャを採用していました。
そこで、クリーンアーキテクチャを学ぼうとして色々な記事読んでみたけどその概念がいまいち腹落ちしないというまま放置していました。
ですが、「Clean Architecture 達人に学ぶソフトウェアの構造と設計」の著者であるRobert C.Martin (愛称: Uncle Bob)さんの講演会のYoutube動画を見たら、色々腹落ちしたのでそれについて説明していきます。
公演内容はクリーンアーキテクチャの概念が生まれた背景やクリーンアーキテクチャがもたらすメリットなどが初心者にも分かるように説明されていました。
講演動画一覧
- ITkonekt 2019 | Robert C. Martin (Uncle Bob), Clean Architecture and Design
- Robert C Martin - Clean Architecture
上の動画の方が最近で閲覧数も多いようです。
基本的に内容は一緒です。
本題
クリーンアーキテクチャという概念が生まれた背景
「クリーンアーキテクチャとは何か?」を簡潔に知りたいかもしれませんが、それを聞くよりもクリーンアーキテクチャが必要になった背景を知った方が明らかに理解速度が高まるので背景から説明します。
皆さんがこれまで関わったプロジェクトや自作のポートフォリオを思い出してみてください。
プロジェクトのルートフォルダを開いたときに一番最初に伝わってくるのは何でしょうか?
Ruby on Rails
やDjango
を使っているならば、フォルダを開いたときに最初に伝わってくるのは**「何のフレームワークを使っているか?」**ということだと思います。ですが「何のフレームワークを使っているか?」は今行っているプロジェクトにおける現実の課題解決において重要でしょうか?
答えはNoです。
なぜなら、フレームワークはツールに過ぎないからです。
ちなみに私のポートフォリオはDjnagoで作られているのですが、プロジェクトのルートフォルダの中身は以下のようになっています。
これを見て「このシステムが何をしてくれるサービスなのか?」や「どこにこのサービスにとって最も大切な情報(ビジネスロジック)が格納されているのか?」が分かるでしょうか?
繰り返しになりますが、答えはNoです。
一番に伝わってくるのはこれがDjangoで作られたこと(Djnagoユーザーであれば)、Webシステムであることです。
本来、プロジェクトフォルダを開いたときに伝わってくるべきものは「どのフレームワークを使っているか?」や「どんなデータベースを使っているのか?」ではなく、**「このシステムは何をしてくれるのか?」**であるべきです。
↑の考え方を採用したのが「クリーンアーキテクチャ」が生まれた背景になります。
もし会計システムを作っているなら、会計システムであることが分かるような設計にしましょうということです。
フレームワークはあくまでツールであることを強調しています。
さらに深掘りするとWebもあくまでツールであると主張しています。
Webは重要な要素でなく単なるインプットを受け取ってアウトプットを返すためのインターフェースに過ぎないということです。
なぜなら、解決するべき課題、クリーンアーキテクチャ風に言うと「ビジネスロジック」はインターフェースが何であろうが不変だからです。
具体例
ビジネスロジックは不変であると言うことをもっと分かりやすくするために、一つ具体例として料理の注文をする場合について考えてみます。
以下の画像は注文の際に必要な情報と出力される情報やその情報を扱う手順などを示しています。
このように注文において必要な情報は、それを受け取る場所がWebブラウザであろうが、コンソールであろうが、電話であろうが、変わりません。もっと言うと、受け取った情報を使って注文を作成する手順も同じです。
これが、根底にあるビジネスロジックは、不変であると言うことを示しています。
クリーンアーキテクチャを採用するメリット
背景がわかったところでクリーンアーキテクチャを採用するメリットについて解説していこうと思います。
結論から言うと、クリーンアーキテクチャを採用することで、将来の変更に強いアプリケーションを作ることができます。
その理由は、ビジネスロジックを中心に添えて開発をすることで、フレームワークやUIに依存しないアプリケーションを作ることができるからです。
もっと言うとWebやDBにすら依存しないアプリケーションが作れます。
依存しないと言うことは、将来フレームワークやUIの変更をしても、Webが使われなくなっても(中々ないと思いますが、、、)根底にあるビジネスロジックを書いたコードは変わらず生き残り続けるということです。
副次的なメリット
上記のメリットに加えて副次的に以下のようなメリットが生まれます。
ビジネスロジックが明確になる
「ビジネスロジックをどこに書いているのか?」をはっきりディレクトリに分けて管理するため、「どこからどこまでがビジネスロジックでどこからがWebやDBに関するコードなのかがとても分かりやすくなります。
テストがやりやすくなる
クリーンアーキテクチャを採用することで以下のように階層的にテストを行えます。
- まずは、細かいビジネスロジック(Entities)だけをテストする。
- 次にビジネスロジックを複数まとめた一連の業務ロジック(Use Cases)をテストする。
- 最後にWebからインプットを受け取って、DBに保存等(Controllers, Presenters, Gateways)についてテストする。
これにより、テストがより細かい粒度で行えるため、修正がしやすく、将来の変更にも対応しやすくなっていることがわかります。
例えば、DBが変わっても、1や2の実装を再度テストしなくて済む。
※( )の中の英単語がよく分からない人はまだ気にしなくて大丈夫です。以降で解説します。
クリーンアーキテクチャを実装できるまでレベルアップするために
クリーンアーキテクチャの背景とメリットはまだ序章で、実装レベルまで理解するには下の図を理解しなくてはいけなくなります。
「クリーンアーキテクチャ」と検索すると真っ先に出てくるあの図です。
私は先にこれを理解しようとして、結局、何がしたいのかよく分からないままでいました。
私は、この図を理解しようとするのはクリーンアーキテクチャが生まれた背景を理解した後の方が断然分かりやすいと思いました。
図の解説
それでは図の解説に入ります。今回は中心の円についてだけ解説したいと思います。
Entities (Enterprise Business Rules)
中心の黄色のEntities
はビジネスロジックが入ります。
先程の注文システムの図で言うならData
にあるCustomer-id
やCustomer-contact-info
等はこの階層で定義される必要があります。
また、細かいビジネスロジックもEntities
に含まれます。
注文システムの図で言うとPrimary Course
にあるそれぞれ番号が書かれている処理です。
これを番号ごとに関数で実施するイメージです。
Use Cases (Application Business Rules)
Use cases
は赤色の円のところです。
ここでは、細かいビジネスロジックをまとめて一連の流れを実行します。
具体的に注文システムの図で言うとPrimary Course
で書かれた1〜4の業務を順番に並べて実行するような関数を作ります。
人事システムを作るなら、「従業員を雇う」とか「従業員解雇する」とかの単位がUse Cases
で実行されることになります。
Controllers, Gateways, Presenters (Interface Adapters)
これらは緑の円で書かれているところを示しています。
Webシステムを使いたい場合、ここでようやくWebやDBに関する処理が出てくることになります。
ここでDBに接続して保存する処理、Web APIの処理などが書かれます。
Devices, Web, UI, DB, External Interfaces (Frameworks & Drivers)
一番外の青色の部分です。
UIやWebはビジネスロジックから切り離されていることが分かります。
円の左側の矢印について
この矢印は依存関係を示しています。
ControllersはUse Casesを参照できますが、逆はだめです。
同様にUse CasesはEntitiesを参照できますが、逆はだめです。
これを守ることによりクリーンアーキテクチャが完成します。
※ 一部どうしても内側から外側に参照しなければならない箇所が生じる場合があります。その時は右下の図のようなことを使うのですがそれはより理解できた時に別記事にでもしようと思います。
具体的にどう階層分けするか?
この点についてUncle Bobさんは動画では詳しく述べていません。最後の質問コーナーで少し回答しているのですが、「トップの階層にdomain
フォルダやusecase
フォルダがあると良いよね」って感じで回答しています。
私のインターン先でどう実装しているか?
Go言語でのプロジェクトを例に解説します。
トップの階層を見るとdomain
やusecase
などがあります。
また、トップの階層にadapter
というフォルダがあり、その中にcontroller
やec2client
などがあります。controller
にはWebAPIの処理、ec2client
にはAWSのEC2関係の処理などが書かれています。
このようにクリーンアーキテクチャを知っていればdomain
を見ればビジネスロジックが書かれているとかがすぐ分かるようになっています。
これは途中からプロジェクトに参加するエンジニアにとっても親切な構成だなと思います。
まとめ
クリーンアーキテクチャを理解したいときはその背景から知ると内容がスッと入ってきやすいのではないかと思います。
感想
これまでは個人規模の開発が多く、短期的な目線でアーキテクチャとかあまり深く考えずに実装さえできれば良いという考えが強めでした。
ですが、アーキテクチャにこだわると長期的に運用する際にプラスになって返ってくると思いました。開発しているときは確かにフレームワークはとても便利ですが、長期的に見るとメンテナンスにコストがかかったり、他の技術に移行しにくいなどの負の側面が見えてくるのかなと思いました。
この考え方自体は古くからあるものなので、アーキテクチャの知識は寿命も長く、学習のコスパ的にも良いと思います。アーキテクチャについて知ることは今後エンジニアとしてレベルアップするために必須だなと思っています。
※補足
クリーンアーキテクチャの右下の図の理解がまだ追いついてないので理解出来次第追加しようと思います。
私の解釈で書いている部分もあるため、間違いなどありましたらコメントで教えていただけると幸いです。