/note/tech

モデリングとアーキテクチャの知見を積み上げて基幹システムに可変性を注入する

要約:

■ 問題領域の特定: 在庫管理の「神テーブル」

  • 深刻な現状: モノタロウの基幹システム(受注・配送・発注ドメイン)には、商品の在庫状況に関する属性がたった一つの巨大なテーブルに保存されている。
  • 複雑性の原因:
    • レコード数は5000万件以上に及び、関連する更新ユースケースは80以上、参照ユースケースは730以上存在する。
    • 各ドメインがこのデータ構造に密に依存しており、データ構造の変更は入出荷停止リスクなど、ビジネス基本業務に深刻な影響を与える。
    • この「神テーブル」は在庫の状態のみを持ち、状態に至った経緯(理由)を把握できない。
    • 必要な数値の導出に他のテーブルとの結合が生じ、「在庫状況の管理」という文脈で担保すべき不変条件の範囲が曖昧になっている。
  • 課題への取り組み: 業務とシステムの可変性を取り戻すため、この不要な複雑性の本丸である「在庫状況問題」の分割に取り組むことを決定した。

■ 課題の分割とドメインモデルの仮説構築

  • 分割の常套手段: 「神クラス」分割の常套手段にならい、以下の手順で問題解決にアプローチした。
    • (1) 在庫状況に関連する更新ユースケースを網羅的に洗い出す。
    • (2) どのドメインがどの属性を更新しているか分類する。
    • (3) 属性のオーナー候補ドメインを仮定する。
  • 在庫ドメインの仮説検証:
    • 存在が不確かな「在庫ドメインとその属性」を仮定し、既存の更新ユースケースが破綻なく処理できるか慎重に確認した。
    • 大規模ワークショップでモブプログラミングを実施し、在庫ドメインの属性と責務のイメージをつかんだ。
    • 更新ユースケースをシーケンス図に起こし、ドメインシステム間のメッセージングを確認した。
  • 成果: 上記の密な調整を経て、ついに「在庫ドメインはあります!」という仮説(存在)に至り、積年の課題に切り込むことができた。

■ ドメイン駆動設計(DDD)によるアプローチ

  • DDDの採用理由:
    • 問題領域が基幹業務であること。
    • 在庫管理の柔軟性がモノタロウの競争優位性の源泉となり得ること。
    • 最大の目的が業務とシステムの可変性を取り戻すことであるため。
  • 体制強化: DDDエキスパートやリソース不足という足踏み要因を解消するため、専任チームを結成し、AWSプロフェッショナルサービスの支援を受けた。
  • モデリングの手順:
  • ビッグピクチャーの作成: フルフィルメント全体の業務イベントを可視化する大規模なイベントストーミングを実施。
  • プロセスモデルの作成: 在庫状況の業務領域に絞り込み、イベントがどのように発生したかを分析。
  • ドメインモデルの導出と洗練:
    • プロセスモデル上の集約を取り上げ、コマンドを振る舞い、必要となる値を属性として推定した。
    • 属性をエンティティと値オブジェクトに分けて集約を構成した。
    • その後、業務・モデル・コードを往復する試行錯誤(禅問答)を重ね、概念構成図などを活用しながらモデルを洗練させた。

■ レイヤードアーキテクチャによる実装と品質向上

  • アーキテクチャの採用: 導出されたドメインモデルを実装するためにレイヤードアーキテクチャを採用し、以下の4層で構成した。
    • ビュー層: イベント受付(イベントハンドラ)
    • アプリケーション層: ビジネスロジック実行、ユースケース管理(集約のロードと振る舞い呼び出し)
    • ドメイン層: ビジネスルール、ドメインモデル定義(在庫集約、リポジトリインタフェース)
    • インフラストラクチャ層: データベースアクセス、外部システム連携(リポジトリ実装)
  • 依存関係の逆転: ドメイン層がインフラストラクチャ層に依存するのを避けるため、リポジトリのインタフェースをドメイン層で定義し、実装をインフラストラクチャ層で行うことで回避した。
  • メリット(保守性の向上):
    • 各層の責任と関心事が独立し、システム全体の理解が容易になる。
    • 層間の依存が限定されることで、コードの変更の影響範囲が限定され、変更容易性が向上する(例: 同期→非同期への変更がビュー層の書き換えのみで済む)。
  • ソフトウェアの「質」の向上: 「良いソフトウェア」であるために、設計原則の共有と定期的なリファクタリングを実施。
  • リファクタリングの例(アプリケーション層):
    • 複数のユースケースで共通していた「集約をロード→イベント適用→集約を保存」の処理の流れを特定。
    • SingleEntityCommandServiceという単一のサービスに共通処理を集約し、ユースケースごとにCommandインタフェースを渡す形にリファクタリングした。
    • これにより、コードの重複が減り、再利用性、メンテナンス性、拡張性が向上した。

■ 今後の展望

  • 活動の継続: 在庫ドメインの成果を基幹システム分割・モダナイズ活動の一環として、今後も多くの業務領域に取り組む。
  • 全体最適: 個別の業務領域と並行して、基幹システム全体の構造とマスタデータ管理の最適化を進める必要がある。
  • 知見の共有と仲間探し: 得られた知見のドキュメント化やワークショップ開催を通じて、活動を推し進めるためのより多くの仲間を求めている。