Skip to content

Latest commit

 

History

History
424 lines (288 loc) · 25.4 KB

File metadata and controls

424 lines (288 loc) · 25.4 KB

ビジネスルールドリブン開発

この文書の位置づけ

Miko の開発手法の設計メモ。議論の経緯と合意事項を記録する。


基本思想

ビジネスルールを明文化し、人間と AI がドメイン知識を共有する基盤とする。

ドキュメント管理手法ではなく、AI 協業のプロトコルである。

なぜビジネスルールか — SDD からの到達

SDD(Specification-Driven Development)を試した結果、以下の問題に気づいた:

  • 仕様が詳細すぎる: SDD の成果物は実装とほぼ1:1のドキュメントになる。AI に実装させるにはそれでもいいが、実装後はそんなドキュメントは不要。コードを読めばいい
  • 人間には理解できない: 詳細すぎる仕様は、よっぽど実装の方がわかりやすい
  • 実装後に死ぬ: メンテされず、すぐに陳腐化する

一方で、コードだけでは「なぜそうなっているか」が読み取れない。AI に毎回コードベースを読ませても、ドメイン知識は散らばっていて拾いきれない。

ビジネスルールは、人間と AI がともに共通認識を取れるちょうど良い抽象度にある。 実装の詳細には踏み込まないが、ドメインの本質的な判断基準は明文化されている。実装後もコードからは読み取れない価値が残り続ける。

レイヤー 人間の理解 AI の理解 実装後の価値
SDD 仕様 詳細すぎる 良い なし(コードを読めばいい)
ビジネスルール ちょうどいい 良い あり(コードに書かれない「なぜ」)
コード 良い 毎回読み直す必要あり コードそのもの

speckit の位置づけ

speckit は SDD のためではなく、Claude に丁寧にコードベースを調査させるための仕掛けとして使っている。speckit を通すと Claude はかなり深くコードを読むので、直接「実装して」と言うより品質が上がる。speckit の成果物自体は使い捨てで、git commit しない。


ドキュメント体系

miko/ の整理軸

  • miko/ の下は ケイパビリティ単位(機能ではない)
  • ケイパビリティ = 「注文管理」「在庫管理」「通知配信」のような大きな単位
  • 機能 = 「注文キャンセル」「在庫引き当て」のような個別の操作。ケイパビリティの一部

ケイパビリティごとの成果物

ファイル 役割 メンテ
business_rules.md ドメインの判断基準。この手法の主役 AI がメンテ
high_level_design.md ケイパビリティの構造と全体像 AI がメンテ
proposals/ ケイパビリティへの変更提案と経緯 人が元ネタを出し、AI と相談しながら書く
  • business_rules.mdhigh_level_design.md は長期メンテ対象。実装と並行して AI が更新する
  • 手法の名前は「ビジネスルールドリブン」だが、ハイレベル設計も並列に置く成果物である。ビジネスルールだけでは構造が見えず、ハイレベル設計だけではドメインの判断基準がわからない。両方あって初めてケイパビリティを理解できる

システム全体のドキュメント

ファイル 役割
miko/system_high_level_design.md システム全体のアーキテクチャ(テナント構造、API 構造、コード探索ガイド等)
miko/glossary.md 用語の定義。ケイパビリティごとのセクションに分けて管理する
ofuda/guides/business_rules_guide.md business_rules.md の生成指示書(AI 向け)
ofuda/guides/business_rules_driven_development.md この文書。開発手法の設計メモ

使い捨ての成果物

ドキュメント 配置 目的
speckit 成果物 specs/<feature>/ Claude に徹底調査させる道具。git commit しない

開発フロー

新規ケイパビリティの場合

1. high_level_design.md を作成(AI)
   miko/<capability>/high_level_design.md
   - ケイパビリティの全体像、構造、処理パイプライン等を記述

2. business_rules.md を作成(AI、モード A: 既存実装から)
   miko/<capability>/business_rules.md
   - 既存コードからビジネスルールを抽出・明文化

既存ケイパビリティへの変更は 提案 → 検証 → 実装 の三段で進む。

1. 提案フェーズ — proposal を書く(人間が元ネタを出し、AI と相談しながら書き上げる)
   miko/<capability>/proposals/YYYY-MM-DD-<title>.md
   - 変更の背景・動機、ビジネスルールの変更、機能仕様を記述

