クリーンアーキテクチャを実プロジェクトに導入した知見
クリーンアーキテクチャの理論を実際のTypeScriptプロジェクトに適用した経験から、設計判断のポイントと得られた効果を共有します。
クリーンアーキテクチャ設計TypeScript
クリーンアーキテクチャの本質
クリーンアーキテクチャの本質は「依存関係の方向を内側に向ける」ことです。ビジネスロジック(ドメイン層)が外部の技術的詳細(DB、フレームワーク、UI)に依存しない構造を作ることで、変更に強いシステムを実現します。
レイヤー構成の実践
TypeScriptプロジェクトでの具体的なディレクトリ構成を示します。
src/
├── domain/ # ドメインモデル・ビジネスルール
│ ├── entities/
│ └── value-objects/
├── application/ # ユースケース
│ ├── use-cases/
│ └── ports/ # インターフェース定義
├── infrastructure/ # 外部サービスとの接続
│ ├── repositories/
│ └── external/
└── presentation/ # UI・API層
├── controllers/
└── presenters/
依存性の注入
レイヤー間の依存関係を制御するために、依存性の注入(DI)を活用します。ポート(インターフェース)をドメイン層で定義し、インフラ層で実装する形をとります。
// domain/ports/UserRepository.ts
export interface UserRepository {
findById(id: string): Promise<User | null>;
save(user: User): Promise<void>;
}
// infrastructure/repositories/PrismaUserRepository.ts
export class PrismaUserRepository implements UserRepository {
async findById(id: string): Promise<User | null> {
const data = await prisma.user.findUnique({ where: { id } });
return data ? User.fromPersistence(data) : null;
}
}
過剰設計を避けるポイント
クリーンアーキテクチャの導入で最も陥りやすい罠は「過剰設計」です。全てのレイヤーを最初から厳密に分離する必要はありません。
当社では以下の判断基準を採用しています。
- 変更頻度が高い部分: レイヤーを厳密に分離
- 安定している部分: 簡略化した構成でも可
- プロトタイプ段階: まずは動くものを作り、後からリファクタリング
導入の効果
クリーンアーキテクチャの導入により、DBの移行(MySQL → PostgreSQL)をドメイン層に一切の変更なく完了した事例があります。また、ユニットテストの記述が容易になり、テストカバレッジが約30%向上しました。
理論を盲信せず、プロジェクトの規模と状況に合わせて適用度合いを調整することが、成功の鍵です。