リファレンス
バックエンド実装規約
各層のクラス定義・命名・配置の規約を定める
各層の設計意図は アーキテクチャ に従う。このページは、その設計を実装へ落とすときの具体的な規約を層ごとにまとめる。
Domain 層
エンティティ
- クラスで定義する。
- constructor は
privateにし、生成経路をcreate()/reconstruct()に限定する。 create()は新規作成用とし、初期値の設定などのビジネスルールを強制する。idとcreatedAtは UseCase から渡す。reconstruct()はデータベースからの復元用とし、全フィールドをそのまま受け取る。- フィールドは
readonlyで公開する。 - constructor 内で Valibot スキーマによるランタイム検証をする。
update()メソッドは新しいインスタンスを返す(不変パターン)。
ID
domain/id.tsのgenerateId()(nanoid)で生成する。- UUID は使わない。
Repository
interfaceとして定義する。- メソッド名は操作の意図を明確にする(
create/update/findById/findAll)。
UseCase 層
- クラスとして定義し、
execute()メソッドで実行する。 - 1クラス1操作を原則とする。
- コンストラクタで Repository インターフェースを受け取る(コンストラクタインジェクション)。
- 入力スキーマは UseCase が Valibot で定義・export する。API 層はそのスキーマを import してバリデーションに使う。
- 更新系は Load-Mutate-Save パターンで実装する。
execute()の戻り値は DTO(plain な type)で返す。Domain Entity をそのまま返さない。- DTO は
usecase/{domain}/{domain}-dto.tsにXxxDto型とtoXxxDto変換関数を定義する。
Infrastructure 層
di/container.tsで UseCase とその依存を組み立てる。- Repository 実装は
infrastructure/配下に置く。 - データベースの行からエンティティへの変換は
toDomainヘルパーでreconstruct()を使う。
API 層
- tRPC ルーターは UseCase を呼び出すだけとし、ビジネスロジックを持たない。
- ドメインエラーから
TRPCErrorへの変換はtrpc.tsの middleware が行う。 - ルーター内でエラーをキャッチしない。エラー変換は middleware に一任する。
ディレクトリ構成
server/
├── api/
│ ├── trpc.ts # tRPC初期化・ドメインエラー変換middleware
│ ├── index.ts # appRouterの定義
│ └── routers/ # 各ドメインのルーター
├── usecase/
│ └── {domain}/ # ドメインごとにディレクトリを分ける
├── domain/
│ ├── id.ts # ID生成(nanoid)
│ ├── error/ # ドメインエラー
│ └── {domain}/ # エンティティ + Repositoryインターフェース
└── infrastructure/
├── di/ # DIコンテナ
└── {impl}/ # Repository実装関連項目
- アーキテクチャ — 各層の責務と設計の理由