2. 検証フェーズ — harae で proposal 適用後のルール体系を攻撃的に検証(AI)
   /miko.harae <capability> <proposal>
   - 矛盾・穴・悪用耐性などを攻撃的に確かめる。指摘は proposal 内に記録
   - 変更が大きい場合は harae の後に /miko.split_proposal で親 + サブに分割できる

3. 実装フェーズ — proposal に基づいて実装(AI)
   - 基本: /miko.quick_impl(speckit を通さず直接実装)
   - 重い変更: speckit で仕様策定・実装
     /speckit.specify → /speckit.clarify → /speckit.plan → /speckit.tasks → /speckit.analyze → /speckit.implement
     - speckit の成果物は使い捨て。Claude に深く調査させるための道具
   - 実装後にドキュメントを更新
     - business_rules.md を更新(proposal の「ビジネスルールの変更」を反映)
     - high_level_design.md を更新(構造に変更があった場合のみ)
     - harae.md に検証の指摘を転記
     - 重要な代替案があれば proposal に追記

ドキュメントの流れ

提案: proposal(人が元ネタを出し、AI と相談しながら書く)
    ↓
検証: harae(AI が攻撃的に検証、指摘は proposal 内に記録)
    ↓
実装: quick_impl / speckit(AI が実装)
    ↓
business_rules.md(AI が更新:ドメインの判断基準)
high_level_design.md(AI が更新:構造の変化)
harae.md(AI が更新:検証の指摘を転記)
    ↓
proposal に代替案を追記(AI:重要な検討経緯があれば)

ビジネスルールの定義

ビジネスポリシーとビジネスルールの 2 層構造

ドキュメントは 2 つの抽象レイヤーで構成する。

  • ビジネスポリシー(ビジネス方針) — ケイパビリティに通底する価値判断・指針。客観的には判定できない(POL-{連番} 形式で管理)
  • ビジネスルール — ポリシーと整合する具体的な決まり。任意のケースで客観的に判定できる

ポリシーがルールを機械的に「導出」するわけではなく、両者は整合する関係にある(ルールが先にあり、方針が後から整理されることもある)。

両者の分離テスト「客観性」: 任意のケースにおいて客観的に判定できるか? — Yes ならルール、No ならポリシー。

コードから抽出する際、本来はポリシーである価値判断がルールに紛れ込みやすい。意識的に分離する。

ビジネスルールとは

ユースケースの条件には2種類ある:

  • システム的制約 — 技術的に必然。違反するとバグやデータ破壊が起きる。合理的な別の選択肢がない
  • ビジネス的制約 — ビジネスが選んだ判断。合理的な別の選択肢があったが、あえてこちらを選んだ

ビジネスルールとは、後者のビジネス的制約のことである。 「このビジネスでは何が真か」を記述するもので、「システムがどう振る舞うか」ではない。

例: 「ユーザーは、出荷前かつ注文確定から24時間以内であれば、注文をキャンセルできる」

  • 「出荷前」→ 出荷後もキャンセル可能にする設計もありえた → BR
  • 「24時間以内」→ 48時間でもよかった → BR
  • 「キャンセルするとステータスが cancelled になる」→ 他にどうしろと? → BRではない

ビジネスルールは独立して「定義する」ものではなく、ユースケースの条件から「抽出する」ものである。ユースケースを書き、その条件に対して「別の選択もありえたか?」と問うことで、ビジネスルールが浮かび上がる。

ビジネスルールを分離して管理するのは、同じ判断が複数のユースケースに横断するためである。ユースケースごとに条件を書くと判断基準がバラバラに埋まり、一貫性が崩れる。一箇所にまとめることで、すべてのユースケースが同じ判断基準を参照できる。

ドメインビジネスルール / システムビジネスルールの区別

ビジネスルールには 業務寄りのもの(ドメインビジネスルール)システム寄りのもの(システムビジネスルール) がある。

  • ドメインビジネスルール — システムが存在しない(紙台帳と人手だけで運用する)世界でも意味として成立するルール
  • システムビジネスルール — 非同期処理・冪等性・整合性回復など、システムの存在を前提とする概念に依存するルール

判定: 「紙運用」テスト — 紙運用で意味として成立するか?

既存のビジネスルールはコードから抽出されることが多く、表現がコードの語彙に引きずられる。「自動キャンセル」「即時反映」のような語は紙運用なら「日次でキャンセル」「翌朝確認」と置き換え可能で、意味としてはドメインビジネスルール。一方「非同期リトライで整合性回復」は紙運用に対応する概念がなく、システムビジネスルール。コードの表現を一旦剥がして意味で判定する

