「Clean Architecture 達人に学ぶソフトウェアの構造と設計」を読んでいても、実際にはどんな順番で物事を進めて行けば良いのかが全然わからなかったので、多分こんな感じにやって行くんじゃないかな、っていう妄想。
クリーンアーキテクチャを考える上でのヒントにでもなれば。
前提になってる頭の中の既存システムは、大体Railsです。
クリーンアーキテクチャの目的の復習
以下、「Clean Architecture」から抜粋
- ソフトウェアアーキテクチャの目的は、求められるシステムを構築・保守するために必要な人材を最小限に抑えることである
- アーキテクチャの形状の目的は、そこに含まれるソフトウェアシステムの開発・デプロイ・運用を・保守を容易にすることである
- できるだけ長い期間、できるだけ多くの選択肢を残すことである。
- 決定を遅延できれば、その分だけ適切に作るための情報が数多く手に入る
- 境界線を引けば、決定を延期・留保できる
- システムのアーキテクチャは、ソフトウェアコンポーネントとそれらを分離する境界によって定義される
- 境界線は「重要なもの」と「重要ではないもの」の間に引く。GUIはビジネスルールにとって重要ではないので、その間に境界線を引く。データベースはGUIにとって重要ではないので、その間に境界線を引く。データベースはビジネスルールにとって重要ではないので、その間に境界線を引く
などなど、まだまだ重要な部分はたくさんあるけれど、とりあえずこれらの言葉から雑に纏めてみるならクリーンアーキテクチャは、**「システム開発のライフサイクルにおける手間暇を最小限に抑えるために、構築しやすく、デプロイしやすく、決定を遅延させる事が出来る構造を目指す仕組み」**なんだと思う。
(大体のアーキテクチャはこういう目的を持っていると思うけど、「決定の遅延」が入っているあたりが新しい?)
このために、アプリケーションをレイヤ化して、依存関係を一方向に調整して、外側にあればあるほど決定を遅延出来るように、構造でサポートする。
図はこちらから
構築時に最初に検討するのはユースケース
「Clean Architecture」に、こんな文章がある。
システムの最初のアーキテクチャを決めるための第一歩は、アクターとユースケースを見つけることだ
初見は「あれ?『エンティティ』(企業ビジネスルール)は?図でも中心を占めているし、本文中でも何度も言及されている様に、何にも依存せず、システムの中核を成すのは『エンティティ』なはずだから、ここから作るべきなんじゃないの?」って感じた。多分みんな感じる。
でも考えてみたら、エンティティというか、それが表す企業ビジネスルールのモデル化を最初に始めるのは、不可能なんですね。
エンティティが表現する企業ビジネスルールは、その企業のビジネスそのものじゃなくて、その一部だけ。
その実装のためには、まずは既存ビジネスの内、どのルールをその対象にすれば良いのかを決定する必要がある。
じゃあ、その特定のルールの抽出は、どんな仕組みを持って行えば良いのか。
これはもう、「ユースケース」から抽出するしかない。
「ユースケース」には、これから作り上げようとするシステムが最終的に実現したい情報が詰まっている。
実は必要になる企業ビジネスルールだってここに内包されている。
という事は、「エンティティ」を規定しているのは「ユースケース」という事になる。
コード上では分離しているものの、アプリ全体で見た場合には、実は実質的には、「エンティティ」は「ユースケース」に依存してるわけです。
だから、構築時に最初に検討しなければならないのは、「ユースケース」(とそれを使用するアクター)になる。
というか、それでしか検討を始められない。
この本文は、そういう意味なんでしょう。
(この点、クリーンアーキテクチャで言うところの「アプリケーションビジネスルール=ユースケース」は、名が体を表していないんじゃないかな、って気がする。ユースケースには実質的に、企業ビジネスルールだって含まれてるはず)
ここからクリーンアーキテクチャを目指した初期構築時の作業順を考えると、以下の様になるんじゃないかと。
- ユースケース把握(つまり要件定義)
- ユースケースを満たすために必要な企業ビジネスルールを抽出
- 企業ビジネスルールを満たすエンティティを実装
- エンティティに依存する形で、ユースケース層を実装
- ユースケースに依存する形で、インターフェース層を検討・実装
- インターフェースに依存する形で、DBやウェブサーバといった「詳細」部分を検討・実装
既存システム改修時に最初に検討するのは、詳細の分離
既存システムの改修でクリーンアーキテクチャを目指す場合は、構築時とは検討する観点を変える必要がある。
まず、アプリケーションに必要な情報はすべて、動作しているコードに織り込まれているという前提がある。
なので、アプリケーションビジネスルールの把握という作業は無いし、そこから企業ビジネスルールを抽出するという作業も必要が無い。
また、既に動いているシステムなのだから、決定の遅延も何もない。
なので、遅延の観点からDBやウェブサーバといった「詳細」についての作業を最後に持って行くべきという道理もない。
遅延の問題が無いので、既存システムの改修でクリーンアーキテクチャを目指す場合は、新規構築時とは目的そのものの優先順位を変える必要がある。
改修時に目指すのは決定の遅延ではなく、依存関係の調整による、保守やデプロイの容易さの追求になる。
そのためには、何を最初に行えば良いんだろう。
多分、まず最初に考えるのは新規構築時の逆で「詳細」の分離でしょう。
理由は、「詳細」に関わる依存関係を整理する方が、他の部分の依存関係を整理するよりも、利点が大きいから。
例えば「ユースケース->エンティティ」の分離。
もちろん、エンティティが独立しており、ユースケースがそこに依存する形の方が、責任が分割されて扱いやすいコードになるのは間違いないのだけれど、でも、既存システムでユースケースやエンティティを担っていたコードは、おそらく既にそこかしこで「詳細」に依存してしまっているでしょう。
これを取り除かない内に、ユースケースとエンティティの依存関係を整理したところで、さほど扱いやすくもならないはず。
せっかく分離をしても、まだ依存関係がごちゃごちゃしたままという事になってしまって、これでは意味がない。
やっても効果が見込めないので、優先度は落ちる。
同じ理由で「インターフェース->ユースケース」の依存関係の調整も、優先度は落ちる。
「詳細」は、クリーンアーキテクチャではどこからも依存されない事を目指す層なのに、おそらく既存の実装では、どこよりも多く依存されてしまっている可能性が高い(DB関連なんかは特に)
インターフェースに相当する部分も、ユースケースに相当する部分も、エンティティに相当する部分でも、広範に「詳細」に依存している。
これを引き剥がすだけでも、扱いやすさは格段に上がるはず。
さらに、「詳細」最終的には何も依存しない事を目指すのだから、分離し終えたらそれ以上詳細に手を加える所は無い。
後にはスッキリした依存関係が残るはずだ。
後腐れがない。
手を付けやすいし、管理しやすいし、後にもつなげやすいのだから、まずは「詳細」の分離から始めたいところ。
その次はどうしよう。同じように、アプリケーションの中核(ユースケースとエンティティ)から遠い順に、分離をしていけばいいか。
ユースケースとエンティティは運命共同体で、その修正のタイミングは同じになる可能性がとても高い(多分)のだから、この分離は最後で良い。
ここから既存システムをクリーンアーキテクチャに寄せる改修の作業順を考えると、以下の様になるんじゃないかと。
- 「詳細」に対応するインターフェースを検討・実装
- 「詳細」から遠い層(多分既存ビジネスロジック層)から順に、詳細そのものではなくそのインターフェースに依存する様に修正
- すべての「詳細」について、1,2を繰り返す
- インターフェース層を責務(アクター)に合わせる形で再調整
- 既存ビジネスロジックを、責務(アクター)に合わせてインターフェース層から呼び出される形に修正
- ユースケースとエンティティを分離
おしまい
後記
これを既存のRailsでこれをやるなら、まずはActiveRecordのModelからの分離を目指す事になりますね。
その時点で気が遠くなるし、それRailsの意味あるのって感じだけど、それでもある程度規模の大きいシステムになってたら、分ける利点は大きいんじゃないかって気がしてます。なんとなくだけど。
ただ、Rubyにはインターフェースが存在しないんで、相当頑張らないと直ぐに実装がクリーンアーキテクチャから乖離しそうだし、改修より維持が難しそうですね。
チームマネジメントもセットで考えないとどうにもならなくなりそう。
ところで、技術書典6に行って来たんですけど、ざっと見た感じだと、クリーンアーキテクチャについての本は見かけませんでした。
タイミング的に和訳がまだ出たばかりだからですかね。
多分需要はあると思うんで、次回に期待してます。