Skip to content

ドメインモデル設計 - 国際貨物輸送管理システム

概要

本ドキュメントは、国際貨物輸送管理システムの DDD(ドメイン駆動設計)戦術的設計を定義する。システムは以下の 6 つの境界付けられたコンテキスト(Bounded Context)で構成される。

コンテキスト 日本語名 主な責務
Booking Context 予約コンテキスト 貨物予約の受付・旅程管理・状態遷移
Routing Context 経路コンテキスト 航海スケジュール・経路情報の管理
Tracking Context 追跡コンテキスト 貨物追跡・例外イベント管理
Handling Context 荷役コンテキスト 荷役作業登録・通関申告管理
Billing Context 精算コンテキスト 請求書発行・割引・支払い管理
Shared Domain 共有ドメイン 共有カーネル(Location・TransportStatus)

各コンテキストは自律的に変更可能な集約を持ち、コンテキスト間の連携はドメインイベントおよび ACL(Anti-Corruption Layer)ポートを通じて行う。

ユビキタス言語

英語(コード名) 日本語(業務用語) 使用コンテキスト 説明
Cargo 貨物 Booking Context 予約の中心的エンティティ。荷主から荷受人へ輸送される物品
Shipper 荷主 Booking Context 貨物を発送する主体。個人・法人の 2 種別
Consignee 荷受人 Booking Context 貨物を受け取る主体。氏名・住所・連絡先を保持
BookingId 予約 ID Booking Context 予約を一意に識別する値オブジェクト
RouteSpecification ルート仕様 Booking Context 出発地・目的地・到着期限の要件定義
CargoItinerary 旅程 Booking Context 貨物の輸送経路全体。1 つ以上の Leg で構成
Leg 輸送区間 Booking Context 単一航海での積込港から荷降港までの区間
Delivery 配送状況 Booking Context 現在の輸送状態・経路状態・最終荷役イベントの集合
Voyage 航海 Routing Context 特定の船舶が実施する一連の運送区間
Schedule 航海スケジュール Routing Context 航海を構成する時系列の運送区間一覧
CarrierMovement 運送区間 Routing Context 出発港・到着港・出発時刻・到着時刻を持つ区間単位
TrackingActivity 追跡レコード Tracking Context 貨物の追跡情報全体を管理する集約
TrackingNumber 追跡番号 Tracking Context 追跡活動を一意に識別する番号
TrackingActivityEvent 追跡イベント Tracking Context 時系列で記録される追跡の出来事
TrackingExceptionEvent 追跡例外イベント Tracking Context 遅延・損傷・紛失・税関保留などの例外事象
HandlingActivity 荷役作業 Handling Context 実際に行われた荷役作業の記録
HandlingActivityHistory 荷役履歴 Handling Context クエリ専用の荷役作業履歴(Read Model)
Invoice 精算書 Billing Context 貨物輸送 1 件に対して発行される請求書
DiscountPolicy 割引方針 Billing Context 法人・ボリューム・シーズン割引のポリシー
Location 位置情報 Shared Domain UN/LOCODE で識別される港湾・地点の共有カーネル
TransportStatus 輸送状態 Shared Domain 貨物の現在の輸送フェーズを表す共有列挙型
RoutingStatus 経路状態 Shared Domain 経路の妥当性状態(NOT_ROUTED / ROUTED / MISROUTED)
BookingStatus 予約状態 Booking Context 予約ライフサイクルの状態(8 値)
CargoType 貨物種別 Booking Context GENERAL / HAZARDOUS / REFRIGERATED
ExceptionType 例外種別 Tracking Context DELAY / DAMAGE / LOST / CUSTOMS_HOLD
CustomsStatus 通関状態 Handling Context PENDING / CLEARED / HELD / REJECTED
PaymentStatus 支払い状態 Billing Context PENDING / CONFIRMED / OVERDUE / REFUNDED

アクターとコンテキストの対応

