【ミライトデザイン社内勉強会#21】「IDDD本から理解するドメイン駆動設計」輪読会~第12章「リポジトリ」~

### 前回の記事
[【ミライトデザイン社内勉強会#20】「IDDD本から理解するドメイン駆動設計」輪読会~第11章「ファクトリ」~ - Qiita](https://qiita.com/tkek321/items/f68548663aa63c7cf100)

## [実践DDD本 第12章「リポジトリ」～集約の永続化管理を担当～ \(1/3\)：CodeZine（コードジン）](https://codezine.jp/article/detail/11048)

### 前回、ファクトリの章でファクトリを利用するのは生成の時って話だったけど、再構築（リポジトリから取り出す）時もファクトリを利用することがあるの？

[p1](https://codezine.jp/article/detail/11048)

> ![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/364773/503a1446-4da8-2bdb-67fc-f97be535fe08.png)


- 基本的には難しい生成の処理でファクトリを使うので、再構築（DBから値とってきてオブジェクトに詰めるだけ）の場合はあんまり使うイメージはない
- リポジトリで再構築するのも、ファクトリで再構築するのもコードの内容はあまんまり変わらない気がするから、ファクトリを使う意味がない気がする
- ここでは再構築の処理をファクトリに切り出しているだけの気がする
- DBだけでは足りない時は（DBに保存されているデータプラス、APIで取得する値が必要とか）、ファクトリを作ることがあるのかも
- プロジェクトで、オブジェクトの生成はファクトリを使うっていうルールがある場合もあるかも
- 複雑なものを再構築する場合、集約の生成はファクトリでやるっていうルールになっている場合とかはファクトリを使う場合もある
    - ここで、ファクトリを使うかはそこまで重要な話ではないと思う
    - 使ってもいいし、使わなくてもいい
    - でも、再構築でファクトリを使う必要がある場合は少ない

### アプリケーションサービスでトランザクションを管理すると、アプリケーションサービスがインフラ層に依存することになりそうだけど問題ないの？

[p2](https://codezine.jp/article/detail/11048?p=2)

> ![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/364773/739ad17a-7529-51ff-2161-3db0bff5e20b.png)

- 本来はよくない
- でも、ここでやるしかないからここにいる
- トランザクションはいろんな方法があるPHPは実コードに書くけど、Javaだとアノテーションだったり
    - トランザクションの方法によってはUseCaseに書かなくてもいい方法もある
    - UseCaseでロールバックの処理を制御したい場合はJavaの場合でもUseCaseに書く必要がある
- トランザクションの方法としては3つ考えられる
    - IDDDにあるようにアプリケーション層で使用
    - AOPを使用してアノテーションで宣言
        - BEAR.Sundayとか使えばPHPでもAOPができる
        - [https://bearsunday.github.io/manuals/1.0/ja/](https://bearsunday.github.io/manuals/1.0/ja/)
    - ユニットオブワークを使うパターン
        - トランザクションの処理だけをInterfaceに切り出す
        - [ボトムアップドメイン駆動設計 後編 │ nrslib](https://nrslib.com/bottomup-ddd-2/#outline__3_5)

### NoSqlとかあまり使ったことがないけど、永続指向のリポジトリを利用するメリットって何かあるの？

[p3](https://codezine.jp/article/detail/11048?p=3)

- DDD的なメリットではなく、パフォーマンス上でのメリットがある
- 一般的なRDBはスケールしづらいが、NoSQLはスケールがしやすいのでパフォーマンス重視する複雑なことはあんまりしないものとかでは重宝する
    - スケールアップ
        - CPUやメモリなどのスペックをあげる
    - スケールアウト
        - サーバーを増やして性能を高める
    - スケールダウン
        - CPUやメモリなどのスペックを下げて最適化を行う
    - スケールイン
        - サーバーを減らしてリソースの最適化を行う
    - 参考
        - [スケールアウトとは | クラウド・データセンター用語集／IDCフロンティア](https://www.idcf.jp/words/scale-out.html)
        - [スケールインとは | クラウド・データセンター用語集／IDCフロンティア](https://www.idcf.jp/words/scale-in.html)
    - NoSQLはスケールアウトできるけど、MySqlはできない
        - オーロラとかはよしなにやってくれると思う
        - [Amazon Aurora MySQL の特徴 | MySQL PostgreSQL リレーショナルデータベース | アマゾン ウェブ サービス](https://aws.amazon.com/jp/rds/aurora/mysql-features/)
- キーバリューストアなので、キーが被らなければ問題ない
    - エンティティの一意のIDを使用すればNoSqlでも一意に扱える

### DAOがよくわかってない。名前の通りだとデータをアクセスするためのオブジェクトだけど、どういう時にどんなふうに使用されるのか知らない。

- SQLの代わりみたいなもの
- だいたいDDDじゃないほうのリポジトリみたいなもの
- MVCフレームワークのモデルみたいのもの
    - モデルは、そのクラスにまつわるその他の処理も書かれていたりする
        - MVCフレームワークでDDDで実装しようとすると、モデルをDAOとして扱うような実装をすることが多い
    - getUserとかgetUserListとか持ってるようなもの
- EloquentみたいなモデルはORマッパーなので、データアクセス+マッピングもしてくれるイメージ
- リポジトリの中でDBにアクセスするために使用するオブジェクト
- DAO以外の場所にDBにアクセスする処理は書かない
- [p1](https://codezine.jp/article/detail/11048) `リポジトリとDAOの違い` にも軽く書いてある

### コレクション指向と永続指向の違い・使い道がよくわかっていない。そもそもNoSQL自体の理解もあまりない。

> ![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/364773/46a933ab-af9d-bf64-5dce-a1843c222e40.png)

- 基本的にはコレクション指向で考えて、パフォーマンス重視だと永続化指向
- 集約とリポジトリが1対1になるようなことをコレクション指向と読んでいて、複数の集約（階層構造の集約）が単一のリポジトリを使用することがある場合は、ドキュメントとして追加できる永続指向の方が相性がいいのではないか。
    - 店舗集約・スタッフ集約のように集約は分けているけど、1つのリポジトリを使用するパターンみたいな
- IDDD本では変更の検知ができるかできないかによってコレクション指向か、永続化指向かを使い分けているようなことが書いてある
    - 変更検知ってなんだ？
    - O/Rマッパーの変更検知の話っぽい？
    - 昔はトランザクションが貼れなかったからその話も関係あるのかも
    - よくわからん
- ユーザーと記事の1対nの関係があったとして、NoSQLは記事をユーザーのリストとして扱うことができないのではないか。
    - RDBではユーザーのリストで持つことができるが、NoSQLはユーザーのリストとして扱うことができないので、コレクションの機能などが使えないのではないか。



### 例えばユーザーを削除するとき、ユーザーが投稿した記事もすべて削除するといった場合は、アプリケーションサービス層で記事のリポジトリを呼び出して削除した方が良いか？もしくはユーザーのリポジトリ内で記事のデータの削除も行って良いのか？

- カスケードで消してしまえ！！
- 大きい集約にするか、小さい集約で消すか、って話で出ていた気がする
    - [第10章「集約」](https://qiita.com/tkek321/items/248a4203c40b96fcfa84#%E9%9B%86%E7%B4%84%E3%81%AF%E6%A5%B5%E5%8A%9B%E5%80%A4%E3%82%AA%E3%83%96%E3%82%B8%E3%82%A7%E3%82%AF%E3%83%88%E3%81%8B%E3%82%89%E6%A7%8B%E6%88%90%E3%81%99%E3%82%8B%E3%81%A8%E3%81%82%E3%82%8B%E3%81%8C%E3%81%9D%E3%82%8C%E3%81%AF%E3%81%AA%E3%82%93%E3%81%A7%E5%80%A4%E3%82%AA%E3%83%96%E3%82%B8%E3%82%A7%E3%82%AF%E3%83%88%E3%81%A0%E3%81%91%E3%81%AB%E3%81%97%E3%81%9F%E3%81%BB%E3%81%86%E3%81%8C%E9%9B%86%E7%B4%84%E3%81%AF%E5%B0%8F%E3%81%95%E3%81%8F%E3%81%AA%E3%82%8B%E6%B0%97%E3%81%AF%E3%81%99%E3%82%8B%E3%81%91%E3%81%A9%E4%BB%96%E3%81%AB%E3%81%AF%E7%90%86%E7%94%B1%E3%81%8C%E3%81%82%E3%82%8B%E3%81%AE)
    - その時の話では、ドメインサービスで集約を更新すると言う話になった
- 別集約の場合、リポジトリで削除するのはやめた方がいい
    - 集約の中で別の集約のリポジトリを呼んで削除するのはやめたほうがいい
    - 操作していないはずの集約も消えてしまうから
- [DDDで複数集約間の整合性を確保する方法(サンプルコードあり)[ドメイン駆動設計] - little hands' lab](https://little-hands.hatenablog.com/entry/2021/03/08/aggregation)
    - 複数方法がある
    - ユースケースで複数集約を更新する
        - UseCaseで削除する場合、集約間の整合性をUseCaseがとることになってしまう
    - ドメインサービスを使用する
        - 前回の勉強会で話した内容
        - hiroさんはドメインサービスでやってる
    - ドメインイベントを使用する
- [「DDDで複数集約間の整合性を確保する方法」に対する考察 - かとじゅんの技術日誌](https://blog.j5ik2o.me/entry/2021/03/09/231332)
    - トランザクションの単位を分割した方がいい
    - トランザクションは別（結果整合性）だけどUseCaseに書いている
    - 集約の分け方の話

## 調べた単語

### トランザクションスクリプト
- 手続き型のスクリプト
- UseCaseみたいな

### テーブルデータゲートウェイ
- DAOみたいなもの

### アクティブレコード
- アクティブレコードパターン
- MVCのモデルは大体アクティブレコードパターン


## 次回
[【ミライトデザイン社内勉強会#22】「IDDD本から理解するドメイン駆動設計」輪読会~第13章「分散システム設計」~ - Qiita](https://qiita.com/tkek321/items/ecaaf790124e0b0213bf)