QUIZ 30分

クイズの説明

Step 2で学んだヘキサゴナルアーキテクチャの理解度をチェックします。

  • 全8問
  • 合格ライン: 80%(7問正解)
  • 不合格の場合は復習してから再挑戦してください

問題

Q1. ヘキサゴナルアーキテクチャにおけるDriving Port(入力ポート)の役割はどれですか?

  • A) データベースに接続する方法を定義する
  • B) アプリケーションが提供する機能(Use Case)を定義する
  • C) HTTPレスポンスのフォーマットを定義する
  • D) 外部APIの認証方法を定義する
答えを見る

正解: B

Driving Port(入力ポート)は、アプリケーションが外部に提供する機能を定義するインターフェースです。具体的にはUse Case単位でインターフェースを切り、CreateOrderUseCase、CancelOrderUseCaseのように、アプリケーションが「何ができるか」を表現します。


Q2. 以下のコードの問題点はどれですか?

// domain/entities/Order.ts
import { Column, Entity, PrimaryColumn } from 'typeorm';

@Entity()
class Order {
  @PrimaryColumn()
  id: string;

  @Column()
  status: string;
}
  • A) クラス名がPascalCaseでない
  • B) ドメインモデルがORMフレームワークに依存している
  • C) プロパティがprivateでない
  • D) コンストラクタが定義されていない
答えを見る

正解: B

ドメインモデルは外部ライブラリやフレームワークに依存してはいけません。TypeORMの@Entity()@Column()デコレータがドメインモデルに侵入しているため、テスト時にTypeORMの接続が必要になり、ドメインの隔離が破れています。ドメインモデルは純粋なTypeScriptクラスとして実装すべきです。


Q3. Driven Portを設計する際の原則として正しいものはどれですか?

  • A) 特定のデータベースのクエリ構文で定義する
  • B) ドメインの言葉を使い、技術的詳細を含めない
  • C) StripeGateway、PrismaRepositoryのように実装技術名を含める
  • D) 可能な限り多くのメソッドを1つのPortにまとめる
答えを見る

正解: B

Driven Portはドメインの言葉でインターフェースを定義します。OrderRepository.findById()PaymentGateway.charge()のように、ビジネスの概念で命名します。特定の技術名(Stripe、Prisma等)はAdapter側の実装の話であり、Portには含めません。


Q4. Driving Adapter(例: HTTPコントローラー)の責任として適切なのはどれですか?

  • A) ビジネスルールのバリデーションを行う
  • B) データベースに直接アクセスする
  • C) HTTPリクエスト/レスポンスとCommand/DTOの変換を行う
  • D) ドメインイベントを発行する
答えを見る

正解: C

Driving Adapterの責任は「変換」です。外部の入力(HTTPリクエスト)をUse Caseが理解できる形式(Command)に変換し、Use Caseの結果をHTTPレスポンスに変換します。ビジネスルールのバリデーションはドメインモデル、データベースアクセスはDriven Adapterの責任です。


Q5. テスト用のInMemoryRepositoryを使う主な利点はどれですか?

  • A) 本番環境で高速にデータを保存できる
  • B) データベース接続なしでUse Caseのテストが実行できる
  • C) SQLのパフォーマンスチューニングが不要になる
  • D) データの永続化が自動的に行われる
答えを見る

正解: B

InMemoryRepositoryはDriven Port(OrderRepository等)のインメモリ実装です。Map等のデータ構造を使ってメモリ上にデータを保持するため、データベース接続が不要です。これにより、Use Caseのテストが高速に実行でき、外部依存なしにビジネスロジックを検証できます。


Q6. 以下のディレクトリ構造で、依存関係として正しい記述はどれですか?

src/
├── domain/
│   ├── entities/Order.ts
│   └── ports/out/OrderRepository.ts (interface)
├── application/
│   └── CreateOrderUseCaseImpl.ts
└── adapters/
    └── out/PrismaOrderRepository.ts (implements OrderRepository)
  • A) domain → adapters
  • B) application → adapters
  • C) adapters → domain
  • D) domain → application
答えを見る

正解: C

adapters層のPrismaOrderRepositoryは、domain層のOrderRepositoryインターフェースを実装(implements)しています。つまりadaptersがdomainに依存しています。applicationもdomainのPortに依存します。domainは最も内側の層であり、外側の層に一切依存しません。


Q7. 以下のコードで、ヘキサゴナルアーキテクチャの原則に違反している箇所はどこですか?

class CreateOrderUseCaseImpl implements CreateOrderUseCase {
  constructor(
    private orderRepo: PrismaOrderRepository,  // (1)
    private stripe: Stripe                       // (2)
  ) {}

  async execute(command: CreateOrderCommand): Promise<OrderId> {
    const order = Order.create(command.customerId, command.items);
    await this.orderRepo.save(order);
    await this.stripe.paymentIntents.create({    // (3)
      amount: order.totalAmount.toCents(),
    });
    return order.id;
  }
}
  • A) (1)のみ
  • B) (1)と(2)
  • C) (1)と(2)と(3)
  • D) (3)のみ
答えを見る

正解: C

(1) Use CaseがPrismaOrderRepository(具象クラス)に依存しており、OrderRepository(インターフェース)に依存すべきです。(2) Stripe(外部ライブラリの具象クラス)に直接依存しており、PaymentGateway(Port)に依存すべきです。(3) Stripeの具体的なAPIを直接呼び出しており、PaymentGatewayのメソッドを通じて呼び出すべきです。全箇所が原則に違反しています。


Q8. Value Objectの設計原則として正しいものはどれですか?

  • A) 可変(mutable)で、自由に値を変更できる
  • B) 不変(immutable)で、自己検証を行い、等値比較で比較する
  • C) 必ずデータベースのIDを持つ
  • D) 外部APIの型定義をそのまま使う
答えを見る

正解: B

Value Object(値オブジェクト)は不変であり、コンストラクタまたはファクトリメソッドで自己検証を行います。同一性はIDではなく値で比較します(例: Money(100, ‘JPY’) === Money(100, ‘JPY’))。外部ライブラリの型に依存せず、ドメインの概念を純粋に表現します。


結果

7問以上正解の場合

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

Step 2「ヘキサゴナルアーキテクチャ」を完了しました。 次は Step 3「クリーンアーキテクチャ」に進みましょう。

6問以下の場合

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

問題復習セクション
Q1step2_1 Ports & Adaptersの概念
Q2step2_2 ドメインモデルの隔離
Q3step2_3 Port(インターフェース)の設計
Q4step2_4 Adapter(実装)の設計
Q5step2_4 テスト用Adapter
Q6step2_1 / step2_4 依存の方向
Q7step2_1 / step2_3 PortとAdapterの関係
Q8step2_2 Value Object

Step 2 完了

お疲れさまでした。

学んだこと

  • Ports & Adaptersの概念(Driving/Driven)
  • ドメインモデルの隔離(外部依存の排除)
  • Portの設計(1 Use Case = 1 Port、ドメインの言葉)
  • Adapterの設計(変換のみ、テスト用InMemory)

次のステップ

Step 3: クリーンアーキテクチャ(3時間)

ヘキサゴナルの考え方をさらに発展させた、クリーンアーキテクチャの4層構造を学びます。


推定所要時間: 30分