アクター 対話するコンテキスト 主要コマンド / 操作
営業担当者 Booking Context BookCargoCommandRouteCargoCommand・見積作成
経路設計者 Routing Context + Booking Context RouteCargoCommandAssignTrackingNumberCommand
荷役作業員 Handling Context HandlingActivityRegistrationCommand
追跡管理者 Tracking Context AddTrackingEventCommand・例外登録
荷主 Booking Context(読取)+ Tracking Context(読取) 追跡照会・状態確認
荷受人 Tracking Context(読取)+ Booking Context(読取) 到着確認・引取手続き
経理担当者 Billing Context GenerateInvoiceCommandConfirmPaymentCommand

境界付けられたコンテキスト概要

uml diagram

1. Booking Context(予約コンテキスト)

ドメインモデル図

uml diagram

集約・エンティティ・値オブジェクト一覧

種別 クラス名 日本語名 責務
集約ルート Cargo 貨物 予約の中心。状態遷移・旅程・配送状況を統括
値オブジェクト BookingId 予約 ID 予約の一意識別
値オブジェクト ShipperId 荷主識別子 荷主 ID と種別(個人・法人)の保持
値オブジェクト Consignee 荷受人情報 荷受人の名前・住所・連絡先メール
値オブジェクト RouteSpecification ルート仕様 出発地・目的地・到着期限の要件定義
値オブジェクト CargoItinerary 旅程 輸送区間(Leg)の集合と到着時刻計算
値オブジェクト Leg 輸送区間 単一航海での積込港から荷降港までの区間
値オブジェクト Delivery 配送状況 現在の輸送状態・経路状態・最終荷役イベント
値オブジェクト Money 金額 金額と通貨コードのペア。多通貨対応
値オブジェクト CargoHandlingActivity 荷役活動(参照用) 最終荷役イベントの記録
列挙型 BookingStatus 予約状態 8 段階の予約ライフサイクル
列挙型 ShipperType 荷主種別 INDIVIDUAL / CORPORATE
列挙型 CargoType 貨物種別 GENERAL / HAZARDOUS / REFRIGERATED
列挙型 RoutingStatus 経路状態 NOT_ROUTED / ROUTED / MISROUTED

ビジネスルール

  1. 貨物は必ず BookingId・ShipperId・CargoType を持つ
  2. RouteSpecification の出発地と目的地は異なる(UN/LOCODE 形式で検証)
  3. CargoItinerary は 1 つ以上の Leg で構成される。Leg[n].unloadLocation == Leg[n+1].loadLocation の連結制約を満たす必要がある
  4. BookingStatus の遷移は PRELIMINARY → ROUTE_PROPOSED → CONFIRMED → TRACKING_ISSUED → IN_TRANSIT → DELIVERED → SETTLED の順に進む。いずれの状態からも CANCELLED に遷移可能
  5. CORPORATE ShipperType の荷主は割引適用の対象となる
  6. HAZARDOUS / REFRIGERATED の CargoType は指定港のみ取扱可能

コマンド一覧

コマンド 実行アクター 主な処理
BookCargoCommand 営業担当者 貨物予約の新規登録(PRELIMINARY 状態で作成)
RouteCargoCommand 経路設計者 CargoItinerary を Cargo に割り当て、ROUTE_PROPOSED → CONFIRMED に遷移
AssignTrackingNumberCommand 経路設計者 TrackingNumber を Cargo に紐付け、TRACKING_ISSUED に遷移
UpdateBookingStatusCommand システム BookingStatus の状態遷移を更新

2. Routing Context(経路コンテキスト)

ドメインモデル図

uml diagram

集約・エンティティ・値オブジェクト一覧

種別 クラス名 日本語名 責務
集約ルート Voyage 航海 航路スケジュールを管理する中心エンティティ
値オブジェクト VoyageNumber 航海番号 Routing Context 固有の航海一意識別子
値オブジェクト Schedule 航海スケジュール 時系列の CarrierMovement 一覧を保持
エンティティ CarrierMovement 運送区間 出発地・到着地・出発時刻・到着時刻の区間単位
共有カーネル参照 Location 位置情報 UN/LOCODE で識別される港湾・地点

ビジネスルール

  1. 航海は必ず一意の VoyageNumber を持つ
  2. Schedule は時系列順の CarrierMovement で構成される
  3. CarrierMovement の出発地と到着地は異なる
  4. Location は UN/LOCODE で一意に識別される(例: JPOSA = 大阪、USLAX = LA)

コマンド一覧

