Slide 1

Slide 1 text

ドメイン駆動設計 と 依存性逆転の原則 株式会社ユニクエスト 長谷川広樹 github.com/hiroki-it @Hiroki__IT

Slide 2

Slide 2 text

自己紹介 ▼ お仕事 最近:クラウドインフラ、IaC、CICD、... 以前:DDD ▼ 関心のある技術領域 ・クラウドインフラ ・IaC ・DDD github.com/hiroki-it @Hiroki__IT 長谷川 広樹 (はせがわ ひろき) 株式会社ユニクエスト

Slide 3

Slide 3 text

目次 ■ なぜ,我々は依存関係を理解する必要があるのか ■ 依存(前回のおさらい) ■ 依存オブジェクト注入の種類(前回のおさらい) ■ ドメイン駆動設計の原著のアーキテクチャ ■ インフラ層で使われるデザインパターン ■ レイヤードアーキの問題点 ■ 解決策 ■ ドメイン駆動設計のアーキテクチャ変遷 ■ SOLIDの原則 ■ B:実装が抽象に依存するべき ■ A:上位と下位のレイヤーの両方が抽象に依存するべき ■ 『依存性逆転の原則』の成立 ■ 改めて,アーキテクチャを見る

Slide 4

Slide 4 text

なぜ,我々は依存関係を理解する必要があるのか オブジェクト間の依存関係を 意識しながら 実装されてますでしょうか??

Slide 5

Slide 5 text

なぜ,我々は依存関係を理解する必要がある? 基本的なMVCから始まりアーキテクチャには オブジェクト間の依存関係を工夫して 保守性の高いシステムを開発しようとする思想がある 依存関係を理解しなければ アーキテクチャを正しく使えない!(持論)

Slide 6

Slide 6 text

依存(前回のおさらい) ■ 依存とは クラスAがクラスBを引数/返却値として使用 『 A 』は『B 』に依存 ■ クラス図における依存 (例)UserクラスはUserNameクラスを使用 getName(); } }

Slide 7

Slide 7 text

依存オブジェクト注入の種類(前回のおさらい) ■ コンストラクタインジェクション constructメソッド経由で依存対象を渡す. ■ メリット constructメソッドはインスタンス生成時のみ有効. セッターを完全に無くした場合に インスタンス生成後に状態を変更不可能. 不変的な(Immutable)オブジェクト より安全なシステム name = $name; } }

Slide 8

Slide 8 text

ドメイン駆動設計の原著のアーキテクチャ ドメイン層 インフラストラクチャ層 プレゼンテーション層 ユースケース層 ※順にコンストラクタインジェクションを実行していく ■ プレゼンテーション層  ・データの必須や書式に関するバリデーション  ・レスポンス構造の整形 ... ■ ユースケース層  ・システムの振舞(ユースケース)を具現化 ... ■ ドメイン層  ・要件定義で作成したドメインモデル図を具現化  ・ビジネス上ありえない値をバリデーション ... ■ インフラストラクチャ層  ・Active Recordではなく,リポジトリを使う  ・データを取得し,ドメインモデルを作成 ... レイヤードアーキ

Slide 9

Slide 9 text

インフラ層で使われるデザインパターン ■ リポジトリパターン  ・極論,DBは何でもよい.  ・複数のテーブルからデータを取得し,   ドメインモデルを作成.  ・ドメインモデル間の依存関係の設計が自由  ⇒ ドメイン駆動設計に合う ■ ちなみに,Active Recordパターン  ・モデルが特定のテーブルに関連づけられる.  ・テーブル間のリレーションの設計が,   そのままドメインモデル間の依存関係になる.  ⇒ ドメイン駆動設計には合わない 引用: https://terasolunaorg.github.io/guideline/public_review/ImplementationAtEachLayer/DomainLayer.html

Slide 10

Slide 10 text

レイヤードアーキの問題点 リポジトリパターンを採用しても インフラ層への依存関係を 完全に除去できない インフラ層の修正がドメイン層に影響 ビジネスに影響 ドメイン層 インフラストラクチャ層 プレゼンテーション層 ユースケース層 ドメイン層は他レイヤーに依存させたくない

Slide 11

Slide 11 text

解決策 ~ 先人の知恵 ~ 『依存性逆転の原則』を組み込んだら良いのでは?? ドメイン層 インフラストラクチャ層 プレゼンテーション層 ユースケース層 矢印の向きを揃えると,インフラ層が最上位になる ドメイン層 インフラストラクチャ層 プレゼンテーション層 ユースケース層

