世界一わかりやすいClean Architecture
~ 誤解されがちな二つのことと、おさえるべき二つのこと ~
Atsushi Nakamura
ふたつ質問させてください
Copyright 2019 @nuits_jp Slide 2
この図を見たことはありますか?
Copyright 2019 @nuits_jp Slide 3
書籍読んでみましたか?
Copyright 2019 @nuits_jp Slide 4
Easiest Clean Architecture
Today’s Goal
Today’s Goal
全員が
「クリーンアーキテクチャチョットデキル」
ようになること
Easiest Clean Architecture
Overview
Overview
Slide 8Copyright 2019 @nuits_jp
Clean Architectureの次の点についてお話させていただきます。
• 誤解されがちな二つのこと
• おさえるべき二つのこと
Easiest Clean Architecture
注意事項
注意事項
Slide 10Copyright 2019 @nuits_jp
今日お話しすることは、あくまで私の解釈です
• 極端に要約しているので、これがすべてではありません
• 書籍の記載とやや矛盾する点もあります
しかし、私は今日お話しする二つこそ、Clean Architectureの
本質だと思っています。
異論・反論大歓迎
Slide 11Copyright 2019 @nuits_jp
異論・反論大歓迎です。※
オンライン・オフラインいずれでも、ぜひご意見を聞かせてください。
ぜひ議論しましょう!
※ 聞く耳持たないマサカリはご遠慮ください
Easiest Clean Architecture
About Me
About Me
Copyright 2019 @nuits_jp Slide 13
中村 充志 / Atsushi Nakamura
• リコージャパン株式会社 所属
• Enterprise(おもに金融)系SIerのITアーキテクト
• 「持続可能なソフトウェア」の探求がライフワーク
• 2019年の目標
• 「世界一わかりやすいClean Architecture」で登壇したい
• 「xUnit & Moqハンズオン」開催
• Blog http://www.nuits.jp
• Blog(英語) https://blog.nuits.jp
• Twitter @nuits_jp
Easiest Clean Architecture
誤解されがちな二つのこと
Clean Architectureといえば・・・
出典:TheCleanArchitecture
https://blog.cleancoder.com/uncle-bob/2012/08/13/the-clean-architecture.html
この図が良くできてい過ぎて誤解を招く
Copyright 2019 @nuits_jp Slide 16
ひとつ目の誤解
Clean Architectureとは
「レイヤーをこれらに分割しろ」
という意味でもない
「関心をControllerやUse Case, Entityに分離しろ」
という意味ではないし
ふたつ目の誤解
「PresentationをMVC的に分離しろ(MVVMなどの否定)」
という意味ではないし
「データや処理の流れを一方通行にしろ」
という意味でもない
Copyright 2019 @nuits_jp Slide 18
MVC Model(出展Wikipedia)
では、どういう意味か?
Copyright 2019 @nuits_jp Slide 19
図の解釈
「依存性は、内側(上位レベルの方針)だけに
向かっていなければいけない。」※
Slide 20
※出典:Clean Architecture 達人に学ぶソフトウェアの構造と設計
図の解釈
こうすればよい ※
内側の変化に応じて、外側を呼び出したい場合どうすればよいのか?
Slide 21
※ より厳密な意図は後述
Easiest Clean Architecture
それあってますか?
はい(当者比)
-The architecture rules are the same! -
(邦訳:アーキテクチャのルールはどれも同じである!)
著者は明言しています
Copyright 2019 @nuits_jp Slide 24
すべてが同一アーキテクチャに帰結するとすれば
以下は、あくまで一例であることは自明
• レイヤーが4つ※1
• UIがMVC的である
• Web限定
• Output PortはUse Caseとの間「だけ」に
ある※2
• 中央がDomainじゃなくてEntities
※1 とは限らないと書籍にも明記されている
※2 eventみたいなPub/SubがUseCase限定じゃ困っちゃう
あくまで例示であると取れる記載もある
Clean Architecture説明の冒頭に、著名なアーキテクチャ(Hexagonal, Onion,
etc...)には類似の共通点が見られるとある。
そして続けてこう記載されている。
The diagram in Figure is an attempt at integrating all these architectures into a single
actionable idea.
(邦訳:図は、これらのすべてのアーキテクチャを単一の実行可能なアイデアに統合し
たものである。)
該当の図は、アーキテクチャは全てClean Architectureで説明可能であることを
例示したモデルであり、Clean Architectureを採用したソフトウェアの具体例の
一つにすぎない
Copyright 2019 @nuits_jp Slide 26
どんなソフトウェアにも適用可能な
普遍的なアーキテクチャである
だって↓だって言うし
-The architecture rules are the same! -
(邦訳:アーキテクチャのルールはどれも同じである!)
Chean Architectureとは
Copyright 2019 @nuits_jp Slide 27
Easiest Clean Architecture
おさえるべき二つのこと
ひとつ目
「依存性は、より上位レベルの方針にのみ向けよ」
ふたつ目
「制御の流れと依存方向は分離しコントロールせよ」
おさえるべき二つのこと
Copyright 2019 @nuits_jp Slide 29
ひとつ目
「依存性は、より上位レベルの方針にのみ向けよ」
ふたつ目
「制御の流れと依存方向は分離しコントロールせよ」
おさえるべき二つのこと
Copyright 2019 @nuits_jp Slide 30
Easiest Clean Architecture
さあ具体例を見てみよう!
• SQL ServerのサンプルDB AdventureWorksを利用します
• プロダクト別の総売上をCSV出力するコンソール アプリ
Overview
Copyright 2018 @nuits_jp Slide 32
Software Architecture
ではコードを見てみよう!
Copyright 2019 @nuits_jp Slide 34
Not Clean Architecture
Copyright 2019 @nuits_jp Slide 35
Not Clean Architecture
Copyright 2019 @nuits_jp Slide 36
依存方向
凡例
Software Architecture
依存方向
凡例
Not Clean Architecture
Copyright 2019 @nuits_jp Slide 38
依存方向
凡例
という訳で修正してみましょう
Copyright 2019 @nuits_jp Slide 39
これでCleanArchitectureになったでしょうか?
Copyright 2019 @nuits_jp Slide 40
Copyright 2019 @nuits_jp Slide 41
依存方向
凡例
Clean Architecture ?
Clean Architecture ?
Slide 42
Copyright 2019 @nuits_jp Slide 43
依存方向
凡例
Clean Architecture ?
Not Clean Architecture
Copyright 2019 @nuits_jp Slide 44
依存方向
凡例
Gatewayはこのままという選択肢はありですが・・・
Copyright 2019 @nuits_jp Slide 45
Software Architecture
依存方向
凡例
DBを呼び出さないといけないのに無理じゃない?
Copyright 2019 @nuits_jp Slide 47
• SQLを利用しないという意味ではない
• RDBというアーキテクチャには依存する
• 永続化データのスキーマに依存しないという意味
DBからGatewayへ依存させるとは?
Copyright 2019 @nuits_jp Slide 48
Not Clean Architecture
Copyright 2019 @nuits_jp Slide 49
依存方向
凡例
Gatewaysのクラス図とER図
Copyright 2018 @nuits_jp Slide 50
dm SalesOrderDetail and Product
Product
«column»
*PK ProductID: int
* Name: nvarchar(50)
* ProductNumber: nvarchar(25)
* MakeFlag: bit = 1
* FinishedGoodsFlag: bit = 1
Color: nvarchar(15)
* SafetyStockLevel: smallint
* ReorderPoint: smallint
* StandardCost: money
* ListPrice: money
Size: nvarchar(5)
FK SizeUnitMeasureCode: nchar(3)
FK WeightUnitMeasureCode: nchar(3)
Weight: decimal(8,2)
* DaysToManufacture: int
ProductLine: nchar(2)
Class: nchar(2)
Style: nchar(2)
FK ProductSubcategoryID: int
FK ProductModelID: int
* SellStartDate: datetime
SellEndDate: datetime
DiscontinuedDate: datetime
* rowguid: uniqueidentifier = newid()
* ModifiedDate: datetime = getdate()
SalesOrderDetail
«column»
*pfK SalesOrderID: int
*PK SalesOrderDetailID: int
CarrierTrackingNumber: nvarchar(25)
* OrderQty: smallint
*FK ProductID: int
*FK SpecialOfferID: int
* UnitPrice: money
* UnitPriceDiscount: money = 0.0
* LineTotal: numeric(38,6)
* rowguid: uniqueidentifier = newid()
* ModifiedDate: datetime = getdate()
クラス図 ER図
Gatewaysが完全にデータベースの文脈で記述されている
Gatewaysのクラス図とER図
Copyright 2018 @nuits_jp Slide 51
dm SalesOrderDetail and Product
Product
«column»
*PK ProductID: int
* Name: nvarchar(50)
* ProductNumber: nvarchar(25)
* MakeFlag: bit = 1
* FinishedGoodsFlag: bit = 1
Color: nvarchar(15)
* SafetyStockLevel: smallint
* ReorderPoint: smallint
* StandardCost: money
* ListPrice: money
Size: nvarchar(5)
FK SizeUnitMeasureCode: nchar(3)
FK WeightUnitMeasureCode: nchar(3)
Weight: decimal(8,2)
* DaysToManufacture: int
ProductLine: nchar(2)
Class: nchar(2)
Style: nchar(2)
FK ProductSubcategoryID: int
FK ProductModelID: int
* SellStartDate: datetime
SellEndDate: datetime
DiscontinuedDate: datetime
* rowguid: uniqueidentifier = newid()
* ModifiedDate: datetime = getdate()
SalesOrderDetail
«column»
*pfK SalesOrderID: int
*PK SalesOrderDetailID: int
CarrierTrackingNumber: nvarchar(25)
* OrderQty: smallint
*FK ProductID: int
*FK SpecialOfferID: int
* UnitPrice: money
* UnitPriceDiscount: money = 0.0
* LineTotal: numeric(38,6)
* rowguid: uniqueidentifier = newid()
* ModifiedDate: datetime = getdate()
クラス図 ER図
Gatewaysが完全にデータベースの文脈で記述されている
実際にはこの4項目しか
必要ない
たとえば・・・
• 他機能の変更で列が増える
• 影響がほぼないことは分かりきっている
• しかし回帰テストはせざるを得ない
テーブルの構造にダイレクトに依存してしまうと・・・
Copyright 2019 @nuits_jp Slide 52
Software Architecture
依存方向
凡例
ひとつ目
「依存性は、より上位レベルの方針にのみ向けよ」
ふたつ目
「制御の流れと依存方向は分離しコントロールせよ」
おさえるべき二つのこと
Copyright 2019 @nuits_jp Slide 54
本質的に大切なのは文脈である
Copyright 2019 @nuits_jp Slide 55
Not Clean Architecture
Copyright 2019 @nuits_jp Slide 56
依存方向
凡例
ここで言うGatewaysのDB依存とは
✖ DBを呼び出しているから
〇 DBの文脈(スキーマ)で記述されているから
Not Clean Architecture
Copyright 2019 @nuits_jp Slide 57
依存方向
凡例
DBがGatewaysの文脈で定
義されていればよい
???
CQRSを使え
Copyright 2019 @nuits_jp Slide 58
CQRS :Command-Query Responsibility Segregation
データベースの操作を次のふたつの責務に完全に分離する方法論
1. データベースを更新するCommand
2. データベースを参照するQuery
今回のケースはQueryに該当するため
Gatewayの文脈でQuery用のDBオブジェクトを用意します。
CQRSとは
Copyright 2019 @nuits_jp Slide 59
完ぺきなCQRSを適用するのは難しい。
また、場合によってはオーバースペックでさえある。
1. CommandとQueryのデータソースの完全分離
2. ドメインイベント
3. 非同期メッセージ
4. イベントソーシング
5. 結果整合性
6. などなど
そこで今日は、データベースのViewを使った軽量な方法論を紹介します※
※ 必ずしもViewを使えという訳ではない
とはいえ・・・
Copyright 2019 @nuits_jp Slide 60
これがCleanなArchitectureだ!
Copyright 2019 @nuits_jp Slide 61
※ 言い過ぎです
Clean Architecture
Copyright 2019 @nuits_jp Slide 62
依存方向
凡例
Clean Architecture!
Slide 63※ 言い過ぎでもないです
このアーキテクチャの完璧な再現性を見てください!
CQRSと類似概念にCQSがある
• コマンドクエリ分離原則(Command-Query Separation)
雑に言うと・・・
• CQRSはデータソースに対するパターン
• CQSはクラスに対するパターン
DBの文脈をGatewayで吸収する選択をする場合はCQSも検討する
CQSについて
Copyright 2019 @nuits_jp Slide 64
Easiest Clean Architecture
制御の流れと依存関係の分離
制御の流れと依存関係の分離
凡例
制御の流れ
依存方向
アプリケーション
コード
データベース
オブジェクト
一般的に
制御の流れ=依存方向
になりがち
<<具象概念>> <<具象概念>>
Slide 66
制御の流れと依存方向は分離しコントロールできる
Copyright 2019 @nuits_jp Slide 67
制御の流れと依存関係の分離
凡例
制御の流れ
依存方向
アプリケーション
コード
データベース
オブジェクト
そのためには関係のコントラクト(契約・仕様・お約束)
のコンテキスト(文脈)を制御する
<<具象概念>> <<具象概念>>
コントラクト
<<抽象概念>>
それぞれの具象概念は抽象的な契約(仕様)に依存する Slide 68
契約の文脈をコントロールする
アプリケーション
コード
<<具象概念>>
コントラクト
<<抽象概念>>
データベース
オブジェクト
<<具象概念>>
Slide 69
アプリケーション
コード
<<具象概念>>
コントラクト
<<抽象概念>>
データベース
オブジェクト
<<具象概念>>
凡例
制御の流れ
依存方向
文脈
-The architecture rules are the same! -
Copyright 2019 @nuits_jp Slide 70
システム
サブシステム
コンポーネント
ソフトウェアのフラクタル
Copyright 2018 @nuits_jp Slide 71
クラス
サブシステム
クラス
コンポーネント
クラス クラス
ソフトウェア エンティティすべてに、ここまでの話は適用可能
• 要素間のインターフェースの文脈により、制御の流れと依存関係は制御可能
• 依存関係によって、安定性と柔軟性をコントロール可能
ソ
フ
ト
ウ
ェ
ア
エ
ン
テ
ィ
テ
ィ
ソフトウェア エンティティ 代表的なコントラクト
システム OpenAPI(なんならCSVのFTP転送)
サブシステム OpenAPIやSwagger
コンポーネント プログラム インターフェース
クラス プログラム インターフェース
ソフトウェア エンティティとコントラクト
Copyright 2018 @nuits_jp Slide 72
文脈によって、制御の流れと依存方向は分離し制御せよ
クライアント
エンティティ
<<具象概念>>
コントラクト
<<抽象概念>>
サーバー
エンティティ
<<具象概念>>
Slide 73
クライアント
エンティティ
<<具象概念>>
コントラクト
<<抽象概念>>
サーバー
エンティティ
<<具象概念>>
-The architecture rules are the same! -
Copyright 2019 @nuits_jp Slide 74
Easiest Clean Architecture
まとめ
まとめ
Slide 76Copyright 2019 @nuits_jp
• Clean Architectureとは、どんなソフトウェアにも適用可能な普遍的な
アーキテクチャである
• Clean Architectureは、次のふたつを誤解されがち
• 参考図の通りに関心を分離するのがClean Architectureである
• PresentationとModelの境界はInputとOutputを分離すべし
• 次のふたつを理解せずClean Architectureは語れない
• 依存性は、より上位レベルの方針にのみ向けよ
• 制御の流れと依存方向は分離し制御せよ
ThankYou!
Any Questions?

