第2章: 合成の最小コア(対象・射・合成)
第2章では、仕様を最小の文法へ落とす場面を扱います。 注文処理の流れを Objects / Morphisms / 合成で言い直すと、 AI に渡す契約がどこで閉じるかが見えます。
本章の見せ場は、注文処理フローの図と Objects / Morphisms の断片です。 射の契約をどの粒度で書けば後続章へ持ち運べるかを、その場で確認できます。
学習ゴール
- 対象=状態/型/境界、射=変換/操作、合成=パイプラインとして説明できる
- 合成律(結合律・恒等射)が保守性に効く理由を説明できる
- 例題システムを Objects/Morphisms(最小テンプレ)に落とせる
- 射の契約(Pre/Post、失敗条件)を AI に守らせるための入力(Context Pack)を作れる
圏論コア(定義・直観・ミニ例)
圏(Category)は、最小限には次で定義できます。
- 対象(Object): 要素(本書では「型/状態/境界」を代表させる)
- 射(Morphism): 対象から対象への写像(本書では「操作/API/変換」を代表させる)
- 合成(Composition): 射をつないで新しい射を作る(
g ∘ f) - 合成律(Laws):
- 結合律(Associativity):
h ∘ (g ∘ f) = (h ∘ g) ∘ f - 恒等射(Identity):
- 任意の
f: A → Bに対してf ∘ id_A = fが成り立つ - 同時に
id_B ∘ f = fも成り立つ
- 任意の
- 結合律(Associativity):
型シグネチャの最小例を示します。
validate: Command → ValidatedreserveInventory: Validated → ReservedauthorizePayment: Reserved → AuthorizedauthorizePayment ∘ reserveInventory ∘ validate: Command → Authorizedvalidate |> reserveInventory |> authorizePayment: Command → Authorized(擬似記法)
注: g ∘ f は「まず f を適用し、その結果に g を適用する」ことを表します。
実装で左→右に書く場合は、validate |> reserveInventory |> authorizePayment のような擬似記法で「入力から出力へ読む」形を明示すると混乱しにくくなります。
直観を示します。
合成律は「実装の括弧の付け替え(リファクタ)をしても意味が変わらない」ための条件です。 ソフトウェアでは、パイプラインやユースケースの分割・統合、処理段階の抽象化を繰り返します。そのため、合成律が成立する形で契約を固定すると保守性が上がります。
ミニ例を示します。
validate(入力検証)、reserveInventory(在庫引当)、authorizePayment(決済承認)を順に適用する処理を考える。
- 結合律が成立していれば、2つの合成順序を入れ替えられる。 結果として、状態と副作用の意味は一致する。
- 恒等射は「何もしない段階」を許し、共通処理・条件分岐の組み立てを単純化する(例: ある条件では
idを挟んでパイプラインの形を揃える)。
graph LR
I["Input(Command)"] -->|validate| V["Validated"]
V -->|reserveInventory| R["Reserved"]
R -->|authorizePayment| P["Authorized"]
P -->|appendAudit| O["Order(Placed)"]
ソフトウェア設計への射影(どこに効くか)
本書では次の対応で設計成果物を作ります。
- 対象(Object)=状態/型/境界:
Order(注文)やPayment(決済)などの主要なドメイン型- 状態遷移(例: Draft → Placed → Paid → Shipped)
- 境界(例: Order/Payment/Inventory/Shipment/Audit の責務分離)
- 射(Morphism)=変換/操作:
CreateOrder,PlaceOrder,AuthorizePayment,ShipOrderなどのユースケース/API- 入力/出力、Pre/Post、失敗条件(failures)
- 合成(Composition)=パイプライン:
- ユースケースの連鎖(例: PlaceOrder → AuthorizePayment → ShipOrder)
- 非同期/再試行を含む場合も「意味としての合成」をまず固定する(実装方式は後段で選ぶ)
重要なのは、「AIへ委任する前に射の契約を固定する」ことです。契約が曖昧だと、AIは不足情報を補完し、合成可能な部品(保守可能な境界)になりません。
設計成果物(テンプレ:表/図式/チェックリスト)
共通例題(注文処理)の Context Pack は次を参照します。
ここでは、Objects/Morphisms の最小テンプレを示し、例題で一部を埋めます。
Objects テンプレ(最小)
objects:
- id: <ObjectId>
kind: entity # entity | value | event
states: []
fields: []
note: "" # 任意(境界/権限/不変条件の補足など)
例(Order)を示します。
objects:
- id: Order
kind: entity
states: [Draft, Placed, Paid, Shipped, Cancelled]
fields: [orderId, items, totalAmount, state]
note: "状態遷移の安全性(禁止遷移)を不変条件として後段で固定する"
Morphisms テンプレ(最小)
morphisms:
- id: <MorphismId>
input: {}
output: {}
pre: []
post: []
failures: []
例(PlaceOrder)を示します。
morphisms:
- id: PlaceOrder
input: { orderId: "OrderId" }
output: { orderId: "OrderId" }
pre:
- "Order.state == Draft"
post:
- "Order.state == Placed"
- "InventoryReservation が作成される(または更新される)"
- "AuditEvent(\"PlaceOrder\") が記録される"
failures:
- NotFound
- InvalidState
- OutOfStock
AIエージェントへの引き渡し
AIに実装を委任する場合、まず Morphisms を「契約」として固定し、AIが勝手に改変できないようにします。
最低限、次を Context Pack に含めます。
- Morphisms の Pre/Post/failures(契約)
- Non-goals(やらないこと)
- Forbidden changes(禁止事項)
プロンプト例(抜粋)を示します。
入力の Context Pack に従って実装とテストを生成せよ。
Pre/Post/failures/Forbidden changes を変更してはいけない。
不足情報があれば、補完せず質問せよ。仕様追加は禁止。
検証(テスト観点・可換性チェック)
本章では、射の契約(Pre/Post/failures)が守られていることを最優先で検証します。
- Pre 条件の検証: 前提を満たさない入力で failures が返ること
- Post 条件の検証: 正常系で状態/副作用(監査)まで含めて成立すること
- 合成の安全性: 合成された一連の操作でも、個々の Post が矛盾しないこと
可換図式(Diagrams)をテストへ落とす手順は第3章で扱います。
演習
共通例題の Context Pack を参照し、次を実施します。
- Objects テンプレで、
Order・Payment・InventoryReservation・Shipment・AuditEventを整理する CreateOrder,PlaceOrderを Morphisms テンプレで整理する(Pre/Post/failures を必ず書く)- 作成した Objects/Morphisms を AI に提示し、実装スケルトンと受入テスト案を生成させる
- AIが契約(Pre/Post/failures)を勝手に変更していないかレビューする
まとめ
- 対象=状態/型/境界、射=操作、合成=パイプラインとして設計単位を揃える
- 合成律(結合律・恒等射)は、括弧の付け替え(リファクタ)を意味保存で行うための条件になる
- AI委任では、まず射の契約(Pre/Post/failures)と禁止事項(Forbidden changes)を固定する
次章への接続
- 第3章では、ここで定義した射の契約を Diagram と verification へ押し上げる。