##はじめに
スターアプリケーションズ株式会社の吉田です。
Clean Architecture 達人に学ぶソフトウェアの構造と設計 (アスキードワンゴ)Robert C. Martin著、角征典、高木正弘 訳(以下、本書)を読みました。本書の内容については、議論の分かれるところもあり、Amazonの評価記事や、ネットの記事なども参考に自分なりに考えを整理してみました。
著者のRobert C. Martin(以下ボブおじさん)は、アジャイル宣言の起草者の一人でもあり、C++ Reportの編集者を勤めたり、プログラムやオブジェクト指向に関して何冊も本を出しています。著者と中身は別ですが、本書もかなりまともな内容であると思いました。
##アーキテクチャのルールはどれも同じである
いきなり序文の中にこれが出てきて面食らうのですが、「アーキテクチャはどれも同じ」とは言ってません。「アーキテクチャのルールはどれも同じ」と言ってます。では、アーキテクチャのルールって何ですかと言えば、本書のすべてだとい言います。
もう少し分かりやすく言うと、全てのプログラムの構成要素は「順次」「選択(if)」「反復(for)」の3つであると言います。そしてオブジェクト指向だろうが何だろうが、全てのコードはこの3つを組み合わせて使う、これは50年60年何も変わっていない。そして以下に、序文から引用します。
書いてるコードが変わらないのだから、どんな種類のシステムでもソフトウェアアーキテクチャのルールは同じ。ソフトウェアアーキテクチャのルールとはプログラムの構成要素をどのように組み立てるかのルールである。構成要素は普遍的で変わらないないのだから、それらを組み立てるルールもまた、普遍的で変わらないのである。
若いプログラマは「そんなわけがない」と言うかもしれない。昔は昔、今は今。過去のルールが今でも通用するわけがないと思うのだろう。もしそう考えているのなら、残念ながら間違っている。ルールは何も変わっていない。言語やフレームワークやパラダイムがまったく新しいものに変わったところで、ルール自体はAlain Turingが最初のマシンコードを書いた1946年と同じままだ。
本記事のタイトル「Clean Architectureはオジサンの逆襲だ」は、前記を読んで決めました。ボブおじさんは、半世紀の経験を経て、ようやくルールをつかんだと言ってます。昔はルールを知らなかった、今はこの本を読めばルールが分かる。本当ならすごいです。
##ソフトウェアはソフトでなければならない
「第I部 イントロダクション」の第1章で、ボブおじさんはアーキテクチャと設計に何も違いはないと言ってます。続く第2章では、ソフトウェアは簡単に変更できるようになっていなければならないと言います。また変更を容易にするためには、アーキテクチャがとても重要であると言い、さらに機能よりも、アーキテクチャの方が重要と言います。以下第2章から引用。
機能?それともアーキテクチャ?価値が大きいのはどちらだろうか?ソフトウェアシステムが動作することが重要だろうか?それとも、簡単に変更できることのほうが重要なのだろうか?
ビジネスマネージャに質問すると、ソフトウェアシステムが動作することが重要であると答える。開発者もこの意見に賛同することが多い。だが、これは間違った態度だ。簡単な論理的思考で極端な状況を設定し、これが間違っていることを証明しよう。
・完ぺきに動作するが、変更できないプログラムが与えられたとする。要件が変更されると機能しなくなる。修正することもできない。したがって、このプログラムはいずれ役に立たなくなる。
・動作しないが、変更が簡単なプログラムが与えられたとする。要件が変更されても修正は可能なので、動かし続けることができる。したがって、このプログラムはこれからも引き続き役に立つ。
これでは納得できないかもしれない。変更できないプログラムなど存在しないからだ。だが、変更のコストがメリットを上回っており、変更が事実上できなくなっているシステムは存在するだろう。多くのシステムでは、一部の機能や設定がその段階に到達している。
莫大な費用のため変更できない例を読んで、日本でもDX、DXと騒ぎながら、多くのレガシーシステムが塩漬けになっている状態を思い浮かべました。今あるシステムも、これから作成するシステムもきちんとしたアーキテクチャがないと、未来の負債になる。この辺は、日本もアメリカも変わらないなと言うのが、個人的な感想です。
また、ソフトウェアの変更を恐れて、ソフトウェアを変更しにくくするのであれば、もはやソフトウェアと言えない。変更に柔軟に対処できることが必要かと。
##そんなのみんな昔からあるよ
「第II部 構成要素から始めよ:プログラミングパラダイム」では、3つのプログラムパラダイム、すなわち「構造化プログラミング」「オブジェクト指向プログラミング」「関数型プログラミング」の3つの説明をしています。オブジェクト指向のカプセル化は中途半端とか、結構大胆に言い切っています。この3つのパラダイムは随分前に作られ、中にはコンピュータが発明される前からありました。そしてボブおじさんは、プログラミングパラダイムはこの3つしか存在しないと言いきっています(3章)。そう言えば昔、Prologという「論理型プログラミング」のパラダイムがありましたが、もう誰も使ってないか。。。
これら3つのパラダイムはプログラマにパワーを与えるのではなく制限(規律)を加えるものだと言います。具体的に6章から引用します。
・構造化プログラミングは、直接的な制御の移行に規律を果たすものである。
・オブジェクト指向プログラミングは、間接的な制御の移行に規律を果たすものである。
・関数型プログラミングは、代入に規律を果たすものである。
これらのパラダイムは、何をすべきかを伝えるよりと言うよりも、何をすべきでないかを伝えています。そして、ソフトウェアは急速に進歩する技術ではないと、ソフトウェアの本質も変わっていない。
ソフトウェア(コンピュータプログラムの本質)は、「順次」「選択」「反復」と「間接参照」で構成されている。それ以上でも、それ以下でもない。
プログラミングパラダイムは、何か制限を加えている(規律)と言う視点は新鮮でした。パラダイムに限らず、プログラムに規律を与えることによって、開発の生産性や品質を高めると言うのはよくあることだと思います。今は、猫も杓子も型、型、カタ、カタと言ってますが、静的な型もプログラムに規律を与える要素だと思います。
本書全体に言えることですが、境界を作るとか、一方向に限るとか、そう言う制限を加えることによりシステムの保守性を高めていくと言う発想が随所に見られます。
SOLID原則が分からなければ
「第III部 設計の原則」では、SOLID原則に関する説明となっています。ボブおじさんは1980年代の後半から原則を集め始め、原則の追加削除を経て、2004年にこの命名を決めたそうです。SOLID原則というと、一般にオブジェクト指向プログラミングに当てはまるものと思いがちですが、ボブおじさんは慎重にそれ以外でも通用すると言ってます。SOLID原則の中の単一責任の原則(SRP)は、とても誤解されやすいと書いてありますが、本書の説明を読むと理解が進みます。その他の原則も、個人的にはとても良くまとまっている内容だと思いますが、本書にも記載の通り、アーキテクチャ寄りに書かれており、ここで十分理解ができない場合は、他の本、例えばアジャイルソフトウェア開発の奥義を見るとよいと思います。
アジャイルで思い出したのですが、アジャイル開発だからと言って、何も考えずにプログラムをポンポン作っていくのは良くありません。やはりアーキテクチャを考え、SOLID原則なども踏まえて、プログラムを作って行かないと、後で痛い目に会うでしょう。
##コンポーネントの原則、実装は簡単でない?
「第IV部 コンポーネントの原則」では、コンポーネントの凝集性とコンポーネントの結合の2つについて書かれています。ここで言うコンポーネントは、デプロイの単位であり、いくつかのクラスをどのようにまとめるかの議論になります。コンポーネントの凝集性では、再利用・リリース等価の原則(REP)、閉鎖性共通の原則(CCP)、全再利用の原則(CRP)の3つがあり、これらの原則は互いに相反する。従って開発時の利便性と再利用生のトレードオフを考える必要があります。また、最適な落とし所は常に変わっていきます。今の時点で正しかった判断が翌年には変わっている可能性もあります。
もう一つのコンポーネントの結合にも3つの原則があります。非循環依存の原則(ADP)、安定依存の原則(SDP)、安定度・抽象度等価の原則(SAP)。非循環依存の原則のように比較的簡単な物もありますが、安定度を計測したり、抽象度を測定したりと難しい話が続きます。何よりも実装段階で、アプリケーションのニーズに沿ってバランスをとる必要があり、言わば、正解の無い世界になります。
##ソフトウェアアーキテクト
「第V部 アーキテクチャ」で、本書は佳境に入りますが、冒頭でソフトウェアアーキテクトについて記載があります。以下15章から引用します。
そもそもソフトウェアアーキテクトはプログラマである。プログラマを続けておかなければいけない。ソフトウェアアーキテクトはコードを書かず、より高いレベルの問題にフォーカスするものだ、というウソを信じてはダメだ。そんなのはデタラメだ!ソフトウェアアーキテクトは最高のプログラマであり、継続してプログラミングの仕事を引き受けながら、生産を最大化する設計にチームを導いていく。
ボブおじさんのプログラマとしての矜恃を示すものではないですか。
日本でも、コンサルタント、システムアナリスト、アーキテクト、システムエンジニア、プログラマなどなど、ITカーストが築かれて来ましたが、やはりプログラマが一番だと思う人も少なくないと思います。最近では、FrontEnd,BackEnd,DevOpsなど多種多様なエンジニアが出ていますが、本質はプログラマではないかと思います。一番顕著なのは運用を担うSREでしょう。以前は運用と言えばオペレータの仕事でしたが、今やれっきとしたプログラマの仕事ではないでしょうか。もっとも、ボブおじさんは、運用の問題は大部分ハードウェアの追加で済ませられるような言説で、この部分は少し違和感があります。
##GUI、DBは重要でない
第17章は、境界線の話です。
境界線は「重要なものと」と「重要でないもの」の間に引く。GUIはビジネスルールにとって重要でないので、その間に境界線を引く。データベースはGUIにとって重要でないので、その間に境界線を引く。データベースはビジネスルールにとって重要でないので、その間に境界線を引く。
このことに異議を唱える人もいるだろう。特に「データベースはビジネスルールにとって重要でない」の部分だ。多くの人たちが「データベースはビジネスルールと密接に結び付いている」と教え込まれてきた。なかには「データベースはビジネスルールを具体化したものである」と信じている人もいるくらいだ。
ほかの章でも触れているが、この考え方は間違っている。
他の章にも関係しますが、ボブおじさんは一貫して、ビジネスルールとインフラ系(GUI,DB)を切り分ける方針です。こうすることにより、DBやGUIを後で取り換えたり、どのDBにするかの決定を大幅に遅らせることができるということです。
考えて見れば、在庫管理のシステムでOracleからMySQLにDBを変えたからと言って、在庫量が変わるなど、あってはならないし、あり得ない話です。同様に経理システムで、手動入力であろうと、CSVの取り込みであろうと、JSONデータであろうと入力の値が同じであれば、同じ結果になる。こういうのは頭で理解していても、DBの変更なんてあり得ないからと言って、DBの固有な機能をビジネスルールのコーディングの中に紛れ込ませる失敗をします。
重要でないと言うのは誤解を招くかもしれませんが、ビジネスルールとGUIやDBが切り離せる構造が大切です。そして、特定のDBなり、GUIに強く依存しないことです。蛇足ながら、ボブおじさんは、なぜかDBに関しては懐疑的な面が見られます。(30章)
##4つの同心円をじっくり考えて見る
4つの同心円とは、以下の図を指します。本書では白黒かつ、用語が日本語に訳されており、複数形か単数形かわからなくなっている点がビミョーです。例えばEntities=>エンティティ、Use Cases=>ユースケースなどです。複数形には重要な意味があると感じています。
22章の4つの同心円は単なるアーキテクチャの例で、あまり固執しないほうが良いという捉え方もあります。しかし、本書を見ると、他の章は、全てこの22章を説明するための準備または後付けに思えます。やはり、章のタイトル(クリーンアーキテクチャ)から言っても、22章が本書の集大成と見るべきでしょう。ところで、ネットなどで、数多く発表されている4つの同心円を模した実装例を見ても、もう一つしっくり来ません。これは、どうしたことでしょう。思うにClean Architectureは小規模なものでは、なかなか良さが発揮できないのではと思います。実際にClean Architectureを実装するとなると、依存性の逆転、ポートとアダプタなど、通常よりもコーディングが増える可能性があります。コーディング量が増大しても保守、追加が楽になるのであれば問題はないのですが、小規模なシステムでコーディングを増やすと、複雑さが目立つ実装となってしまいます。テストがしやすくなるから多少冗長でも良いと言う意見もありますが、ここまで冗長になるとどうでしょうか。逆に規模の大きなシステムでは、全体の中での冗長が目立たない面もあります。本書では、33章で一応サンプルに相当するものが掲載されていますが、ユースケースの例としては適切ですが、CleanArchitectureの例としては、首を傾げざるを得ません。
では、ある程度の規模感のあるもので、どう言うものがCleanArchitectureに向いているでしょうか。ここからは、個人の主観になりますが、MVCアーキテクチャでFATモデルになりそうなものが向いているのではないでしょうか。つまり、モデルの中にDBのアクセスやらビジネスルールがごっそり入りそうな場合、その中からビジネスルールを切り出して、4つの同心円で言うところのエンティティ(Entities)、ユースケース(Use Cases)に組み込む実装です。実際にはFATモデルから、ビジネスルールを切り出すのは、決して簡単な話ではありません。(参考:改めて振り返る Fat Controller / Fat modelとの戦い)。そういう意味では、今動いてるシステムをCleanArchitectureに切り替えるのは難しいかもしれません。
##フレームワーク、MVC
ボブおじさんは、あちらこちらでRailsやSpringに否定的な話をしています。しかし、フレームワークの使用自体を否定するものではありません。32章では、フレームワークと結婚するなと説いています。結婚指輪が一生抜けなくなる、フレームワークは4つの同心円の一番外側に置いておけと言ってます。余程、SpringかRailsで痛い目に会っているのでしょう。個人的には、今の時代フレームワーク無くして開発をするのは結構大変であり、アーキテクチャとフレームワークの距離感をどう保つかはClean Architectureの課題だと思ってます。
MVCについてはどうでしょうか。次の引用は22章のインターフェースアダプターの説明からです。
たとえば、GUIのMVCアーキテクチャを保持するのはこのレイヤーになる。プレゼンター、ビュー、コントローラは、すべてこのインターフェースのレイヤーに属している。モデルは、コントローラーからユースケースに渡され、ユースケースからプレゼンターとビューに戻されるデータ構造にすぎない。
先ほどの、4つの同心円の右下の図がこの制御を表しています。このようにMVCを内包するというか、上位概念としてClean Architectureは存在していきます。
##「ペリフェリック」アンチパターンは本当にダメなのか
不思議なことに、本書ではDDDについて、ほとんど触れられていません。ようやく最後の34章で、少しドメイン駆動設計の記述が見られます。ただし、この章はよく見るとボブおじさんではなく、Simon Brownという方が書かれています。章全体としては、ボブおじさんはこう言ってるけど、自分はこういう考えだみたいな構成です。
34章にある下記の図は、「内側」に含まれるのはドメインの概念、「外側」には外部世界とのインタラクション(UI、データベース、サードパーティの統合など)を含める。大原則は、「外側が内側に依存するようにせよ、その逆は許さない」である。4つの同心円と比較すると内側の2つがドメイン、外側の2つがインフラストラクチャになります。
さて、ペリフェリックはパリの環状道路で、市内のごちゃごちゃした所に入らなくても、パリを周回できるというものです。上の図で、ドメイン」にアクセスせずとも、UIからDBを直接アクセスできてしまう。これがアンチパターンと記されていますが、個人的には疑問を感じています。以下の情報も参考になります。
(参考:ビジネスの構造を扱うアーキテクチャとユーザーとの接点を扱うアーキテクチャ)
##まとめ
Clean Architectureには、ブログの記事がありますが、本書を読まないと、本質が見えてこないのではと思います。また本書の中には、「付録A アキテクチャ考古学」のように、一見、自慢話かページ稼ぎにしか思えなかった部分もよく読んで見ると、どうしてClean Architectureの考えに至ったのか見えていきます。
さて私の考えでは、本書の内容については、かなり過激な言説もありますが、90%くらいは同意できます。ただし、次の2つの点が課題だと思っています。
・既存のシステムをClean Architectureに切り替えるのはコストが高すぎる
・新規のシステムの場合ある程度の規模がないとClean Architectureの良さが出ない
最後に本書を読んで、Clean Architectureを実装しシステムをいずれ公開したいと思っています。ただし、それなりの規模が必要と思われますので少し時間がかかります。ご了承ください。
##参考記事
以下の記事はとても参考になりました。
・クリーンアーキテクチャ(The Clean Architecture翻訳)
・実践クリーンアーキテクチャ
・Clean Architectureは全てのプログラマにお奨めしたい良著
・クリーンアーキテクチャ本を読むためのポイント
・clean architecture 読んで心に残った箇所の覚書
・改めて振り返る Fat Controller / Fat modelとの戦い
・ビジネスの構造を扱うアーキテクチャとユーザとの接点を扱うアーキテクチャ
ありがとうございました。