コマンド 実行アクター 主な処理
RegisterVoyageCommand 経路設計者 新規航海スケジュールの登録
UpdateScheduleCommand 経路設計者 運送区間の追加・変更

3. Tracking Context(追跡コンテキスト)

ドメインモデル図

uml diagram

集約・エンティティ・値オブジェクト一覧

種別 クラス名 日本語名 責務
集約ルート TrackingActivity 追跡レコード 貨物の追跡情報全体を管理
エンティティ(集約内) TrackingActivityEvent 追跡イベント 時系列で記録される追跡の出来事
エンティティ(集約内) TrackingExceptionEvent 追跡例外イベント 遅延・損傷・紛失・税関保留の例外記録
値オブジェクト TrackingNumber 追跡番号 追跡活動を一意に識別
値オブジェクト TrackingBookingId 予約参照 ID Booking Context との関連を保持
値オブジェクト TrackingLocation 追跡位置情報 コンテキスト固有の位置情報型(ACL 変換)
値オブジェクト TrackingVoyageNumber 追跡航海番号 Tracking Context 固有の航海番号型
列挙型 TrackingStatus 追跡状態 9 段階の追跡フェーズ
列挙型 ExceptionType 例外種別 DELAY / DAMAGE / LOST / CUSTOMS_HOLD

ビジネスルール

  1. 追跡活動は必ず一意の TrackingNumber を持つ
  2. TrackingActivityEvent は時系列順で管理される。イベントごとに位置と時刻が必須
  3. ExceptionType が LOST の場合、escalationFlag を true に設定し上位管理者へエスカレーションする
  4. CUSTOMS_HOLD 例外は税関システム(CustomsClearancePort)からの通知によって自動登録される
  5. ResolveExceptionCommand の実行により TrackingStatus は例外発生前の状態に復帰する

コマンド一覧

コマンド 実行アクター 主な処理
AssignTrackingNumberCommand Booking Context(イベント駆動) TrackingActivity を新規作成し TrackingNumber を割り当て
AddTrackingEventCommand 追跡管理者 TrackingActivityEvent を時系列で追加
RegisterExceptionCommand 追跡管理者・税関システム TrackingExceptionEvent を登録
ResolveExceptionCommand 追跡管理者 例外を解決し TrackingStatus を復帰

4. Handling Context(荷役コンテキスト)

ドメインモデル図

uml diagram

集約・エンティティ・値オブジェクト一覧

種別 クラス名 日本語名 責務
集約ルート HandlingActivity 荷役作業 荷役作業の登録と妥当性検証
エンティティ(集約内) CustomsDeclaration 通関申告 通関申告の状態管理
値オブジェクト CargoBookingId 貨物予約識別子 Booking Context との関連識別子
値オブジェクト HandlingType 荷役種別 RECEIVE / LOAD / UNLOAD / CUSTOMS / CLAIM。VoyageNumber 必須判定を内包
値オブジェクト CargoSnapshot 貨物スナップショット ACL 経由で取得した貨物情報。妥当性検証に使用
値オブジェクト LegSnapshot 旅程区間スナップショット CargoSnapshot 内の区間情報
値オブジェクト VoyageNumber 航海番号 Handling Context 固有の航海番号型
列挙型 CustomsStatus 通関状態 PENDING / CLEARED / HELD / REJECTED
Read Model HandlingActivityHistory 荷役履歴 クエリ専用の荷役作業履歴。集約と切り離して管理

ビジネスルール

荷役妥当性検証(isValidFor)のデシジョンテーブル:

荷役タイプ VoyageNumber 必須 場所チェック MISROUTED 判定条件
RECEIVE(受領) 不要 出発港(RouteSpecification.origin)と一致 不一致で警告
LOAD(積込) 必須 Itinerary の積込港(Leg.loadLocation)と一致 不一致で MISROUTED
UNLOAD(荷降し) 必須 Itinerary の荷降港(Leg.unloadLocation)と一致 不一致で MISROUTED
CLAIM(引取) 不要 目的港(RouteSpecification.destination)と一致 不一致で警告

