---
# System prepended metadata

title: 2021/09/26 メンター相談
tags: [9月, メンター相談]

---

# 2021/09/26 メンター相談

###### tags: `メンター相談`,`9月`

## DDDのプロジェクトにおいて、AggregateRootやValueObject, Entityなどの基底クラスを用いていますか？利用している/していない場合の理由が気になります。また、もし利用している場合、基底クラスの形式は何か参考にしたりしていますか？

- 作っている
    - valueObjectを作る
        - TypeScriptだとprivate propertyを用いることで、固有の型を定義出来る
    - valueObjectいがいを作らない理由
        - プロパティ(field)を作り間違えないことが多いから
        - JsonStringifyやpropertyと同じだったら同じものというルールがあるが、もしもvaluobject同士を==で比較すると本当は同じだが、別のものとして扱われてしまう
    - Entityでやらない理由
        - entityはIDさえ一致していれば同じものという扱いにするから
- ドメインイベントを採用するアーキテクチャにするのであれば、[ddd-forum](https://github.com/stemmlerjs/ddd-forum/blob/386d9281ff37874943f15444481791a585d9c94d/src/shared/domain/AggregateRoot.ts)のような実装をする

## DDDのプロジェクトにおいて、実務でドメインイベントを採用したことはありますか？
- まだない
    - ユースケースが手続き的になりがちなときに採用すると思う
    - 実装コストと学習コストがかかるので、採用しないことが多い
- 複数集約間の整合性をとるときの対応は？
    - ユースケース層でトランザクションを張る
    - typeormだと@transactionをつければいいが、prismaはそれが採用されておらず、それが致命的なデメリット
        - prismaの場合は、楽観ロックを使うように言っている
        - それができない場合、書き込みのみなら、prismaのtransactionがカバーしているのでそれを使って欲しい
        - それでもできないのであれば、prismaではカバーできない

## フロントエンドとバックエンドで、エンドポイントに関する型定義をどのように共有していますか?

- OpenAPIの型定義から自動生成するようにしている
    - 最も代表的なライブラリは、OpenAPI generator
    - 松原さんは、Aspida (初めに見つけたのがAspidaだった)


## クエリサービスが使用する DTO のマッピングをどのように記述していますか?

- 独自に記述している。なぜなら、クエリサービスのDTOは固有のことが多く使いまわせることが少ないからだ。
- Q:都度DTOを記述するのはめんどくさいからリフレクション採用する？
    - しない
    - エンジニアがDTOを記述するコストは1分程度。
    - リフレクションを採用したエンジニアがいなくなったときなどのリスクよりは、DTO記述する方が低いと思っている
- 辛いのは、補完が聞かなくなること
- ユースケースごとに個別に作る
    - 過度な共通化は怖い。そのためDTOを共有しない。
- DTOはロジックを持たずに、表示に関することは、フロントに任せるのが自然だと思う


## API で似たデータを取得する場合に、型定義を共有したりしますか?
- 共有すると実は違った時に困るので、しない
    - リファクタするときに地獄になる可能性がある
- 本当に同じなら、エンドポイントが同じでもいいと思う

## 集約とエンドポイントの配置場所に関連はありますか?
- API設計全般に関することだと思う
    - nestされたリソースがある場合、(/api/a/b) or (/api/a and /api/b) どちら？
    - エンドポイントを増やしたい場合は、ネストした形式にする(/api/a/b)
    - エンドポイントを増やしたくない場合は、クエリパラムに付与する(/pairs?team=:teamId)
    - 絞り込み条件多い場合は、クエリパラメータで表現した方がいいのではないと思う
        - ネイティブアプリを開発するとき、既存ユーザーがいるため、APIのバージョンがたくさんあるので、以前のバージョンを消していいのかどうかわからなくなるので大変だと思う
    - 今回のプラハチャレンジなら、ネストしない
    - エンドポイントを増やして、処理を単純にするのが好きな人もいるので、好みだとは思う

## リードモデルに対して、GraphQL を使用することはありますか?
- あると思うが、採用経験はない。
    - 「ユースケース毎にDTOつくるのめんどくさい問題」がバックエンドからは無くなるので、良いと思う

## エンティティや値オブジェクトを基底クラスとして使用する場合、単体テストに関して、具象クラスとどのように役割分担をしていますか?

- 基底クラスはabstractなので、単体テストを実施しない。
    - また、privateメソッドはUT実施しない。publicメソッドから呼び出したケースをテストするのみにする
    - むしろテストはできないと思う
    - エンティティによっては、例えば不正なメルアドだった場合の処理が異なると思うので、そこのテストはすると思う

## 結合テストや単体テストで Prisma を使用する場合、どのようにデータを初期化していますか

- 前提: Prismaを利用するケースは、単体テストとは呼べない。
- 回答: truncateしている
    - なぜなら、テーブルが増えたときに、deleteAllのつけ忘れが発生する可能性があるため。
- 毎回テストデータをリセットするのは、jestの各ファイルのbeforeeachなどでリセットしているのか？
    - そうです

## NestJS を使用している場合、コントローラーに対して大量のユースケースクラスが紐づくと思っていますが、これはコントローラーのコンストラクタにべた書きする方法以外に何かありますか

- DIコンテナを使わずコントローラの各メソッドの中で、usecaseを初期化している
    - コントローラがシンプルなので、テストする必要がないと思っている
    - コンストラクタにユースケースがたくさんあるのは、問題はないのではと思う

## 個人的にはusecase層の単体テストを書かずに結合テストとしてdomainやrepository(DBはtest用のものを用意する)は本物を用いたテストを行った方が費用対効果が高いように感じるのですが、prahaではどうされているのか教えていただきたいです。

- usecase層は手続的。特徴としては戻り値がないケースが多いこと。問題点は、テストが壊れやすいこと。
    - テストは内部実装のテストはしたくなく、結果をテストしたい
    - その点では、ユースケース層のテストは壊れやすいが、ユースケースが複雑なら書いた方がいい。ただ壊れる可能性が高いことは念頭に置いておくべき
    - 最重要なのは、ドメイン層のテスト
    - リポジトリ層は、どれだけシンプルかによって、テストを書くか描かないかが変わる
    - クエリサービスに複雑な生のクエリをかいているならテストする
    - 優先度としては、クエリサービスに生クエリを描いている場合。次がユースケース層のテスト
- 結合テストの場合はどこのテストを書くのか？
    - ユースケース層以降のテストを書くことが多い
    - コントローラの結合テストは優先度は高くない？
        - コントローラをテストしようとするとnestのモジュールを考えないといけない。それにコントローラはシンプルなことが多いので、ここのテストを省いても問題ないだろうと思っている。

https://airtable.com/tblA4yYGHwaqDYKwx/viwAUwNVsR9rOkW6u/recsgWtO3JngG4LGN?blocks=hide