1 つのルールにドメイン判断とシステム判断が混ざることは避ける。混在していたら分解する。

カタログ上は ### 2.1 ドメインビジネスルール### 2.2 システムビジネスルール の 2 セクションに分けて配置し、各カテゴリ(ORD、PAY 等)はどちらか一方に置く。

判定テスト(AI が内部で使う)

「ビジネスルールかどうか」を感覚ではなく機械的に判定するためのテスト。

[制約] の判定: 「却下した代替案」テスト

そのルールに対して、合理的な代替案(別の選択肢)が存在するか?

  • 代替案が書ける → ビジネスルールである。書く
  • 代替案が「バグを作る」「データを壊す」しかない → ルールではない。書かない

例:

  • 「再付与は冪等にする」→ 代替案「エラーにする」→ 書ける → ルール
  • 「revoke は連携状態によらず実施」→ 代替案「連携中のみ revoke」→ 書ける → ルール
  • 「トランザクション内で作成する」→ 代替案は? → データ不整合(バグ)→ ルールではない
  • 「送信者は2種類」→ 代替案は? → 現実的にありえない → ルールではない

[導出] の判定: 「ビジネス定義」テスト

技術的に必然ではなく、ビジネスが定義したマッピングか?

  • Yes → ビジネスルールである。書く
  • No → 書かない

例:

  • 「premium_plan を持つ → プレミアム会員」→ 別の会員ティアもありえた → ルール
  • 「有効な契約が存在する → ステータスは有効」→ ビジネスが決めた対応関係 → ルール

判定できない場合: 「暗黙のルール(要確認)」として末尾に列挙し、人間に確認する。

よくあるアンチパターン

判定テストを通したつもりでも、以下の 2 パターンは BR ではない。判断軸は 「却下した代替案」テスト に集約される。コードに書いてあるかどうかは判断軸にならない(BR は最終的にコードで表現される)。

  • 要望の言い換え: ユーザーが「〜したい」と言ったことを「〜できる」と書き換えただけのもの。要望の 背後にある条件・閾値・除外規則・対象範囲 だけが BR 候補
  • 実装トレース: 「画面に X を表示する」「Y のときメールを送る」「Z を記録する」のような実装フローをなぞっただけの記述。送る/送らないを分ける条件・タイミングの閾値・除外規則 が BR

アンチパターンに当たっても、背後に判断(代替案が書ける選択)が乗っていれば BR。迷ったら「却下した代替案」テストに戻り、「やらない/別の条件にする」以外の合理的な代替案が書けるかを厳しく問う。

1ルールの粒度と長さ

1ルール=1つの判断。本文はそれを言い切る最小限の長さにする。文の数に固定の上限はない(判断が1つに保たれていれば文の数は問わない)。黄信号は 本文がおおむね150字を超える独立した判断が3つ以上並ぶ(補足を1つ足した2判断までは許容)のいずれかで、経緯の漏れ・仕様の混入・複数判断の同居を疑い、分解 / 経緯を本文から落とす(結論だけ残す)/ 仕様を機能仕様・HLD へ除外 のいずれかで対処する。150字はハード上限ではなく再点検の合図であり、意味の切り詰めや不自然な分割のための数値ではない。

重要な代替案の記録

判定テストの過程で AI が重要な代替案を見つけた場合(「これを知らないと将来間違えそう」というもの)は、proposal に「検討・却下した代替案」セクションとして追記する。business_rules.md にはルールだけ簡潔に書き、経緯は proposal に残す。

書かないもの

  • 自明なこと: 一定の技術力があるエンジニアなら知っていること
  • 一般的な技術知識から導けること: トランザクションでデータ整合性を保つ、等
  • このシステムの既存設計から推測できること: 既存のアーキテクチャや慣習
  • 実装方法: どのクラス、どのメソッドで実現するか(実装マッピングに分離)
  • UI仕様: 表示形式、レイアウト、色、文言。「画面に〜を表示する」「ダイアログを出す」自体も BR ではない(判断が乗っていない実装トレース)
  • 技術仕様: データフォーマット、エンコーディング、通信プロトコル
  • ユーザー要望の単なる言い換え: 「〜したい」を「〜できる」に書き換えただけのもの
  • 通知/送信/出力の「存在そのもの」: 「X のときメールを送る」「Y を記録する」は実装トレース。送る/送らないを分ける 条件、タイミングの 閾値、対象から 除外する規則 が BR

ドキュメントの役割分担

