Foundation
リファレンス

バックエンド実装規約

各層のクラス定義・命名・配置の規約を定める

各層の設計意図は アーキテクチャ に従う。このページは、その設計を実装へ落とすときの具体的な規約を層ごとにまとめる。

Domain 層

エンティティ

  • クラスで定義する。
  • constructor は private にし、生成経路を create() / reconstruct() に限定する。
  • create() は新規作成用とし、初期値の設定などのビジネスルールを強制する。idcreatedAt は UseCase から渡す。
  • reconstruct() はデータベースからの復元用とし、全フィールドをそのまま受け取る。
  • フィールドは readonly で公開する。
  • constructor 内で Valibot スキーマによるランタイム検証をする。
  • update() メソッドは新しいインスタンスを返す(不変パターン)。

ID

  • domain/id.tsgenerateId()(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.tsXxxDto 型と 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実装

関連項目

On this page