オニオンアーキテクチャ
ドメインロジックを中心に据え、外側の層が内側に依存する同心円状のアーキテクチャ
オニオンアーキテクチャとは
オニオンアーキテクチャ (Onion Architecture) は、Jeffrey Palermo が 2008 年に提唱したアーキテクチャで、ドメインロジックを中心に据え、外側の層が内側の層に依存する同心円状の構造である。クリーンアーキテクチャやヘキサゴナルアーキテクチャと同じ思想。
層構造
オニオンアーキテクチャは同心円状の層で構成される。最も内側にドメインモデル (エンティティ、値オブジェクト) を配置し、その外側にドメインサービス、アプリケーションサービス、最外層にインフラストラクチャ (DB、外部 API) を置く。依存の方向は常に外側から内側に向かい、内側の層は外側の層を知らない。
┌─────────────────────────────────┐
│ 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 での実装
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 での現実的な判断
Lambda での現実的な判断を以下にまとめる。
| ケース | 推奨 |
|---|---|
| 複雑なドメインロジック | オニオンアーキテクチャ |
| 単純な CRUD | 不要 (直接 DynamoDB を呼ぶ) |
理論と実装の両面から学ぶなら関連書籍が参考になる。
この記事は役に立ちましたか?
関連用語
クリーンアーキテクチャ
ビジネスロジックを外部の技術的詳細から分離し、依存関係を内側に向けることで変更に強い設計を実現するアーキテクチャ原則
ポートとアダプター
アプリケーションのコアロジックを外部技術から分離し、ポート (インターフェース) とアダプター (実装) で接続するアーキテクチャ
依存性逆転の原則
SOLID の D - 上位モジュールは下位モジュールに依存せず、両者とも抽象に依存すべきという設計原則
C4 Model
ソフトウェアアーキテクチャを 4 つの抽象レベルで図示するモデル
ヘキサゴナルアーキテクチャ
ポートとアダプターでビジネスロジックを外部依存から分離する設計パターン
YAGNI
You Aren't Gonna Need It - 今必要でない機能を先回りして実装しない原則