何を記録するか どこに書くか
ルールそのもの(結論だけ、簡潔に) business_rules.md
なぜそう決めたか、何を却下したか proposal

良い例・悪い例

悪い例(書いてはいけない) 良い例(こう書く) 理由
フレームワークのバリデーション構文で一意制約をかける 1ユーザーにつき、同一商品のレビューは1つしか投稿できない フレームワーク非依存の記述
レコードは物理削除せず論理削除する 注文の監査証跡を保持するため、キャンセル後もレコードを残す 「なぜ」が本当のルール
定数定義でステータスを区別する (書かない) 注文のステータスが複数あるのは自明
処理中は全チャネルで受付不可 処理中は、対象チャネルだけでなく全チャネルで新規リクエストを受け付けない 「全チャネル」は非自明な判断

business_rules.md の構造

# {ケイパビリティ名} ビジネスルール

## 背景
## ビジネスポリシー(ビジネス方針)
## 状態遷移(該当する場合)
## 1. 操作の定義(Operations)
## 2. ビジネスルール・カタログ
### 2.1 ドメインビジネスルール
### 2.2 システムビジネスルール
## 3. 関連ケイパビリティとの境界
  • ビジネスポリシー(ビジネス方針): POL-{連番} 形式。ケイパビリティを貫く価値判断。3〜5 個程度を目安に少数に保つ。セクション末尾に <!-- last: POL-XX --> で最終採番を記録する
  • 2.1 ドメインビジネスルール / 2.2 システムビジネスルール: ルールを「紙運用」テストで振り分けて配置する。カテゴリ(ORD、PAY 等)はどちらか一方に置く

操作の定義(Operations)

ケイパビリティは複数の操作群の集合体。フラットなリストではなく、アクター/トリガー別にグループ化して表現する。

### オペレーター操作(API)
- **紐づけ** — 説明。`POST /api/...`

### イベント駆動の自動同期
- **料金プラン変更** — 説明。

### 外部連携(外部サービス名)
- **AI権限の付与・剥奪** — 説明。

### バッチ処理
- **トライアル終了処理** — 説明。

