【ミライトデザイン社内勉強会#15】「IDDD本から理解するドメイン駆動設計」輪読会~第6章「値オブジェクト」~

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

## [実践DDD本 第6章「値オブジェクト」～振る舞いを持つ不変オブジェクト～ (1/4)：CodeZine（コードジン）](https://codezine.jp/article/detail/10184)

### 例えば、ユーザーエンティティの値オブジェクトである住所とかがRDBでは別テーブルになっているとき、値オブジェクトの実装がどうなるのか知りたい
- テーブルがこんな感じになっていて

| ユーザーテーブル | 住所テーブル |
| -------- | -------- |
| ID | ID |
| --------（なんかその他の値とか） | ユーザーID |
| --------     | 郵便番号     |
| -------- | 都道府県 |
| -------- | 市区町村 |

- クラス図ではこうなっている
    - DBでは住所テーブルがユーザーIDを持っているけど、値オブジェクトの住所はユーザーIDは持っていない。
        - 住所の値オブジェクトがユーザーIDを持っているのは違和感あるので、、
<img width="354" alt="スクリーンショット 2021-01-24 14.30.12.png (35.9 kB)" src="https://img.esa.io/uploads/production/attachments/14942/2021/01/24/76867/bf2d12a9-1b77-4a8b-a21c-fb3009d260dc.png">

- ユーザーと住所のテーブルが別れている場合、住所をDBに保存するときは、userIdが必要になる

```php
interface UserRepository
{
    public function add();
}

class DbUserRepository implements UserRepository
{
    public function add(User $user)
    {
        $dbUser = new Eloquent\User();  // 適当LaravelのModelクラスみたいなイメージ
        $dbUser->id = $user->getUserId();
        $dbUser->save();
        
        $address = $user->getAddress();
        $dbAddress = new Eloquent\Address();
        $dbAddress->郵便番号 = $address->get郵便番号();
        // ... その他の値も全部詰める
        $dbAddress->save();
        
        // 住所の値オブジェクトにはuserIdは存在していないけど、DB保存では使用する。
        // みたいなことはしてもいいの？
        $dbAddress->userId = $user->userId(); 
        $dbAddress->save();
    }
}
```

---

- テーブルで分ける必要があるのであれば、別にこれで違和感はない。
- DBはパフォーマンス都合で作って、クラスはモデリング都合で作りたいので、DBとクラスの実装が別れていても問題ない。
- 保存方法はRepositoryに任せる。
    - そもそもRDBとも限らない。保存する、取り出せることが重要なので、保存方法はなんでもいい。
    - 場合によってはtextファイルに保存しても別にいい。RDBだからモデルと結びつけて考えしまっているけど、textファイルに保存するための実装とモデルの実装が関係ないことはわかると思う。
    - Repositoryで重要なのは集約単位で扱えることなので、クラスのモデルの実装とRepositoryの実装は一緒に考える必要はない
- Repositoryに限らず、インターフェースを切ってポート（ポートアダプターのポート）になっている箇所は、外部からきた情報を内部で使いやすい形に変換する役割がある。
    - なので、モデルの実装とRepositoryの実装は分けて考えることができる


### 複数コンテキストの結合を緩めるというのはどういうことか？

- [3ページ](https://codezine.jp/article/detail/10184?p=3)

> <img width="500" alt="image.png (61.7 kB)" src="https://img.esa.io/uploads/production/attachments/14942/2021/01/28/67007/5646499e-4ba9-48e3-80e6-fcdba3f6b5ea.png">

- 別コンテキストと同じ形のEntityを使うと、取得元のコンテキストが変更になると、こちらのEntiryも書き換える必要がある場合もあるかもしれない
- ここでは 必要な情報だけをもつ値オブジェクトとして定義している

### 値オブジェクトに不変性がないテストってどんな感じに書くの？

- 4ページの最後に「コピーコンストラクタを使用して、値オブジェクトに不変性がないテストを書く」とあるが、具体的にどういうテストの内容になるの？
    - コピーコンストラクタがいまいちわかってないかも

--- 

- Unitテストで、コピーしたオブジェクトとadd（なんか金額計算とか）などした後のオリジナルのオブジェクトを比較して、値が変わってないことをテストするとか？
- コピーコンストラクタでオブジェクトを2つ用意し、副作用のないメソッドを実行し値が変わっていないことをテストする（IDDD本）
    - 値オブジェクトをテストする際に不変であることを確かめたい。
- 「値オブジェクトに不変性がないテストを書く」じゃなくて、「値オブジェクトが不変である」ことをテストする


### 値オブジェクトの特徴に等価性ってあるけど、「等価性」の判定方法を提供するようなコードって毎回実装する必要がある？
- 例えばequalsメソッドを毎回オーバーライドする必要があるの？必要になったらでいいよね？

---

- PHPとかだったら、equalsメソッドないからいいかもしれないけど、C#とかだったら最初からequalsメソッドがあるからオーバーライドしておかないといけない。
    - 使うひとが、equalsメソッド使っちゃうかもしれないし。

### phpでも列挙型を積極的に使って良し？

- phpには無いよ
- [PHPで列挙型(enum)を作る - Qiita](https://qiita.com/Hiraku/items/71e385b56dcaa37629fe)
- [PHP: 振る舞いを持つEnumの作り方 - Qiita](https://qiita.com/suin/items/17ee61d7e75b422a7ec3)
- [Laravel で Enum を使う - Qiita](https://qiita.com/nunulk/items/2366addc3aab59e6c81e)

## 次回
[【ミライトデザイン社内勉強会#16】「IDDD本から理解するドメイン駆動設計」輪読会~第7章「ドメインサービス」~ - Qiita](https://qiita.com/tkek321/items/2990c4a3533d9550b3a3)