世界一わかりやすいClean Architecture

Editor's Notes

  • #2 こんにちは。 それでは早速はじめさせていただきます。 本日は 「世界一わかりやすいClean Architecture ~ 誤解されがちな二つのことと、おさえるべき二つのこと ~」 というタイトルでお話しさせていただきます。 ちょっとマサカリ投げ放題みたいな内容なんですけど、皆さんくれぐれもお手柔らかにお願いします。
  • #3 さて、本題に入る前にふたつ質問させてください
  • #4 あまりに有名な図ですが、この図を見たことあるかた 良かったら挙手していただけますか?
  • #5 じゃぁもう一つ、この書籍読破したよって方挙手していただけますか? 読んでいない方、掛け値なしの名著だと思うのでまだ読まれていない方は、今すぐ購入して読みましょう。 個人的には
  • #6 というわけで、本セッションの目指すところでが
  • #7 今日は、この場にいる皆さんが 「クリーンアーキテクチャチョットデキル」 という状態になっていただくことを目指します。 ちょっと自信ない方は今のうちにご退席ください。嘘です。
  • #8 というわけで、本セッションの概要ですが
  • #9 クリーンアーキテクチャについて、おもに次のふたつの事をお話しさせていただきます。 ひとつは、クリーンアーキテクチャの誤解されがちな二つのことに対する解説。 もうひとつは、私がクリーンアーキテクチャについて、本当に重要だと考えているふたつの事について、お話しします。
  • #10 さて本題に入る前に、少し注意事項があります。
  • #11 今回お話しするのは、あくまで私の解釈です。 特に極端に要約しているので、今日お話しすることがすべてではないことはご理解ください。 また、書籍の記載とやや異なる説明もします。 それでも私は著者が本当に言いたかったこと、クリーンアーキテクチャでもっとも大切なことは今日お話しする二点にあると考えています。
  • #12 なお異論・反論は大歓迎です。 オンラインでご意見をいただいても良いですし、この後直接お話しさせていただくのも歓迎です。 寝不足なので、その辺で死亡してなかったらですがw ぜひ議論してさせていただけると嬉しいです。
  • #13 本題に入る前に最後にひとつ。 簡単に自己紹介させてください。
  • #14 中村充志と申します。 リコージャパンのソリューション開発部ってところで、主に金融機関向けの 受託開発でアーキテクトをやってます。 「持続可能なソフトウェア」というテーマで色々考えるのが最近の趣味です。 今年の目標の一つは今日でクリアしましたので、あとはテストのハンズオン開催ができると良いなと思ってます。 では、本題に入りましょう。
  • #15 まずは「誤解されがちな二つのこと」です。
  • #16 この図をご覧になったことのある方は多いんじゃないかと思います。
  • #17 実はこの図が良くできてい過ぎることが、大きな誤解を招く要因になっていると私は考えています。 どういうことでしょうか?
  • #18 ひとつは、この図は決してソフトウェアの関心を ControllerやUseCase、Entityに分離しろという意味でもなく レイヤーをこの4つに分割しろという意味ではないということです
  • #19 そしてふたつ目は右下のこれです。 これもPresentationを古典的なMVCのように設計しろという意味ではないですし データや処理の流れを一方通行にしろと言っている訳でもありません。
  • #20 では、どういう意味でしょうか?先の図で本当に大切なことは
  • #21 依存性は、外から中だけに向かっていなくてはいけない。 というたった一点にあります。 でもじゃぁ、例えばEntitiesの状態が変わったことで、UIを受動的に変化させたいみたいな 中から外を呼ばなければいけないときはどうすれば良いの? という疑問が、すぐに湧いてきますよね?
  • #22 右下の図は、内側の変化に応じて外側を呼び出したい場合に 依存性は外から中に向けたまま、処理の流れとして中から外に戻すにはどうすればよいのか? を例示しているものです。
  • #23 そんなこと言っても、本当にあってるのか?って今皆さん思いましたよね?
  • #24 はい。もちろん根拠あっての話です。 そもそも著者は書籍の先頭でこう明言しています。
  • #25 「アーキテクチャのルールはどれも同じである!」 日本語版では帯にも書かれていますよね。
  • #26 つまり、本当にすべてのソフトウェアが同一のアーキテクチャに帰結するとすれば ・レイヤーが4つ限定であったり ・UIがMVC的でMVVMなどを否定していたり ・そもそもWeb限定だったり ・中から外の呼び出しがApplicationレイヤーとInterface Adapterレイヤーの間だけで発生するわけがないですし ・中央がEntitiesじゃなくちゃだめで、DDDするななんて そんな分けないですよね?
  • #27 書籍を読めば、ちゃんと先の図があくまで例示であると書かれています。 もともとクリーンアーキテクチャの発表前は、ヘキサゴナルアーキテクチャとかオニオンアーキテクチャが広く共有されていました。 そしてそれらのアーキテクチャには類似の共通点があることも知られていました。 そしてクリーンアーキテクチャの解説には、それらの著名なアーキテクチャは、先ほどの図のように記述することで単一のアイディアに統合することを例示するために書かれた図なんです。 そう
  • #28 クリーンアーキテクチャというのは、どんなソフトウェアにも適用可能な普遍的なアーキテクチャなんです。 あえて言うと、クリーンアーキテクチャを採用しないという選択肢は、基本的には「あくまで基本的には」無いといって差し支えありません。
  • #29 では先の図のように実装することがクリーンアーキテクチャではないとしたら クリーンアーキテクチャについて何を抑えたらよいのでしょうか? 私はつぎのふたつこそ、本質的に重要なことだと考えています。
  • #30 ひとつめは先ほども話しました。 ソフトウェアは、より上位レベルの方針にのみ依存せよということ
  • #31 ふたつ目は ひとつめを実現するために、依存性を制御の流れから分離してコントロールするということです。
  • #32 てことで、ここからは具体例を見ながら解説したいと思います。
  • #33 今回はSQL ServerのサンプルDBであるAdventure Worksを利用します。 こちらにER図がありますが、これらのテーブルからプロダクト別の総売り上げをCSVに出力するコンソールアプリを作ります。
  • #34 アーキテクチャはもちろんクリーンアーキテクチャです。
  • #35 では早速コードを見てみましょう!
  • #36 さて、先ほどのコードをモデル化したのがこちらになります。 全体的にそう悪くないようにも見えるんですが、少なくとも二つは問題があります。 ひとつは、ぱっと見から分かりますね。
  • #37 この部分でUsecaseからPresenterに依存関係ができてしまっています。
  • #38 依存関係はPresentaerからUsecaseである必要があります。
  • #39 でも逆になっちゃっていますね。
  • #40 という訳で修正してみましょう。
  • #41 さて、これでクリーンアーキテクチャになったでしょうか? 先ほどのモデルで見直してみましょう。
  • #42 IPerenterが移動したことで依存方向がPresenterからUseCaseに移動しました。
  • #43 ちゃんと右下の図の通りになりましたね。 処理の流れは一方通行で、でもすべての依存は外から中に向いています。
  • #44 ただ厳密にいうとまだ中から外へ依存が向かっている箇所があります。 どこか?
  • #45 ここです。 Gatewayがデータベースに依存しています。
  • #46 GatewayはDatabaseに依存するという選択肢はもちろんありだと考えているのですが
  • #47 まぁ今回はせっかくなので、ここもDBからGatewayに依存するようにしてみたいと思います。
  • #48 でもGatewayはDBを呼び出さないといけないし DB操作にはSQLが必要ですよね? GatewayがDBに依存しないなんて実現可能なのでしょうか? 勿論可能ですがちょっと意味が異なります。
  • #49 もちろんSQLを利用しないという意味ではないですし RDBというアーキテクチャに依存しないという意味ではないです システム固有の永続かされたデータのスキーマに依存しないという意味です
  • #50 この部分を見てください。 Repositoryの実装ではProductテーブルとSalesOrderDetailに対応する クラスを作ってDBアクセスし、Repositoryの中でProductSalesインスタンスを 生成していましたよね? これらのクラスをよく見てみましょう。
  • #51 現在の実装は、リポジトリが完全にデータベースの文脈で記述されているのが見て取れます。 結構な列数がありますよね。
  • #52 しかし今回は、この4項目しか本来は必要ありません。
  • #53 テーブル構造にダイレクトに依存してしまうと、テーブル変更の影響をダイレクトに受けてしまいます。 他の機能の影響で列が増えて、実際にはほぼ影響がないのに回帰テストをしないといけない。 みたいな事に陥ったことはありませんか?
  • #54 そこでここの依存関係がDBからGatewayに向いていれば 少なくともGatewayには影響がないことが担保できます。 では実際にはどうするか?
  • #55 制御の流れと依存方向は分離することで、コントロールできます。
  • #56 大切なのは文脈です
  • #57 GatewayがDBへ依存しているというのはつまり Gatewayのクラス設計がDBのスキーマに依存していることを指しているのです
  • #58 そうではなく、DBがGatewayの文脈で定義されていればよいという事になります。 とは言え、これらのテーブルは別にこの機能のためだけにある訳じゃありませんよね。 ではどうすれば良いのか?
  • #59 最も一般的な回答は、CQRSを使いましょうという事になります。
  • #60 CQRSとは、端的にいうとデータベース操作を更新と参照に 責務を分離しなさいという方法論のことで 今回はQueryに該当します。 つまりGatewayの文脈に合わせたQuery用のオブジェクトをDB側に用意すればよいということになります。
  • #61 ただCQRSを完ぺきに適用しようというのは簡単じゃないです。 特に既存のシステムに組み込むには多大な努力が必要になりますし、そこまでしてもケースによってはやりすぎになってしまいます。 そこで、今回はDBのビューを使った手軽な方法を詳解したいと思います。
  • #62 ではサンプルコードを見てみましょう。
  • #63 結果的にこうなりました。 DBにはEntityのPdoructSalesの文脈に適用したViewを作成して、Repositoryからはそれを参照します。 こうすることで、DBつまり外から中に依存するように文脈が書き換えられました。
  • #64 完ぺきにこのアーキテクチャを実現していますね! さて、あらためて整理しましょう。
  • #65 なおCQRSと類似したものにCQSという概念があります。 CQRSはデータベースに対するパターンだったのに対して CQSはクラス、つまりコードにたいするパターンです。 DBの文脈をGatewayで吸収する選択をする場合は CQSも検討してみると良いかもしれません。
  • #66 さてあらためて 大切なのはやはり制御の流れから依存関係を分離することにあります。
  • #67 一般的に依存方向は制御の流れに引っ張られがちです。
  • #68 しかし、これらは分離してコントロールすることが可能です。
  • #69 そのためには二つの依存関係の間のコントラクト、つまり契約・仕様・お約束を文脈によって制御する必要があります。 抽象的なコントラクトを導出することで、それぞれの具象概念はどちらも、抽象概念であるコントラクトに依存することになります。
  • #70 そしてこのコントラクトをどちらの文脈で定義するかによって 具象概念間の依存関係を自由にコントロールすることができるようになります。
  • #71 「アーキテクチャのルールはどれも同じである」 という真意が何となく伝わってきたでしょうか?
  • #72 そもそもソフトウェアは良くフラクタルのようだと言われていますよね。 ①クラスとクラスがまとまってコンポーネントとなり ②コンポーネントとコンポーネントがまとまってサブシステムになります。そして ③サブシステムとサブシステムがまとまってシステムになります。 ④ここではクラス・コンポーネント・サブシステム・システムを、ソフトウェア エンティティと呼ぶことにします。 ⑤ソフトウェアエンティティのすべてにおいて、ここまでした話の内容は適用できます。 もちろんサブシステム間は例えばWeb APIになったりするでしょうけど どの要素間であっても、コントラクトの文脈を管理する事で 制御の流れと依存関係は制御することが可能です。
  • #73 こちらに各ソフトウェアエンティティごとの代表劇なコントラクトを上げてみました。 なんならシステム間でのやり取りがCSVとか固定長テキストであっても、そのファイルがどっちのシステムの文脈によってるかによって、システム間の依存関係はコントロールできるわけです。
  • #74 文脈によって、制御の流れと依存方向は分離し制御することが可能です。
  • #75 クリーンアーキテクチャがあらゆるソフトウェアにおいて 「アーキテクチャのルールはどれも同じである」 ことを受け入れていただけましたか?
  • #76 とうわけで、今日のお話は終わりになります。 最後に簡単にまとめましょう。
  • #77 ①クリーンアーキテクチャは、どんなソフトウェアにも適用可能な普遍的なアーキテクチャです ②クリーンアーキテクチャの代表的な図は、誤解されがちです ③クリーンアーキテクチャの本質的で本当に大切なことが二つはあって ひとつは 依存性はより上位レベルの方針、つまりオニオンアーキテクチャであれば外から中にだけ依存するべきであること そしてもう一つは 制御の流れと依存方向は分離してコントロールできるということです
  • #78 という訳で、本日の内容は以上になります。 ご清聴ありがとうございました。