ルール・カタログ

  • カテゴリ: 関連するルールをグループ化。短い日本語 + 英字プレフィックス(例: 権限管理(PERM)
  • ルールID: {プレフィックス}-{連番} 形式(例: PERM-01
  • タグ: 2種類のみ
    • [制約]: 「〜でなければならない」「〜は禁止」— 違反したらエラー
    • [導出]: 「AならばBと定義する」— 事実から値や状態が決まる
  • 実装マッピング: ルール本体とは分離し <details> で折りたたむ。AI にメンテさせる。多少ズレても問題視しない

生成モード

  • モード A(既存実装から): コードの振る舞いから「なぜそうなっているか」を抽出
  • モード B(提案から): 要件をルール単位に分解し、暗黙のルールを推論

詳細は .miko/guides/business_rules_guide.md を参照。


proposal について

proposal の正体

proposal は business_rules.md への変更提案ではなく、ケイパビリティに対する変更提案。ビジネスルールの変更はその一部にすぎない。UI仕様やAPI設計も含む。

暫定フォーマット案

# [変更タイトル]

## 背景・動機
なぜこの変更が必要か

## ビジネスルールの変更
- TRIAL-06 を修正: 「...」
- AI-05 を新設: 「...」
(business_rules.md に反映する内容だけ抜き出す)

## 機能仕様
### UI
### API
### バッチ

## 影響範囲

ポイントは「ビジネスルールの変更」と「機能仕様」を明確に分けること。開発後に「ビジネスルールの変更」セクションだけ business_rules.md に反映する。

注意: このフォーマットはまだ固まっていない。 数本書いてみて調整する段階。

フェーズ分割(親プロポーザル + サブプロポーザル)

大きな変更を PR 単位でフェーズ分割して実装したい場合、親プロポーザル + サブプロポーザル方式を使う。

フロー: /miko.propose で通常通り 1 本のプロポーザルを作成し、/miko.harae で検証した後、/miko.split_proposal で分割する。

/miko.propose → 1 本のプロポーザル作成
/miko.harae → 検証(推奨。分割前にやると手戻りが少ない)
/miko.split_proposal → 親(umbrella)+ サブに分割
→ 各サブに対して /miko.speckit.specify → 実装フロー

親プロポーザル(umbrella proposal): 全体の背景・動機とフェーズ構成のみ。BR 変更・機能仕様は書かない(サブに委譲)。ファイル先頭の <umbrella-proposal> マーカーの有無で親/通常を判定する。

サブプロポーザル: 既存のプロポーザルフォーマットに <sub-proposal@{親のmiko相対パス}> マーカーを先頭に付与したもの。各フェーズの BR 変更・機能仕様を自己完結で記述する。

影響先サブプロポーザル(横断分割): 横断プロポーザル(<needs-split> マーカー付き)を分割する際、影響先ケイパビリティに作成する。<sub-proposal@{親のmiko相対パス}> マーカーのみを先頭に付与し(<needs-split> マーカーは付与しない。サブプロポーザルは実装対象であるため)、背景(親へのリンク)+ BR 変更のみのフォーマット。機能仕様・影響範囲は不要。

miko/<capability>/proposals/
  2026-03-18-cancel-notify-umbrella.md   # 親(背景 + フェーズ構成)
  2026-03-18-cancel-notify-phase1.md     # メインサブ(Phase 1 の BR・機能仕様)
  2026-03-18-cancel-notify-phase2.md     # メインサブ(Phase 2 の BR・機能仕様)

miko/<other_capability>/proposals/
  2026-03-18-cancel-notify-phase1.md     # 影響先サブ(Phase 1 の横断 BR 変更)
  • 実装は各サブプロポーザルに対して /miko.speckit.specify → 実装フローを実行する。同じフェーズのメインサブ + 影響先サブは /miko.speckit.specify に複数パスを渡して統合 spec を生成する
  • /miko.harae に親プロポーザルを渡すと、全サブプロポーザルを読み込んでフェーズ間矛盾も検出する
  • フラット配置で既存の proposals/*.md との互換性を維持する
  • 親子間のリンクは miko/ からの相対パスで記述する(ケイパビリティを跨ぐため)

未解決の論点

  1. proposal のフォーマット: 上記は暫定。実際に数本書いてみてしっくりくる形を探す
  2. speckit ワークフローとの統合: business_rules.md を speckit のインプットとしてどう組み込むか

解決済みの論点

複数ケイパビリティにまたがる変更

決定(v0.6.0〜): umbrella/sub パターンに統一する。propose で横断影響を含む 1 本のプロポーザルを作成し、split_proposal で影響先ケイパビリティに影響先サブプロポーザルを作成する。implement は各サブの BR 変更に従って各ケイパビリティの business_rules.md を更新する。

フロー:

/miko.propose 時:
  → 対話でドラフトを確定
  → 「他ケイパビリティへの影響を調査しますか?」と確認
  → サブエージェントが business_rules.md 存在するケイパビリティを走査
  → 調査結果をもとに proposal の「他ケイパビリティへの影響」セクション + <needs-split> マーカーを付与
  → 完了報告で /miko.split_proposal の実行を案内

/miko.split_proposal 時:
  → 「他ケイパビリティへの影響」セクションから影響先サブプロポーザルを作成
  → 影響先ケイパビリティの proposals/ に配置
  → 親プロポーザルのフェーズ構成に列挙(パスからケイパビリティが判別可能)

/miko.speckit.specify 時:
  → 同じ親の複数サブ(メインサブ + 影響先サブ)を受け付け、統合 spec を生成

/miko.speckit.implement 時:
  → 統合 spec に含まれる複数ケイパビリティの BR 変更を各 business_rules.md に反映

なぜこのアプローチに変更したか:

  • 以前のアプローチ(implement 時にサブエージェントが影響先の proposal 生成 + BR/HLD 更新を自動実行)は、umbrella/sub パターンとは別ルートで横断変更を処理しており、概念モデルが二重構造になっていた
  • 統一することで、横断変更も通常の umbrella/sub と同じフローで処理できるようになり、ユーザーの認知負荷が下がる
  • 影響先サブプロポーザルは split 時点で各ケイパビリティに配置されるため、影響先の変更経緯が早い段階で可視化される

以前のアプローチ(v0.5.0):

  • メインケイパビリティに proposal を 1 本作り、「他ケイパビリティへの影響」セクションを記述
  • implement 完了時にサブエージェントが影響先ケイパビリティへの proposal 生成 + BR/HLD 更新を行っていた
  • cross_capability_update_guide.md に従ってサブエージェントが実行する方式だったが、umbrella/sub パターンとの統一のために廃止

実例

  • ofuda/examples/business_rules.md — business_rules.md のサンプル
  • ofuda/examples/high_level_design.md — high_level_design.md のサンプル
  • .miko/guides/business_rules_guide.md — business_rules.md の生成指示書