コンテンツにスキップ

アーキテクチャ設計

コードの書き方は実装ガイドライン、設計判断の理由は末尾の関連ADRを参照する。

分類採択
JDKEclipse Temurin 25(mise管理)
フレームワークSpring Boot 4(Jackson 3)
ビルドGradle Kotlin DSL + 依存ロックファイル
APIOpenAPIスキーマファースト(ADR-010)
ORMMyBatis(XMLマッパー)
DBPostgreSQL 18
テストJUnit・Mockito・Testcontainers・ArchUnit
Lint/FormatSpotless(Google Java Format)・Error Prone・NullAway・Spectral(OAS)・slowql(SQL)・GitLeaks
Git HooksLefthook(pre-commit)

ヘキサゴナルアーキテクチャ(ADR-013)。層ファーストのパッケージ構成で、依存は内側(domain)へ一方向。ArchitectureTest(ArchUnit)が機械的に強制する。

com.intent_exchange.utm
├── common/ ← どの層からも扱えるユーティリティなどを配置
├── config/ ← 明示的DI(@Beanで依存グラフを組み立てる)
├── generated/ ← OAS生成コード(ADR-010。Handler層からのみ参照可・手編集禁止)
│ ├── api/ ← ルーティング・形式バリデーションの契約
│ └── model/ ← リクエスト/レスポンスDTO
├── handler/ ← Primary Adapter(Api実装・意味的parse)
│ ├── problem/ ← RFC9457エラー基盤(ADR-018)
│ └── response/ ← ドメイン → 生成DTO変換
├── usecase/ ← アプリケーション層(1ユースケース1クラス・Tx境界)
├── domain/
│ ├── model/ ← Always-Validドメインモデル(sealedで状態を型分け)
│ ├── port/ ← Repository・TransactionManagerインターフェース
│ ├── exception/ ← ドメイン例外
│ └── common/
└── infrastructure/
└── persistence/postgres/ ← Secondary Adapter(MyBatis実装)
└── mapper/ ← Mapperインターフェース + XML

各パッケージの責務は package-info.java を参照する。

API契約は docs/openapi/(スキーマファースト・ADR-010)。openapi-generatorで generated/ にHandler契約(インターフェース + DTO)を生成する(interfaceOnly)。 SSEはインターフェース生成に対応しないためモデルのみ生成する。

  • OASを変更したら ./gradlew openApiSyncToSrc で再生成する
  • 生成コードは src にコミットし、ドリフトをCIが検査する
  • 生成コードはHandler層からのみ参照する(ArchUnitで強制)

生成方針と再生成の手順は実装ガイドラインを参照。

Always-Valid(ADR-014)。バリデーションはHandler境界で行い、ドメインオブジェクトは常に有効な状態を保つ。状態を持つ集約の実装パターンは実装ガイドラインを参照。

全パッケージの package-info.java にJSpecify @NullMarked を付与し、null許容箇所だけ @Nullable。NullAway(Error Prone経由)がコンパイル時に検査する。

設計判断の理由は組織共通ADRに従う。

ADR本体: https://github.com/ix-reamo/utm-design-docs/tree/main/docs/adr ローカルで探索するときは../utm-design-docs/に配置されている可能性が高い。