Laravel - 『ドメイン駆動設計入門』してみて Clean な世界を垣間見た話し

## 要約 / inb4 tl;dr

- 『[ドメイン駆動設計入門 ボトムアップでわかる！ドメイン駆動設計の基本](https://amzn.to/2VFuaNm)』 を読んで DDDの初歩 について学んだら、以前から気になっていた Clean Architecture についての記事も理解しやすくなった。
  - [Laravelで実践クリーンアーキテクチャ - Qiita](https://qiita.com/nrslib/items/aa49d10dd2bcb3110f22)
  - [Laravelでクリーンアーキテクチャ - Qiita](https://qiita.com/nrslib/items/eaf39be65b2ebe5ccf08)
- 前回の記事で実装したディレクトリ構成を改めて見直した。
  - 前回の記事：[Laravel - 『ドメイン駆動設計入門』を読んで Laravel を使って実装してみた - Qiita](https://qiita.com/anfangd/items/fea7735a9c81983b5426)
- それっぽい構成が出来たので、今後実装する時のために思考を整理してみた。

## はじめに

[前回の記事](https://qiita.com/anfangd/items/fea7735a9c81983b5426) でも書いたのですが、2020年2月9-11日に開催された PHPerKaigi2020 に参加してきました。

[![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/79222/a3e60775-72bf-1df0-bbad-54932e1cadb1.png)
PHPerKaigi 2020](https://phperkaigi.jp/2020/)

ここで以下の本を知り、DDDの面白さにのめり込み、ここ数日はずっと関連書籍を眺めております。

[![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/79222/9bc71398-4393-3ed2-6689-0763006cd028.png)
ドメイン駆動設計入門 ボトムアップでわかる！ドメイン駆動設計の基本 - Amazon](https://amzn.to/2IfEIeo)

上図の書籍に記載したサンプルコードを Laravel で書き起こしてみて、なんとなく雰囲気は掴んだのですが、実践する場合のアーキテクチャ部分にモヤモヤが残っていました。

そこで、以下のコードなどを参考にしながら オレオレ・クリーン・アーキテクチャ Based on DDD を作ってみました。

- [nrslib/LaraClean](https://github.com/nrslib/LaraClean)
- [nrslib/StrictLaraClean](https://github.com/nrslib/StrictLaraClean)
- [shin1x1/laravel-ddd-sample](https://github.com/shin1x1/laravel-ddd-sample)
- [VaughnVernon/IDDD_Samples](https://github.com/VaughnVernon/IDDD_Samples)

主要な要素を 成瀬允宣さん（[Twitter](https://twitter.com/nrslib) , [nrslib](https://nrslib.com/) ）の記事やコードを参考とさせて頂きつつ、情報を再編成しながらまとめてみたというのが、この記事の概要です。

## DDD で Clean な アーキテクチャ

そんなわけで、【 DDD × Clean Architecture × Laravel 】で良い感じの構成を考えてゆきます。

### The Clean Architecture

クリーンアーキテクチャといえばこの図というのが以下（らしい）です。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/79222/04d61775-eef8-df9c-bf4b-81c5976948ac.png)
引用：The Clean Architecture 13 August 2012 - Clean Coder Blog
https://blog.cleancoder.com/uncle-bob/2012/08/13/the-clean-architecture.html

この図は、上記の Uncle Bob こと Robert C. Martin 氏 のブログ記事や、書籍『[Clean Architecture　達人に学ぶソフトウェアの構造と設計](https://amzn.to/39Kxnzm)』で紹介されています。

また、同じ文脈で以下の図も クリーンアーキテクチャ を表現する図として知られています。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/79222/16a752e0-e548-e3b0-0a80-59713cf29f74.png)

この２番目の図は、ネット記事では出どころが明記されているものがあまりなかったのですが、書籍『[Clean Architecture　達人に学ぶソフトウェアの構造と設計](https://amzn.to/39Kxnzm)』の中に、同心円図の後にこの図が紹介されてました。（注：\<DS>[^1]、\<I>[^2]）

### DDD & The Clean Architecture

全く関係の無さそうな上の２つの図ですが、[成瀬さんの記事](https://qiita.com/nrslib/items/aa49d10dd2bcb3110f2) を見ると、実は密接に関連していることが分かりました。
そこで、モノクロの２番目の図に、同心円で使われた色を使って分類すると下図のようになりました。

![tenh-note-laravel-ddd (11).jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/79222/bb2d91d9-cfe2-a9b6-8a59-d0e86a771e42.jpeg)


少しだけ分かりやすくなった気がします。
こういった Clean Architecture と DDD の関連については、以下の記事で詳細に説明されています。

- [Laravelで実践クリーンアーキテクチャ - Qiita](https://qiita.com/nrslib/items/aa49d10dd2bcb3110f22)
- [Laravelでクリーンアーキテクチャ - Qiita](https://qiita.com/nrslib/items/eaf39be65b2ebe5ccf08)
- [ドメイン駆動設計のエンティティとクリーンアーキテクチャのエンティティ │ nrslib](https://nrslib.com/clean-ddd-entity/)

次に、上記の記事で解説された内容をざっくりと表にまとめてみます。

#### 『Clean な同心円図』 と 『DDD』

まずは 同心円図 と DDD。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/79222/2fff2493-c64b-af32-71ff-8cd457643cee.png)


|#|Clean|DDD|
|:--|:--|:--|
|1|Entities|Domain Model<br>(Entity, Value Object, Domain Service)|
|2|Use Cases|Application Service|
|3|Controllers|-|
|4|Gateways|Repository|
|5|Presenter|-|

#### 『Clean な同心円図の右下』 と 『DDD』

同心円図の右下の図と DDD。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/79222/53941909-39be-7e0c-a80b-e04fc37db1a2.png)


|#|Clean|DDD|
|:--|:--|:--|
|1|Controller|-|
|2|Use Case <br>Input Port|Application Service <br>Interface|
|3|Use Case <br>Interactor|Application Service|
|4|Use Case <br>Output Port|???|
|5|Presenter|???|

#### 『データベースを使ったWebベースの～』 と 『DDD』

「Webベースのシナリオ～」の図 と DDD。

|#|Clean|DDD|Code|
|:--|:--|:--|:--|
|1|Controller|-|**Controller|
|2|Presenter|-|**Presenter|
|3|View Model \<DS>|-|**ViewModel|
|4|View|-|blade|
|5|Input Data \<DS>|Command Object<br>(DTO)|**Request|
|6|Input Boundary \<I><br>Use Case Input Port|Application Service <br>Interface|**UseCaseInterface|
|7|Use Case Interactor|Applicatoin Service|**UseCaseInteractor|
|8|Output Boundary \<I><br>Use Case Output Port|-|**PresenterInterface|
|9|Output Data \<DS>|-|**Response|
|10|Data Access Interface \<I>|Repository Interface|**RepositoryInterface|
|11|Data Access|Repository|**Repository|
|12|Database|-|(MySQL)|
|13|Entities|Domain Model<br>(Entity, Value Object, Domain Service)|User<br>UserId<br>UserService<br>Specification|

#### 『データベースを使ったWebベースの～』に DDD な名前を当てはめる

前節までの情報を元に、DDDの概念を『データベースを使ったWebベースの～』図にあてはめると以下のようになりました。

![img.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/79222/039810e4-d88a-f782-5e59-44b1c5033a92.jpeg)

おぉ。なんとなく、なんとなくそれっぽい。

### ぼくのかんがえたさいきょうの

そんなこんなで [前回の記事](https://qiita.com/anfangd/items/fea7735a9c81983b5426) で実装したコードの構成を改変して以下のような オレオレ・クリーン・アーキテクチャ Based on DDD が出来上がりました。

![img.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/79222/f3f64863-5e13-7cff-75c6-6981e25d98ad.jpeg)

ざっくりディレクトリ構成は以下の感じです。

```bash:Laravel_Directory_Structure
# OreOre Architecture based on DDD using Laravel
# 
# - Entities と UseCases と pacakes ディレクトリ配下に Domain/Context 単位に作成
#   - 以下の場合は Techno が namespace のトップ。
# - `Clean` な方の `Interface Adapter` は `Laravel/app` に配置。
# 
/
├── packages/
│  └── Techno                        # DDD: Domain
│      └── Sns                       # DDD: Context (Sub Domain ?)
│          ├── Entity                # Clean: Entities
│          │   ├── Core              # 抽象化オブジェクトなど
│          │   ├── Exceptions        # ドメイン特有の例外クラス
│          │   ├── Model
│          │   │   ├── Circle        # DDD: Entity, Value Object, Specification
│          │   │   └── User          # DDD: Entity, Value Object, Specification
│          │   └── Service           # DDD: Domain Service
│          └── UseCase               # Clean: Use Cases
│              ├── Application       # Clean: Use Case Interactor
│              │   ├── Circle        # DDD: Application Service
│              │   │   ├── Create    # ex.) CircleCreateUseCaseInteractor
│              │   │   ├── Invite
│              │   │   ├── Join
│              │   │   └── Update
│              │   └── User          # DDD: Application Service
│              │       ├── Delete    # ex.) UserDeleteUseCaseInteractor
│              │       ├── GetInfo
│              │       ├── Register
│              │       └── Update
│              └── Interface
│                  ├── Circle        # Clean: Input Data, Input Boundary, Output Boundary, Output Data
│                  │   ├── Create    # ex.) CircleCreateUseCaseInterface, CircleCreateRequest, CircleCreateResponse, CircleCreatePresenterInterface
│                  │   ├── Update
│                  │   ├── Invite
│                  │   ├── Join
│                  │   └── Gateway   # Clean: Gateways ( Data Access Interface)
│                  └── User          # Clean: Input Data, Input Boundary, Output Boundary, Output Data
│                      ├── Delete    # ex.) UserDeleteUseCaseInterface, UserDeleteRequest, UserDeleteResponse, UserDletePresenterInterface
│                      ├── Update
│                      ├── GetInfo
│                      ├── Register
│                      └── Gateway   # ex.) UserRepositoryInterface, UserFactoryInterface, UserNotificationInterface
│
├──app/
│  ├── Aspect
│  │   └── Modules
│  │       ├── LogExceptionsModule.php
│  │       ├── LoggableModule.php
│  │       └── TransactionalModule.php
│  ├── Console
│  ├── Database
│  │   └── Eloquent
│  ├── Exceptions
│  ├── Http
│  │   ├── Controllers               # Clean: Controllers
│  │   │   ├── Auth
│  │   │   ├── Controller.php
│  │   │   └── UserController.php
│  │   ├── Kernel.php
│  │   ├── Middleware
│  │   ├── Models
│  │   └── Presenter                 # Clean: Presenters
│  │── Providers
│  │   └── AppServiceProvider.php
│  └── Gateway                       # Clean: Gateways (Data Access)
│       ├── Notification             # ex.) UserNotification
│       ├── Eloquent
│       │   ├── Circle               # ex.) ELCircleRepository
│       │   └── User
│       ├── InMemory
│       │   ├── Circle               # ex.) IMCircleRepository
│       │   └── User                 # ex.) IMUserRepository
│       └── QueryBuilder
│           ├── Circle
│           └── User                 # ex.) QBUserRepository
├── bootstrap
├── composer.json
├── config
├── resources                        # Clean: View
├── routes
└── tests/
    ├── Feature
    │   └── Http
    │       └── Controllers
    └── Unit
        └── packages
            └── Techno

```

### 残課題

- UseCase 内に配置した `RepositoryInterface` などなどの位置付けに悩み中です。

## おわりに

まだ「絵に書いた持ち」状態なので、余裕があれば Code と共にアップデートします。

## 参考

以下の Web勉強会 を聞きながらこの記事を書いてましたが、これもまた大変勉強になりました。

[![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/79222/e30f62ea-96a8-4227-8855-48f39ba5995b.png)](https://twitter.com/little_hand_s/status/1236121490208088065?s=20)

- [ドメイン駆動設計 モデリング/実装ガイド - little-hands - BOOTH](https://little-hands.booth.pm/items/1835632)
- [2020.3.8 ドメイン駆動設計 モデリング/実装入門勉強会](https://app.sli.do/event/imvxc56h/live/questions)
- [little-hands/ddd-task-management-sample](https://github.com/little-hands/ddd-task-management-sample)
- [ドメイン駆動設計 モデリング_実装入門勉強会_2020.3.8](https://www.slideshare.net/koichiromatsuoka/202038)

書籍も購入しました！

[![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/79222/321459da-e7df-456d-897f-dc58d4c2af40.png)<br>ドメイン駆動設計 モデリング/実装ガイド - little-hands - BOOTH](https://little-hands.booth.pm/items/1835632)

## あと書き

そもそもは 【 Kotlin + Spring Boot 】 が今後の潮流になると思い、お試し実装の前に アーキテクチャについて調べだして出会ったのが DDD 本でした。
最初から Kotlin で実装するより、ある程度慣れている Laravel で実装しようと思い色々と調べてみて、多くの参考になる情報に出会うことが出来ました。

ここまで調べてみて、 Clean Architecture 以外の実装パターンについても知りたい欲が強くなり、 Layered Architecture 、 Hexagonal Architecture 、 Onion Architecture などなど、自分なりに腹落ちする解釈を得たいと感じてますが、個別の解説記事はあれど、体系的に解説された情報に行き着いておりません。

いまの所、以下の記事が一番全体像を掴んでいるのでは、というところ。

- [DDDからみた基盤となるアーキテクチャ • masu-mi's blog(Dirty Cache)](https://blog.masu-mi.me/post/2019/01/17/arch-as-basis-from-ddd/)

DDD も 各種アーキテクチャも、時代ごとのバックボーンを背景に生まれ、適用されてきており、そういった情報も含めて全体像を掴んでみたいです。どこかに良いまとめはないものか。

### 欲しいものの整理

- ★ フルスクラッチでシステム構築する時の参考となる Directory / File のサンプルとその解説情報
  - ◉『「軽量DDD」を突き詰める』感じになりそう。
  - ◉対象のシステム
      - Mobile ( iOS/Swift / Android/Kotlin )
      - Web Application
         - Web Client Application ( Web Frontend ) - Vue, React
         - Web Server Application ( Web Backend ) - PHP/Laravel, Kotlin/SpringBoot
      - mBaaS や FaaS 、IDaaS などとの付き合い方
      - 時代背景によってことなるはずなので、1970年以降で整理すると良いかも。
         - システムの用途
         - システムが与えた社会的影響
         - 主要技術
         - 主要デバイス
         - 主要インターフェース
         - 主要通信技術
         - 主要システム構成
         - 主要言語と言語の特徴
         - 主要プロトコル
         - 例えば
             - Main Frame
             - Personal Computer
             - Client-Server
             - World Wide Web
             - Web Application
             - Mobile Application
             - Cloud
  - ◉解説情報
     - MVC , MVP , MVVM などとの関係
     - 時代背景を元に、その概念やデバイスが生まれた経緯や適用された方法など
         - Layered Architecture
         - Layered Architecture with DIP (Dependency inversion principle)
         - Hexagonal Architecture
         - Onion Architecture - [The Onion Architecture : part 1 | Programming with Palermo](https://jeffreypalermo.com/2008/07/the-onion-architecture-part-1/)
     - 情報の原典となる書籍や記事
         - 書籍：エリック・エヴァンスのドメイン駆動設計　（[原作](https://amzn.to/38Abhym)、[和訳](https://amzn.to/2wE7iU7)）
         - 書籍：実践ドメイン駆動設計　（[原作](https://amzn.to/39GoSWo)、[和訳](https://amzn.to/2v3OWLO)）
         - 書籍：ユースケース駆動開発実践ガイド　（[原作](https://amzn.to/2TN1T4Z)、[和訳](https://amzn.to/2PWJ9z5)）
         - 書籍：モデルベース要件定義テクニック　（[書籍](https://amzn.to/2PY6L6i)）
         - 書籍：Clean Architecture　達人に学ぶソフトウェアの構造と設計　（[原作](https://amzn.to/2PYJHVb)、[和訳](https://amzn.to/38AXXKb)）
         - WebSite：ヘキサゴナルアーキテクチャ - blog.tai2.net　（原作 - サイト工事中、[和訳](https://blog.tai2.net/hexagonal_architexture.html)）
         - WebSite：Clean Architecture - Clean Coder Blog - Uncle Bob　（[原作](https://blog.cleancoder.com/uncle-bob/2012/08/13/the-clean-architecture.html)、[和訳](https://blog.tai2.net/the_clean_architecture.html)）
         - WebSite：[DDD Resources - Domain Language](https://domainlanguage.com/ddd/)
      - 情報の濃度と段階
          - よく言われるやつ
              - 実体験
              - メディア
                 - 新聞
                 - 雑誌
                 - 書籍
                 - Web
                 - 動画
                 - TV
                 - 研究論文
          - 整理したい対象
              - 原典
              - 解説書籍
              - 解説の解説書籍
              - 実装例
              - 調べてみた系
          - 生データに近いものを見つけて整理する
- 実践的DDD
  - [リレーションシップ駆動要件分析(RDRA) - Qiita](https://qiita.com/tatane616/items/f7f4e5ad818fe8b125d6)
  - [ICONIX - Wikipedia](https://ja.wikipedia.org/wiki/ICONIX)

[^1]: \<DS> : Data Structure
[^2]: \<I> : Interface