[AIによる執筆注記] 生成AIを活用して執筆しています。内容の監修・確認は著者が行っています。
はじめに
AIコーディングによって、仕様から実装を生成するコストは急速に下がっています。
一方で、生成対象となる仕様そのものが曖昧であれば、AIは曖昧さをもっともらしい実装へ変換します。コード生成能力が高いほど、誤った解釈も広範囲へ一貫して展開されます。
この問題に対して必要なのは、より長いプロンプトではありません。業務知識を、参照可能、検査可能、再生成可能な中間表現へ変換することです。
本稿では、業務モデルを単一のドメインモデルやUML図としてではなく、次の要素からなる意味グラフとして捉えます。
- Domain:業務概念、属性、状態
- Dictionary:属性の意味的な型
- Use Case:アクターが達成する業務目的
- Service:事前条件と事後条件を持つ業務操作
- Business Rule:操作時に強制する制約
- Error:ルール違反や業務上の失敗
- Screen State Machine:人間とのインタラクション
- View Structure:表示情報と論理配置
重要なのは、これらを個別に記述することではありません。モデル間の参照方向、情報の所有権、導出規則を固定することです。
業務モデルはファイル集合ではなく意味グラフである
業務モデルの全体構造は、概ね次のようになります。
Business Sources
│ source_ref
▼
Use Case ──uses──▶ Service ──enforces──▶ Business Rule
│ │
│ └──violates──▶ Error
│
├──reads/writes──▶ Domain
├──precondition──▶ Domain State
└──postcondition─▶ Domain State
Domain.Attribute ──type──▶ Dictionary Domain
Screen State ──invokes──▶ Service
│
└──view──▶ View Structure ──field──▶ Domain.Attribute
この構造には二種類の関係があります。
一つは、明示的な参照です。
SV-M003.related_rules → BR-M005 SCR-M002.action → SV-M003 VIEW-M002.field → ManufacturingOrder.PlannedQuantity
もう一つは、参照をたどって決定的に導出される情報です。
ManufacturingOrder.PlannedQuantity → domain.yaml の type: Quantity → dictionary.yaml の Quantity → number入力、最小値0、3桁区切り表示
後者を各成果物へ書き写すと、モデルはすぐに二重管理になります。業務モデル設計では、何を記述するか以上に、何を記述せず、どこから導出するかが重要です。
Domain――業務状態の閉包を定義する
Domainは業務上の名詞を集めたデータ辞書ではありません。エンティティ、属性、関係、状態によって、業務操作が成立する空間を定義します。
entities: - name: ManufacturingOrder attributes: - name: OrderNumber type: ManufacturingOrderNumber - name: PlannedQuantity type: Quantity - name: CreatorId type: EmployeeId - name: ApproverId type: EmployeeId? - name: Status type: ManufacturingOrderStatus
Domainが所有すべきなのは、少なくとも次の情報です。
- 業務上の識別単位
- 属性と関連
- 必須/任意
- 業務状態の有限集合
- 集約境界
ここで定義された状態は、Serviceの事前条件・事後条件、Business Rule、シナリオから参照されます。
Domain State ├─ Service.preconditions ├─ Service.postconditions ├─ Business Rule.condition ├─ Screen transition guard └─ Scenario Given / Then
したがって、状態モデルには閉包性が必要です。Serviceが生成する事後状態はDomainに存在し、後続Serviceの事前状態へ接続できなければなりません。
検査すべき代表的な欠陥は次のとおりです。
- 到達不能状態
- どの操作からも生成されない状態
- 終端のない遷移
- Domainに存在しない状態を参照する事前条件
- 禁止遷移を回避できる別Service
Dictionary――プリミティブ型の上に意味型を置く
業務属性をstring、integer、dateだけで表現すると、値の意味が利用箇所へ分散します。
例えばQuantityには、単なる整数以上の契約があります。
domains: - id: Quantity base: integer input: number display_format: "#,##0" validation: min: 0
Dictionaryは、プログラム言語におけるtypedefやValue Objectの型契約に相当します。
Domain.Attribute
│ type
▼
Logical Domain
├─ base type
├─ allowed values
├─ min / max
├─ pattern
├─ input representation
├─ display representation
└─ readonly semantics
この関係から、次の成果物を導出できます。
- プロトタイプの入力コントロール
- 出荷UIの表示形式
- クライアント/サーバー検証
- シナリオfixtureの妥当性
- 境界値テスト候補
- APIスキーマ
ポイントは、QuantityというドメインIDで実装を分岐しないことです。生成器はbase、input、validationといった宣言語彙を解釈します。個別ドメイン名をハードコードすると、辞書が拡張可能な型システムではなく、条件分岐の一覧になります。
Use Case――業務価値の完了条件を表す
Use Caseは画面遷移やAPI呼び出しの一覧ではありません。アクターが業務上の目的を達成する単位です。
UC-M002 製造指図を承認する
Actor: 承認者
Precondition: 承認対象が申請されている
Main flow:
1. 承認対象を照会する
2. 対象を選択する
3. 内容を確認する
4. 承認する
Alternative flow:
- 不備がある場合は差し戻す
Outcome:
- 承認結果を確認できる
Use CaseとServiceは、一対一とは限りません。
UC-M002 ├─ SV-M002 承認対象を照会する ├─ SV-M004 製造指図の詳細を取得する ├─ SV-M003 製造指図を承認する └─ SV-M005 製造指図を差し戻す
逆に、一つのServiceが複数Use Caseから再利用されることもあります。
Use Caseを軸に検証するのがE2Eシナリオです。E2Eは個々のルールではなく、アクターの目的がUIから永続化まで貫通して成立することを確認します。
Service――状態変化を契約として定義する
Serviceは業務モデルの主要な実行単位です。単なるユースケース名の言い換えではなく、入力、事前条件、事後条件、関連ルール、失敗を持つ契約として定義します。
- id: SV-M003 name: 製造指図を承認する inputs: - ManufacturingOrder.OrderNumber - Approver.EmployeeId preconditions: - 製造指図が申請済みである postconditions: - 製造指図が承認済みになる - 承認者と承認日時が記録される related_rules: - BR-M005 errors: - ERR-M003
Serviceは各モデルを接続するハブになります。
Use Case ──uses──────────▶ Service Screen ──invokes───────▶ Service Service ──input─────────▶ Domain.Attribute Service ──pre/post──────▶ Domain State Service ──related_rule──▶ Business Rule Service ──error─────────▶ Error Scenario ──verifies──────▶ Service
Serviceの事前条件はUIの活性条件へ投影できますが、ルールの強制点はService層に置きます。UI制御をセキュリティ境界や業務ルールの実体にすると、API、バッチ、別UIからの呼び出しで制約を回避できます。
また、事後条件は「処理が成功した」という抽象表現ではなく、シナリオのThen節とテストassertionへ落とせる粒度が必要です。
Business Rule――検証可能な業務制約を分離する
Business Ruleは、特定画面の条件ではなく、業務操作に対して常に成立させる制約です。
- id: BR-M005 name: 自己承認の禁止 condition: 製造指図を承認するとき expectation: 承認者は当該指図の作成者と異なる source_ref: - doc: sources/製造管理規程.pdf section: "4.2 職務分掌" confidence: confirmed
Ruleには、少なくとも次の性質が必要です。
- 一意なIDを持つ
- 適用条件と期待結果が分離されている
- 真偽判定可能である
- 業務ソース上の根拠を持つ
- confirmed / inferred / assumedを区別する
- 少なくとも一つのServiceから強制される
- 対応する機能シナリオを持つ
confidenceは承認状態ではなく、由来の分類です。人間がassumedを承認しても、それは「受容された仮定」であり、文書根拠を持つconfirmedへ自動昇格してはいけません。
Error――失敗の語彙を統一する
業務上の失敗をメッセージ文字列だけで扱うと、Service、UI、API、テストで表現が分岐します。
- id: ERR-M003 name: SelfApprovalProhibited related_rule: BR-M005 message: 作成者本人は承認できません
Errorを独立した語彙として管理すると、次の参照を同一の意味へ束縛できます。
Business Rule violation
↓
ERR-M003
├─ Service.errors
├─ Scenario expected_error
├─ UI message
├─ API error mapping
├─ Test assertion
└─ Verification report
HTTPステータスや例外クラスは技術表現です。業務エラーIDを中心に置き、それぞれの実装表現へマッピングするほうが責務を分離できます。
Screen State MachineとView Structureを分離する
画面モデルでは、インタラクションと表示構造を分離します。
Screen State Machine
Screen State Machineは、画面やダイアログを状態として扱い、操作、ガード、Service呼び出し、遷移先を定義します。
SCR-M001 承認対象一覧 │ select ▼ SCR-M002 承認内容確認 │ approve → SV-M003 ▼ SCR-M003 承認完了
ここには表示項目の詳細や入力検証を重複して持たせません。
View Structure
View Structureは、再利用可能なVIEWとして表示項目と論理配置を定義します。
VIEW-M002
main
基本情報
ManufacturingOrder.OrderNumber
ManufacturingOrder.CreatorId
製造計画
ManufacturingOrder.PlannedQuantity
actions
SV-M003 承認
SV-M005 差戻し
それぞれの所有権は次のようになります。
| 情報 | SSOT |
|---|---|
| 画面・ダイアログの状態遷移 | Screen State Machine |
| 項目の配置、順序、一覧列、タブ | View Structure |
| 項目の存在と必須性 | Domain |
| 入力形式、表示形式、値域 | Dictionary |
| 操作の事前条件・事後条件 | Service |
| 業務上の禁止・制約 | Business Rule |
| 仮想スクロールなど技術的実現方法 | Architecture |
この分離により、画面モデルは技術非依存の論理画面契約になります。
画面構造IRによる決定的な合成
Screen、View、Domain、Dictionary、Serviceは、画面構造IRへ合成できます。
Screen State Machine
+
View Structure
+
Domain
+
Dictionary
+
Service
↓
Screen Structure IR
├─ fields
├─ labels
├─ layout tree
├─ list columns
├─ control types
├─ actions
└─ transitions
同じIRをプロトタイプ生成器と出荷UIレンダラが消費すれば、ゲートで承認した画面構造と出荷される画面構造を定義上そろえられます。
Screen Structure IR ├─ Prototype HTML └─ Production UI View
これは単なるコード生成の効率化ではありません。「導出可能な構造を人間が手書きし、意味の一部を落とす」という欠陥経路を閉じるための設計です。
実装者が担当するのは、原則として次の領域です。
- データ結線
- HandlerとServiceの接続
- 共有UIコンポーネント
- CSSと視覚表現
- フレームワーク固有の挙動
一方、業務項目、ラベル、項目順、コントロール種別、業務操作はSSOTから導出します。
二軸のシナリオで意味を検証する
業務モデルは、二つの異なる軸でシナリオへ変換します。
| シナリオ | 起点 | 検証対象 |
|---|---|---|
| E2Eシナリオ | Use Case | アクターの業務目的が端まで成立するか |
| 機能シナリオ | Business Rule | 正常、境界、期限、閾値、異常を網羅するか |
Use Caseだけを検証すると、業務フローは通っても境界条件が漏れます。Ruleだけを検証すると、個別条件は正しくても利用者の目的が端まで成立する保証がありません。
さらに、Serviceの事後条件とエラーについて、機能シナリオのThen節が全節を検証している必要があります。
Service.postconditions
├─ 状態が承認済みになる
├─ 承認者が記録される
└─ 承認日時が記録される
│
▼
Scenario.Thenのassertion集合
テストが存在するだけでは不十分です。仕様上の保証がassertionへ保存されていることが必要です。
トレーサビリティを実行可能なグラフとして扱う
トレーサビリティは管理表ではなく、コンパイル結果の健全性を検査するグラフです。
Business Source → UC / BR / SV → Scenario → Test → Source Code → Verification Report
このグラフから、次の欠陥を検出できます。
| 欠陥 | 検出条件 |
|---|---|
| 根拠のないルール | source_refがない |
| 参照切れ | SVが存在しないBRを参照する |
| 孤立ルール | どのSVからも参照されないBR |
| 未検証ルール | BRに対応する機能シナリオがない |
| 未検証ユースケース | UCに対応するE2Eシナリオがない |
| 空疎なテスト | SCは参照するが対象SVや主要assertionがない |
| 勝手な実装 | どのSVにも対応せず、テストにも踏まれないコード |
| stale成果物 | 上流変更後に下流が再生成されていない |
「テストがgreenである」だけでなく、「どの業務上の主張が、どのテストによって、どの実装を通じて検証されたか」を追跡できることが重要です。
モデル全体で守るべき不変条件
業務モデルを意味グラフとして扱うなら、モデル全体に対する不変条件を定義できます。
参照整合性
- すべてのID参照が解決できる
- すべての属性参照がDomainに存在する
- すべての属性型がDictionaryで解決できる
- すべての画面操作がServiceへ接続される
- すべてのError参照が共通語彙へ解決される
到達可能性と網羅性
- 重要なRuleが少なくとも一つのServiceで強制される
- Serviceが少なくとも一つのUse Caseまたは契約から到達可能である
- Use CaseにE2Eシナリオが存在する
- Ruleに機能シナリオが存在する
- シナリオに実行テストが存在する
状態整合性
- Serviceの事前・事後条件がDomain Stateと一致する
- 状態遷移に到達不能状態や抜け道がない
- 画面の遷移ガードがServiceの事前条件を弱めない
- UI制御が漏れてもService層でRuleが強制される
生成物中立性
- プロトタイプがSSOTからの再生成結果と一致する
- 出荷UIの構造がSSOTからの再生成結果と一致する
- トレーサビリティ表がモデル、シナリオ、実テストからの射影と一致する
- 生成物を直接編集して第二の真実源を作らない
人間向け表現への逆コンパイル
構造化モデルは機械検査に適していますが、人間の意味判断には必ずしも適していません。
そこで、同じモデルを確認目的に合った表現へ変換します。
| 判断対象 | 人間向け表現 |
|---|---|
| 業務の流れとルール | 業務マニュアル |
| 情報量と操作性 | 触れるプロトタイプ |
| 境界値と例外運用 | シナリオ一覧 |
| AIによる補完 | 仮定・疑義一覧 |
| 変更の影響 | 差分とトレーサビリティ |
コードへの変換を順方向のコンパイルとするなら、マニュアル、図、プロトタイプへの変換は人間向けの逆コンパイルです。
ここで重要なのは、逆コンパイルされた成果物も直接編集しないことです。マニュアルに誤りがあればモデルを修正し、再生成します。プロトタイプに項目が不足していればViewまたはDomainへ戻ります。
人間が承認した表現と、テストやコードを駆動する原本を一致させなければ、承認の意味が失われます。
変更は上流へ戻して再コンパイルする
例えば、自己承認禁止ルールの適用条件が変更された場合、正しい変更経路は次のようになります。
BR-M005を修正 ↓ 業務マニュアルと仮定・差分一覧を再生成 ↓ 影響するServiceとScenarioを再評価 ↓ Testを再生成してredを確認 ↓ 実装を変更してgreenにする ↓ E2Eと検証レポートを再実行
テストやコードだけを修正すると、モデル上の業務と実装上の業務が分岐します。
変更管理の単位はファイルではなく、IDによって接続された影響部分グラフです。差分コンパイルでは、変更されたRuleからService、Scenario、Test、実装、レポートへ影響を伝播させます。
業務コンパイラとしてのモデリング
ここまでの構造を、業務コンパイラとしてまとめると次のようになります。
業務資料・規程・ヒアリング
↓ 構造化
検査可能な業務モデル
├─ 逆コンパイル
│ マニュアル・図・プロトタイプ
│ ↓
│ 人間の意味承認
│
└─ 順方向コンパイル
シナリオ・テスト・コード
↓
機械的な整合検査
この方式の信頼性は、AIの出力品質そのものから生まれるのではありません。
- モデル要素に明確な所有権がある
- モデル間の参照が機械的に解決される
- 導出可能な情報を重複記述しない
- シナリオとテストが意味の網羅性を束縛する
- 人間が適切な表現で業務妥当性を判断する
- 変更を上流へ戻して再生成する
これらの合成によって、AIが誤っても誤りを次段へ無検査で伝播させない構造を作ります。
まとめ
業務モデリングの価値は、個々のモデルの精緻さだけでは決まりません。業務知識が適切な責務へ分けられ、それらが検証可能な関係として接続されていることが重要です。
本質は次の四点です。
- 業務知識を責務ごとの中間表現へ分解する
- 各情報のSSOTと参照方向を固定する
- モデル間の不変条件を機械検査する
- 機械向け成果物と人間向け成果物を同じモデルから導出する
Domain、Use Case、Service、Rule、Screenは、それぞれ独立した設計書ではありません。
業務の根拠から検証結果までを接続する、一つの型付き意味グラフです。
AI時代のモデルは、実装前に作って保管する資料ではありません。生成、検査、承認、変更管理を駆動するソースになります。