QUIZ 30分

クイズの説明

Month 4「境界を守るアーキテクチャを設計しよう」の総合理解度をチェックする卒業クイズです。

  • 全8問
  • 合格ライン: 80%(7問正解)
  • 不合格の場合は各Stepの関連セクションを復習してください

問題

Q1. ヘキサゴナルアーキテクチャ、クリーンアーキテクチャ、オニオンアーキテクチャに共通する最も重要な原則はどれですか?

  • A) すべてのコードをクラスとして書くこと
  • B) データベースにはRDBMSを使うこと
  • C) 依存は常に外側から内側(ドメイン)に向かうこと
  • D) マイクロサービスとして分割すること
答えを見る

正解: C

3つのアーキテクチャパターンに共通する最も重要な原則は「依存は常に外側から内側に向かう」ことです。ドメイン(ビジネスルール)が最も内側に位置し、最も安定しています。インフラストラクチャ(DB、API、フレームワーク)は最も外側にあり、ドメインに依存します。内側は外側について何も知りません。


Q2. 以下のディレクトリ構造から、このアーキテクチャに違反している可能性が高いファイルはどれですか?

src/
├── domain/
│   ├── entities/Order.ts
│   ├── value-objects/Money.ts
│   └── ports/out/OrderRepository.ts
├── application/
│   └── CreateOrderUseCase.ts
└── adapters/
    └── out/PrismaOrderRepository.ts

Order.tsの中身:

import { PrismaClient } from '@prisma/client';  // (1)
import { Money } from '../value-objects/Money';   // (2)

class Order {
  constructor(private prisma: PrismaClient) {}    // (3)
  // ...
}
  • A) (1)のみ
  • B) (1)と(3)
  • C) (2)のみ
  • D) 違反はない
答えを見る

正解: B

(1) domain層のEntityが@prisma/client(フレームワーク)をimportしており、依存性ルールに違反しています。(2) 同じdomain層内のValue Objectへの依存は問題ありません。(3) PrismaClientをコンストラクタで受け取っており、ドメインモデルがインフラに依存しています。domain層は外部ライブラリやフレームワークに一切依存してはいけません。


Q3. DDDのBounded Contextを特定するための最も適切なアプローチはどれですか?

  • A) データベースのテーブル数でコンテキストを決める
  • B) イベントストーミングでドメインイベントを洗い出し、ユビキタス言語の境界を見つける
  • C) チームメンバーの人数でコンテキスト数を決める
  • D) フレームワークのモジュール機能に合わせてコンテキストを決める
答えを見る

正解: B

Bounded Contextはドメインの言語の境界で決まります。イベントストーミングでドメインイベントを洗い出し、同じ言葉が異なる意味を持つ箇所(例: 「商品」がカタログでは表示情報、在庫では物理的な数量)を見つけることで、自然な境界が特定できます。技術的な都合(DB、チーム人数、フレームワーク)ではなく、ビジネスの言語が基準です。


Q4. 以下の状況で最も適切なアーキテクチャ選択はどれですか?

状況:
- チーム6名
- ドメインが複雑(注文、決済、在庫、配送)
- 初回リリースまで4ヶ月
- 将来的にサービス分割を検討中
  • A) マイクロサービス + 各サービス独立DB
  • B) モジュラーモノリス + ヘキサゴナル + DDD
  • C) レイヤードアーキテクチャ(フレームワーク標準)
  • D) サーバーレスアーキテクチャ
答えを見る

正解: B

6名のチームでドメインが複雑、かつ将来のサービス分割を検討中という状況では、モジュラーモノリスが最適です。BCの境界を明確にしつつ、マイクロサービスの運用複雑さを避けられます。ヘキサゴナルでテスト容易性を確保し、DDDで複雑なドメインを整理できます。将来必要になった時にモジュール単位でサービスを切り出せます。


Q5. Aggregate設計において、以下のどの実装が正しいですか?

// 選択肢A
class Order {
  items: OrderItem[]; // public
}
order.items.push(new OrderItem(...));

// 選択肢B
class Order {
  private items: OrderItem[];
  addItem(productId: string, qty: number, price: Money): void {
    if (this.status !== 'PENDING') throw new Error('変更不可');
    if (this.items.length >= 20) throw new Error('上限超過');
    this.items.push(OrderItem.create(productId, qty, price));
  }
}

// 選択肢C
class OrderItemRepository {
  async addToOrder(orderId: string, item: OrderItem): Promise<void> {
    await prisma.orderItem.create({ data: { orderId, ...item } });
  }
}

// 選択肢D
class OrderService {
  async addItem(orderId: string, item: OrderItem): Promise<void> {
    const order = await this.repo.findById(orderId);
    order.items.push(item);
    await this.repo.save(order);
  }
}
  • A) 選択肢A
  • B) 選択肢B
  • C) 選択肢C
  • D) 選択肢D