Slide 12

Slide 12 text

ドメイン駆動設計のアーキテクチャ変遷 オニオンアーキ 原著から変遷して,依存性逆転の原則が組み込まれた 引用: ・https://little-hands.hatenablog.com/entry/2017/10/11/075634 ・https://blog.cleancoder.com/uncle-bob/2012/08/13/the-clean-architecture.html クリーンアーキ ドメイン層 インフラストラクチャ層 プレゼンテーション層 ユースケース層 レイヤードアーキ

Slide 13

Slide 13 text

SOLIDの原則 ■ SOLIDの原則とは オブジェクト指向プログラミングにおいて, スケーラビリティ,保守性,可読性を高めるための5つの方法のこと ■ 5原則 ・S:Single Responsibility Principle(単一責任の原則) ・O:Open Closed Principle(オープン・クローズドの原則) ・L:Liskov Substitution Principle(リスコフの置換原則) ・I:Interface Segregation Principle(インターフェース分離の原則) ・D:Dependency Inversion Principle(依存性逆転の原則)

Slide 14

Slide 14 text

依存性逆転の原則 ■ 依存性逆転の原則とは  A:上位と下位のレイヤーの両方が抽象に依存するべき.  B:実装が抽象に依存するべき. ■ レイヤードアーキに組み込むメリット  ・ドメイン層が他レイヤーに依存しなくなる.  ・ユースケース層に影響を与えずに,インフラ層のリポジトリクラスを交換しやすくなる.   ⇒ テスト時のみ実装リポジトリクラスをモックリポジトリへのエイリアスとすれば,     DBにアクセスしないユニットテストが可能.(モックリポジトリは値を返却するだけ)   ⇒ リプレイス時に異なるリポジトリクラスに交換可能.

Slide 15

Slide 15 text

B:実装が抽象に依存するべき

Slide 16

Slide 16 text

A:上位と下位のレイヤーの両方が抽象に依存するべき FooRepositoryIF FooRepositoryImpl FooController FooInteractor ⇒ インターフェースリポジトリはドメイン層に置く 下位レイヤーが抽象(インターフェース)に依存 ⇒ 実装リポジトリクラスはインフラ層に置く

Slide 17

Slide 17 text

A:上位と下位のレイヤーの両方が抽象に依存するべき ユースケース層のクラスが ドメイン層のインターフェースリポジトリに依存するには どのようにすればよい? ユースケース層で使う実装リポジトリクラスのデータ型を インターフェースリポジトリとして扱えればよい

Slide 18

Slide 18 text

A:上位と下位のレイヤーの両方が抽象に依存するべき PHP(クラス),Java(クラス),Go(構造体)... 実装リポジトリのデータ型を インターフェースリポジトリとして扱うことが可能

Slide 19

Slide 19 text

A:上位と下位のレイヤーの両方が抽象に依存するべき fooRepositoryIF = $fooRepositoryIF; // データ型はドメイン層のインターフェースリポジトリ } public function getFoo(FooId $id): Foo { return $this->fooRepositoryIF->findById($id); // インターフェースを経由してメソッドをコール } }

Slide 20

Slide 20 text

A:上位と下位のレイヤーの両方が抽象に依存するべき FooRepositoryIF FooRepositoryImpl FooController FooInteractor ⇒ インターフェースリポジトリはドメイン層 上位と下位レイヤーの両方が抽象(インターフェース)に依存 ⇒ 実装リポジトリクラスはインフラ層 ⇒ ユースケース層はドメイン層を使用する依存関係

Slide 21

Slide 21 text

『依存性逆転の原則』の成立  A:上位と下位のレイヤーの両方が抽象に依存するべき.  B:実装が抽象に依存するべき. AとBを実現できたため 『依存性逆転の原則』が成立

Slide 22

Slide 22 text

改めて,アーキテクチャを見る オニオンアーキ 『依存性逆転の原則』がわかるぞ! クリーンアーキ

Slide 23

Slide 23 text

余談 依存性逆転の原則ではないが,上位レイヤーが抽象に依存

Slide 24

Slide 24 text

最後に テーマと関係ないけど Gopherくん超かわいい!!! by Takuya Ueda (https://twitter.com/tenntenn) The Gopher character is based on the Go mascot designed by Renée French.