追加ルール:

  1. LOAD / UNLOAD 作業で MISROUTED が確定した場合、Booking Context の RoutingStatus を MISROUTED に更新する
  2. CustomsDeclaration が CLEARED 状態になるまで CLAIM(引取)は実施できない
  3. HandlingActivityHistory はクエリ専用の Read Model として管理され、集約とは切り離す

コマンド一覧

コマンド 実行アクター 主な処理
HandlingActivityRegistrationCommand 荷役作業員 荷役作業を登録し、CargoSnapshot で妥当性を検証
RegisterCustomsDeclarationCommand 荷役作業員 通関申告を新規登録(PENDING 状態で作成)
UpdateCustomsStatusCommand 税関システム(ACL) 通関申告の状態を更新(CLEARED / HELD / REJECTED)

5. Billing Context(精算コンテキスト)

ドメインモデル図

uml diagram

集約・エンティティ・値オブジェクト一覧

種別 クラス名 日本語名 責務
集約ルート Invoice 精算書 貨物輸送 1 件に対する請求書の発行・管理
値オブジェクト InvoiceId 請求書 ID 精算書の一意識別子
値オブジェクト BillingBookingId 予約参照 ID Booking Context の Cargo との関連識別子
値オブジェクト BillingShipperId 荷主参照 ID 法人判定(isCorporate)を内包
値オブジェクト Money 金額 金額と通貨コードのペア
値オブジェクト DiscountRate 割引率 0〜30% の割引率。範囲バリデーション付き
値オブジェクト DiscountPolicy 割引方針 法人・ボリューム・シーズン割引のロジック
列挙型 PaymentStatus 支払い状態 PENDING / CONFIRMED / OVERDUE / REFUNDED
列挙型 DiscountPolicyType 割引方針種別 CORPORATE_STANDARD / VOLUME_DISCOUNT / SEASONAL / NONE

ビジネスルール

  1. Invoice は貨物配送完了(BookingStatus = DELIVERED)後にのみ発行できる
  2. 法人荷主(CORPORATE)には最大 30% の割引が適用される
  3. 支払期限(issuedAt + 30 日)を超過した場合、PaymentStatus を OVERDUE に更新する
  4. 支払い確定(CONFIRMED)後のキャンセルは IssueRefundCommand で対応し、REFUNDED 状態に遷移する

料金計算ロジック:

基本料金 = 距離係数 × 重量(kg) × 貨物種別係数
  - GENERAL(一般貨物): 係数 1.0
  - HAZARDOUS(危険物): 係数 1.8
  - REFRIGERATED(冷凍・冷蔵): 係数 1.5

割引後料金 = 基本料金 × (1 - 割引率)
  - CORPORATE 荷主: 割引率 0〜30%
  - INDIVIDUAL 荷主: 割引なし(割引率 0%)

コマンド一覧

コマンド 実行アクター 主な処理
GenerateInvoiceCommand 経理担当者 請求書を新規発行(PENDING 状態で作成)
ConfirmPaymentCommand 経理担当者 支払い確認を記録し CONFIRMED に遷移

6. Shared Domain(共有ドメイン)

ドメインモデル図

uml diagram

共有コンポーネント一覧

種別 クラス名 日本語名 責務
共有カーネル Location 位置情報 UN/LOCODE で識別される港湾・地点。全コンテキストで共有
共有列挙型 TransportStatus 輸送状態 9 段階の輸送フェーズ。Booking・Tracking で共有
共有列挙型 RoutingStatus 経路状態 NOT_ROUTED / ROUTED / MISROUTED。Booking・Handling で共有

VoyageNumber のコンテキスト分離設計

VoyageNumber は各コンテキストが独自型を保持する。これにより各コンテキストの自律性を保ちながら意味的な一貫性を維持する。

コンテキスト 型名 役割
Routing Context VoyageNumber 航海スケジュールの識別子
Tracking Context TrackingVoyageNumber 追跡イベントに紐づく航海番号(ACL 変換)
Handling Context HandlingVoyageNumber 荷役作業に紐づく航海番号(ACL 変換)

ビジネスルール

  1. Location の変更は全コンテキストチームの合意のもとに行う(Shared Kernel の制約)
  2. UN/LOCODE は国際規格(ISO 3166-1 alpha-2 + 3 文字のロケーションコード)に従う
  3. TransportStatus と RoutingStatus は Booking Context と Tracking / Handling Context の間で整合性を保つ