答えを見る

正解: B

選択肢Bは正しいAggregate設計です。(A) itemsがpublicで外部から直接操作でき、不変条件が保護されません。(B) Aggregate Root(Order)のメソッド経由でのみ操作でき、ビジネスルール(ステータスチェック、上限チェック)が保護されています。(C) OrderItemに独立したRepositoryを設けるのはAggregate設計に違反します。(D) Service内でitemsを直接pushしており、ビジネスルールのバリデーションがありません。


Q6. Composition Rootの配置場所として最も適切なのはどこですか?

  • A) domain層のEntity内
  • B) アプリケーションのエントリーポイント(main.ts)付近
  • C) 各Use Caseクラス内
  • D) テストファイル内
答えを見る

正解: B

Composition Root(依存関係の組み立て場所)はアプリケーションのエントリーポイント付近に配置します。main.tsやcomposition-root.tsで、全てのPort(インターフェース)にAdapter(実装)を注入します。本番用とテスト用のComposition Rootを用意することで、環境に応じて異なるAdapterを注入できます。domain層やUse Case内に配置すると、依存性ルールに違反します。


Q7. アーキテクチャフィットネス関数をCI/CDに統合する主な目的はどれですか?

  • A) ビルド時間を短縮するため
  • B) アーキテクチャの品質劣化をコミットごとに早期検出するため
  • C) デプロイを自動化するため
  • D) コードレビューを不要にするため
答えを見る

正解: B

フィットネス関数をCI/CDに統合する目的は、アーキテクチャの品質(依存性ルール、循環依存、モジュール境界など)がコミットごとに維持されているかを自動検証することです。時間の経過とともにアーキテクチャは劣化しがちですが、フィットネス関数による自動チェックで違反を早期に検出し、修正できます。


Q8. Anti-Corruption Layer(ACL)を使うべき状況として最も適切なものはどれですか?

  • A) 自チームが管理するデータベースに接続するとき
  • B) 外部の決済APIなど、モデルや命名規則が自ドメインと異なるサービスと連携するとき
  • C) 同じチーム内の別モジュールと連携するとき
  • D) ログを出力するとき
答えを見る

正解: B

Anti-Corruption Layer(腐敗防止層)は、外部システムのモデル(命名規則、データ形式、API仕様)が自分のドメインモデルを汚染しないように変換層を設ける際に使います。外部決済APIがrecipient, parcelsという名前を使っていても、ACLを通じて自ドメインのShippingAddress, OrderItemに変換します。自チーム管理のDBや同一チーム内のモジュールにはACLは不要です。


結果

7問以上正解の場合

合格です。おめでとうございます。

Month 4「境界を守るアーキテクチャを設計しよう」の全Stepを修了しました。

あなたは以下のスキルを身につけました:

  • ヘキサゴナルアーキテクチャ(Ports & Adapters)の設計と実装
  • クリーンアーキテクチャの4層構造と依存性ルール
  • DDDの戦略的設計(Bounded Context、ユビキタス言語)
  • DDDの戦術的設計(Entity、Value Object、Aggregate)
  • アーキテクチャの品質特性とフィットネス関数
  • トレードオフの判断とADRによる記録

高橋アーキテクトからのメッセージ:

「おめでとう。“動くコード”から”美しい構造のコード”へ、そして”境界を守るアーキテクチャ”へ。きみはもう、システム全体を見渡して設計できるエンジニアだ。

ただし、覚えておいてほしい。アーキテクチャに正解はない。あるのはトレードオフだけだ。コンテキストを理解し、意識的に選択し、記録すること。それがアーキテクトの仕事だ」

6問以下の場合

もう少し復習しましょう。

問題復習セクション
Q1Step 1: step1_4 アーキテクチャパターンの全体像
Q2Step 2: step2_2 ドメインモデルの隔離
Q3Step 4: step4_1 DDDの戦略的設計
Q4Step 5: step5_3 モジュラーモノリス / step5_4 トレードオフ
Q5Step 4: step4_2 DDDの戦術的設計
Q6Step 3: step3_3 依存性注入(DI)の実践
Q7Step 5: step5_2 フィットネス関数
Q8Step 4: step4_4 コンテキストマップとチーム境界

Month 4 完了

お疲れさまでした。

学んだこと(全体まとめ)

Stepテーマ主要スキル
1アーキテクチャ思考関心の分離、依存性の方向、ADR
2ヘキサゴナルPort、Adapter、ドメイン隔離
3クリーン4層構造、Use Case、DI、テスタビリティ
4DDDBC、ユビキタス言語、Aggregate、ドメインイベント
5実践と評価品質特性、フィットネス関数、モジュラーモノリス
6最終試験総合的なアーキテクチャ設計

次のMonth

Month 5以降は、今月学んだアーキテクチャの知識を活かして、より実践的なシステム設計に取り組んでいきます。


推定所要時間: 30分