オニオンアーキテクチャ
ドメインロジックを中心に据え、外側の層が内側に依存する同心円状のアーキテクチャ
アーキテクチャDDD
オニオンアーキテクチャとは
オニオンアーキテクチャ (Onion Architecture) は、Jeffrey Palermo が 2008 年に提唱したアーキテクチャで、ドメインロジックを中心に据え、外側の層が内側の層に依存する同心円状の構造である。クリーンアーキテクチャやヘキサゴナルアーキテクチャと同じ思想。
層構造
┌─────────────────────────────────┐
│ Infrastructure (外側) │
│ ┌─────────────────────────┐ │
│ │ Application Services │ │
│ │ ┌─────────────────┐ │ │
│ │ │ Domain Services │ │ │
│ │ │ ┌───────────┐ │ │ │
│ │ │ │ Domain │ │ │ │
│ │ │ │ Model │ │ │ │
│ │ │ └───────────┘ │ │ │
│ │ └─────────────────┘ │ │
│ └─────────────────────────┘ │
└─────────────────────────────────┘
| 層 | 責務 | 例 |
|---|---|---|
| Domain Model | エンティティ、値オブジェクト | User, Order, Money |
| Domain Services | ドメインロジック | OrderService |
| Application Services | ユースケースの調整 | CreateOrderUseCase |
| Infrastructure | 外部依存 | DynamoDB, API, メール送信 |
依存の方向
Infrastructure → Application → Domain ← (依存の方向は内側へ)
内側の層は外側の層を知らない。Domain Model は DynamoDB の存在を知らず、インターフェースを通じてデータにアクセスする。
TypeScript での実装
// Domain Model (最内層)
class Order {
constructor(readonly id: string, private items: OrderItem[], private status: OrderStatus) {}
get total() { return this.items.reduce((s, i) => s + i.price, 0); }
cancel() { if (this.status !== 'pending') throw new Error('Cannot cancel'); this.status = 'cancelled'; }
}
// Domain Service: リポジトリのインターフェース (内側で定義)
interface OrderRepository {
findById(id: string): Promise<Order | null>;
save(order: Order): Promise<void>;
}
// Application Service: ユースケース
class CancelOrderUseCase {
constructor(private orderRepo: OrderRepository) {}
async execute(orderId: string) {
const order = await this.orderRepo.findById(orderId);
if (!order) throw new Error('Order not found');
order.cancel();
await this.orderRepo.save(order);
}
}
// Infrastructure (最外層): DynamoDB 実装
class DynamoDBOrderRepository implements OrderRepository {
async findById(id: string) { /* DynamoDB から取得 */ }
async save(order: Order) { /* DynamoDB に保存 */ }
}
クリーンアーキテクチャとの違い
実質的に同じ思想。クリーンアーキテクチャ (Robert C. Martin) はオニオンアーキテクチャを一般化したもの。
Lambda での現実的な判断
| ケース | 推奨 |
|---|---|
| 複雑なドメインロジック | オニオンアーキテクチャ |
| 単純な CRUD | 不要 (直接 DynamoDB を呼ぶ) |
理論と実装の両面から学ぶなら関連書籍が参考になる。