ドメインイベント

イベント名 発生元 処理先 内容
CargoBookedEvent Booking Context Tracking Context 新規貨物予約後、追跡番号割り当て依頼を通知
CargoRoutedEvent Booking Context Tracking Context 旅程確定後、経路・旅程情報を追跡コンテキストに同期
HandlingActivityRegisteredEvent Handling Context Tracking Context・Booking Context 荷役作業完了後、TransportStatus と BookingStatus を同期
TrackingExceptionDetectedEvent Tracking Context Booking Context・Notification 例外(遅延・損傷・紛失・税関保留)検知後、通知を配信
InvoiceCreatedEvent Billing Context Notification 請求書発行後、荷主への通知を配信

ドメインイベントフロー

uml diagram

外部システム ACL Ports

ポート名 対応外部システム 責務
ExternalRoutingServicePort 外部経路最適化システム 出発地・目的地・期限を渡し最適 CargoItinerary を取得
CustomsClearancePort 税関システム 通関申告の提出・状態照会・CUSTOMS_HOLD 例外の自動通知受信
PaymentGatewayPort 決済機関 支払い処理の実行と支払い確認の受信
PortManagementPort 港湾管理システム 港湾の取扱可能貨物種別(HAZARDOUS / REFRIGERATED)の照会
NotificationPort 通知システム 荷主・荷受人へのメール / SMS 通知の送信

各ポートはヘキサゴナルアーキテクチャの出力ポート(Secondary Port)として定義され、インフラ層のアダプターが実装を担う。これにより外部システムの変更がドメインロジックに影響しない。

集約設計の判断

Booking Context:Cargo 集約

Cargo を集約ルートとし、BookingId・ShipperId・RouteSpecification・CargoItinerary・Delivery を集約内に含める設計とした。

根拠:予約の状態遷移(BookingStatus)はこれらのオブジェクトが一体として整合性を保つ必要がある。特に CargoItinerary の Leg 連結制約(Leg[n].unloadLocation == Leg[n+1].loadLocation)は単一トランザクション内で検証しなければ不整合が生じる。Consignee は Cargo に対して 1 対 1 であるため、独立した集約とせず値オブジェクトとして含める。

Routing Context:Voyage 集約

Voyage を集約ルートとし、Schedule(CarrierMovement のリスト)を内包する設計とした。

根拠:Schedule と CarrierMovement は Voyage の文脈でのみ意味を持つ。Schedule の時系列整合性(CarrierMovement の順序・連続性)は Voyage 単位で保証する必要があるため、単一集約に含める。

Tracking Context:TrackingActivity 集約

TrackingActivity を集約ルートとし、TrackingActivityEvent と TrackingExceptionEvent を集約内エンティティとして管理する設計とした。

根拠:追跡状態(TrackingStatus)は時系列の全イベントと例外状態を総合的に判定するため、単一集約としてまとめる必要がある。例外解決時に「例外発生前の状態に復帰」するロジックは集約内の一貫したトランザクションで実行される。

Handling Context:HandlingActivity 集約 + Read Model 分離

HandlingActivity を集約ルートとし、CustomsDeclaration を集約内エンティティとした。荷役履歴は Read Model(HandlingActivityHistory)として集約と切り離す設計とした。

根拠:個々の荷役作業は独立した記録単位であり、互いに強い整合性制約を持たない。一方、通関申告(CustomsDeclaration)と荷役作業は「CLEARED にならないと CLAIM 不可」という不変条件があるため、同一集約に含める。クエリ専用の履歴参照は Read Model として分離することで、コマンド側(集約)の複雑性を低減する。

Billing Context:Invoice 集約

Invoice を集約ルートとし、DiscountPolicy はドメインサービスではなく値オブジェクトとして Invoice に委譲する設計とした。

根拠:請求書 1 件の整合性(基本料金・割引率・最終金額の一貫性)は Invoice 集約内で保証される。DiscountPolicy の割引率計算ロジックは Invoice の applyDiscount() 内で完結するため、外部ドメインサービスとして切り出す必要はない。支払い状態(PaymentStatus)の遷移も Invoice 集約が責任を持つ。