🐙

ベイトソンの冗長性理論で解き明かす、ドメインモデルが『伝わる』設計の秘訣

に公開

導入:完璧な仕様書なのに、なぜ伝わらないのか

「仕様書を読んだけど、結局何を作ればいいか分からない」

この体験は多くの開発者が経験することでしょう。

完璧に見える要件定義書、網羅的なユースケース、詳細なデータモデル。しかし、それらを前にしても開発者は迷います。

ドメインエキスパート(顧客・クライアント)は「ちゃんと説明したのに」と困惑し、開発者は「書いてある通りに作ったのに」と戸惑う。そして出来上がったシステムは、エキスパートが本当に欲しかったものとは違う。

この問題の本質は、「情報の伝え方」にあります。

本記事では、グレゴリー・ベイトソン(システム論・サイバネティクスの研究者)の冗長性理論とコミュニケーション様式の理論、そしてエリック・エヴァンスのドメイン駆動設計を組み合わせることで、「伝わる設計」とは何かを論じます。


Part 1: コミュニケーションには「アナログ」と「デジタル」がある

ベイトソンの2つのコミュニケーション様式

まず、重要な前提を共有します。ベイトソンは、情報の伝え方には2つの様式があると指摘しました。

デジタル・コミュニケーション:

  • 離散的、明確、記号として切り分けられている
  • 例:言葉、コード、データ、文章
  • 特徴:明確だが、それ単体では文脈を持たない

アナログ・コミュニケーション:

  • 連続的、全体的、関係性を保持
  • 例:図像、身振り、表情、業務フロー図
  • 特徴:曖昧だが、文脈(コンテキスト)が直接的に伝わる

小説はデジタルだが、アナログ的に受け取られる

ここで重要なのは、小説や詩といった文学作品です。

文字は明らかにデジタル(離散的な記号)です。しかし、優れた小説を読む時、私たちは単語の羅列ではなく、登場人物の感情や情景という「アナログ的な全体像」を想起します。

なぜでしょうか?

この問いの答えは、Part 2で明らかになります。


Part 2: 冗長性とは「受け手のハート(心、情動)の理」が働くこと

ベイトソンの「円弧」の例

ベイトソンは『精神の生態学』で、こう問いかけます:

なぜ円弧(円の一部)を見ただけで、円全体が推測できるのか?

      ___
    /     \     ← 人が円弧(実線)を見ると...
   |       |
    
      ___
    /     \   ← 円全体が想起される
   |       |     (人にパターン認識が働く)
    \     /
     \___/

答え:情報の受け手の中に「円というパターン」の知識があり、それが働くから

円弧そのものに「私は円の一部です」という情報は書かれていません。しかし、受け手が過去の学習で獲得した「円というパターン」の知識があるため、断片から全体を推測できます。

これが冗長性(Redundancy)です。

冗長性の定義:
情報の断片から、他の情報がランダム以上の確率で予測できること。これは、受け手の中にパターン認識能力(ベイトソンの言う『ハート(心、情動)の理』、すなわち無意識的な感情や直感に基づく論理)が存在し、それが働いて初めて生まれることです。

つまり:

  • 冗長性は「送り手が埋め込むもの」ではない
  • 冗長性は「受け手が過去の学習で獲得したパターンを使って、情報を補完した結果、生まれるもの」
  • アナログ=冗長性ではない(アナログは連続量、冗長性は受け手のパターン認識の結果)

Part 1の答え:なぜ小説から情景が想起されるのか

小説の文字(デジタル)から、読み手が情景や感情(アナログ的な全体像)を想起できるのは:

  1. 読み手が過去の学習で「人間関係のパターン」「感情の流れ」を知っている
  2. 文字の断片を読むと、そのパターンが働く
  3. 結果として、文字に書かれていない「行間」まで想起できる

冗長性が生まれます

ソフトウェア開発における問題

ソフトウェア開発では、ドメインエキスパートが持つ業務の全体像(業務の流れ、顧客の感覚、暗黙の前提)を、デジタルな言葉・コードに変換する必要があります。

しかし:

【情報の流れ】
ドメインエキスパート(全体像を持つ)
  → 言葉で説明(デジタル化)
    → 仕様書・コード(さらにデジタル化)
      → 開発者が読む

この時、開発者の中に「業務パターン」の理解がなければ、断片的な単語から全体像を再構成できません。

つまり、冗長性が生まれないのです。


Part 3: 論理階型理論―「クラスとメンバーを混同するな」

まず「クラス」と「メンバー」とは何か

ベイトソンが影響を受けたバートランド・ラッセルの論理階型理論を理解するには、まず「クラス」と「メンバー」の違いを知る必要があります。

クラス(Class):

  • カテゴリ、概念、集合
  • 例:「大学」「哺乳類」「円」

メンバー(Member):

  • 具体例、要素、個別の事例
  • 例:「東京大学」「犬」「この円」

ラッセルとベイトソンの警告

論理階型理論の核心は:

「クラス(概念)は、それ自身のメンバー(要素)にはなれない」

例:大学というクラス

大学(クラス:カテゴリ・概念)
  ├─ 東京大学(メンバー:具体的な大学)
  ├─ 京都大学(メンバー:具体的な大学)
  ├─ 大阪大学(メンバー:具体的な大学)
  └─ 名古屋大学(メンバー:具体的な大学)

この時:

  • 「大学」(カテゴリ)と「東京大学」(具体例)は異なる論理階型に属する
  • 「大学」というクラス自身を、「大学」のメンバーとして扱ってはいけない

クラスとメンバーを混同するのは、そもそも論理の前提に誤りがあるという、論理階型の誤謬になります。

ドメインエキスパートと開発者のコミュニケーションミスマッチ

ドメインエキスパート:「注文の処理をしてほしい」

開発者が聞き取る内容:

  • 「注文」(概念?具体的な注文データ?)
  • 「処理」(どのレベルの話?個別の注文を処理?注文システム全体を構築?)

問題:エキスパートの言葉の中で、何が「クラス(概念)」で何が「メンバー(具体例)」なのか、明確でない

エキスパートの頭の中:
- 「注文システム」(クラス:システム全体の概念)
  └─ 「今日の注文100件」(メンバー:具体的なデータ)
  
開発者の理解:
- 「注文」って何?
  - 注文クラス(Order)を作ればいい?
  - それとも注文データ(order_id: 001)の話?
  - 注文プロセス全体のこと?

この混同が、仕様書を読んでも「何を作ればいいか分からない」状態を生みます。


Part 4: デジタルデータにも階層がある

コンテキストとは何か

ベイトソンは、コミュニケーションには常にコンテキスト(文脈)があると指摘しました。

同じ「噛む」という言葉でも:

  • 犬が遊びとして噛む
  • 犬が攻撃のために噛む

では全く意味が違います(コンテキストが異なる)。

ソフトウェアで扱うデジタルデータにも、このコンテキストの階層があります。

デジタルコードの3つのレベル

レベル0:データの断片

const stockCount = 100;
const orderId = "ORD-001";
  • 個別の事実、測定値
  • 「今、ここ」のデータの断片

レベル1:データのパターン(ルール・構造)

class Inventory {
  private _count: number;

  // allocate: 割り当てる
  allocate(amount: number): void {
    this._count -= amount;
  }
  
  isLowStock(): boolean {
    return this._count < this.LOW_STOCK_THRESHOLD;
  }
}
  • データを統べる規則、振る舞い
  • 「こういう構造で、こう動く」というパターン

レベル2:パターンのパターン(メタ構造・パターンの型)

レベル2は「学習の学習」に相当します。つまり、「パターン(L1)をどう理解するか、どう扱うか」というメタレベルです。

コード例としては、命名やパッケージ構造で表現されます:

// パッケージ: domain/stock-out-prevention/
// ↑ この名前自体が「在庫切れ防止」というL2の文脈を表現

class StockOutPreventionPolicy {
  // 「在庫予測パターン(L1)」を
  // 「在庫切れ防止(L2)」という文脈で理解する
}

あるいはドキュメント:

// システムの存在理由(L2):
// 「在庫切れによる機会損失を防ぐ」ための予測発注システム

Part 5: ドメインエキスパートとのレベルが混在する会話

実際の会話で何が起きているか

在庫管理のドメインエキスパートに「どうやって在庫を管理していますか?」と聞くと:

「うちは在庫を切らさないようにしてて、
↑ L2: サービス全体の意図・ビジネス戦略

だから毎週月曜に発注するルールで、
↑ L1: 業務パターン・運用ルール

今週は80個発注した。
↑ L0: 個別のデータ

でも先月の売れ行きを見ると、
↑ L1: データのパターン認識

クリスマス商戦に向けて発注量を調整するんです。
↑ L2: 市場環境という上位文脈の認識

来週は120個にする予定」
↑ L0: 予定データ

問題:エキスパート自身も、どのレベルの話をしているか自覚していない

さらに深い問題:「学習のレベル」

ベイトソンは、論理階型を「学習」にも適用しました。

  • 学習0(ゼロ学習):単なる情報の記憶(データベース的)
  • 学習I:試行錯誤による行動の変化(「毎週80個発注」の習慣化)
  • 学習II:学習の仕方そのものを学ぶ(「季節変動を読む」という学習戦略の獲得)

エキスパートの「クリスマス商戦に向けて」は、実は学習IIの話――つまり、「顧客動向の読み取り方を学習している」というメタレベルの話です。

これを単に「120個」というデータ(L0)として受け取ると、なぜ120なのかという文脈が完全に失われます。


Part 6: ドメインモデルへの翻訳―情報の断片だけでは伝わらない

悪い翻訳:全てを同じレベルに並べる

エキスパートの話を聞いた後、多くの設計者はこうします:

// 悪い例:レベルが混在している
interface InventorySystem {
  stockCount: number;           // L0: データ
  reorderPoint: number;         // L1: ルール
  preventStockOut: boolean;     // L2: 意図(?)
  sendNotification(): void;     // L0: 機能
  weeklyOrderAmount: number;    // L0: データ
}

何が問題か?

  1. preventStockOut という「システムの意図(L2)」が、boolean という「データ(L0)」として表現されている
  2. 「このシステムは何のために存在するか」が見えない
  3. レベルの違うものが同列に並んでいる

受け手(開発者)は、これらの断片から「在庫切れ防止」という全体像を再構成できません。冗長性がゼロです。

結果:ドメインエキスパートが本当に欲しいものが作れない。
(参考:顧客が本当に必要だったものをブランコで例えた話)

エヴァンスの蒸留:受け手がパターンを認識できる設計

エヴァンスのDDDにおける蒸留(Distillation)とは、システムを整理して、特に重要なモデル(コアドメイン)を抽出することです。

エヴァンスは以下の概念を提唱しています:

  • コアドメイン(Core Domain):ビジネスの差別化要因。ビジネス価値を生む源泉
  • 汎用サブドメイン(Generic Subdomain):重要であるが、差別化などのビジネス価値は生まないドメイン
  • 凝縮されたメカニズム(Cohesive Mechanisms):複雑な処理をカプセル化したもの(例:暗号化、アルゴリズム)

ここで重要な洞察:

コアドメインには、ビジネスが長年かけて獲得した「学習」が含まれています。特に、より高次の学習(学習I、学習II)がコアに近づく傾向があります。

Part 5で見た「クリスマス商戦に向けて発注量を調整する」というエキスパートの行動は学習II、つまり「顧客動向の読み取り方を学習している」メタレベルの知識でした。

このビジネスの「高次の学習」こそが、コアドメインとして抽出すべきものになります

つまりソフトウェア開発において、受け手(開発者)は、コアドメインを明確にすることで、「このシステムは○○をするためのものだ」とパターンを認識できるようにすることです。

良い設計の例:

// === コアドメイン: システムの存在理由を明示 ===
// パッケージ: domain/model/stock-out-prevention/

class StockOutPreventionService {
  // 「在庫切れを防ぐ」という意図が名前に現れている
  
  constructor(
    private forecastingPolicy: ForecastingPolicy,
    private inventoryRepository: InventoryRepository
  ) {}

  // 補充の必要性をチェックする
  checkReplenishmentNeeds(inventory: Inventory): void {
    const forecast = this.forecastingPolicy.calculateForecast(inventory);
    // 必要に応じて発注
    if (forecast.requiresReorder()) {
      this.triggerReorder(forecast.amount);
    }
  }
}

// === 汎用サブドメイン: データ処理 ===
// パッケージ: domain/model/inventory/

class Inventory {
  private _count: number;
  
  allocate(amount: number): void {
    this._count -= amount;
  }
}

// === 凝縮されたメカニズム: 複雑な計算のカプセル化 ===
// パッケージ: domain/model/forecasting/

class ForecastingPolicy {
  calculateForecast(inventory: Inventory): Forecast {
    // 需要予測のルール
    // 季節変動を考慮した発注量計算
  }
}

何が変わったか?

  1. パッケージ構造(stock-out-prevention)でシステムの意図を表現
  2. クラス名(StockOutPreventionService, ForecastingPolicy)で、受け手がパターンを認識できる
  3. preventStockOut() というメソッドを見ただけで、「ああ、在庫切れ防止システムだな」と分かる

これが冗長性です。


Part 7: ドメインモデルにおける冗長性―受け手が全体を想起できるか

エヴァンスが言う「優れたドメインモデル」

エヴァンスは『ドメイン駆動設計』で、こう述べています:

「コードはモデルの表現であり、モデルをコードから読み取れなければならない」

これは、デジタル(コード)から、受け手がアナログ的な全体像を想起できるようになることと考えられます。

悪い例(冗長性ゼロ):

// stockProjection : 在庫予測
stockProjection.value1  // ???
stockProjection.flag2   // ???

→ 断片を見ても、システムの意図が推測できない

良い例(冗長性がある):

stockProjection.forecastedDemand         // 需要予測
stockProjection.safetyStockLevel         // 安全在庫
stockProjection.preventStockOutThreshold // 在庫切れ防止閾値

→ これらの名前を見た瞬間、受け手の中で「ああ、在庫切れ防止システムだな」というパターン認識が働く

これが「優れたドメインモデル」となります


Part 8: ユビキタス言語―デジタル情報の関係性を設計する

エヴァンスの「ユビキタス言語」とは何か

エヴァンスが提唱するユビキタス言語とは、単なる用語集ではありません。

それは:

デジタルな言葉(単語)どうしの関係性を設計することで、受け手が「ハートの理」を通してアナログ的な全体像を想起できるようにする試み

悪い命名(関係性が見えない):

// inventoryManager: 何でも屋の管理者
// process: 具体的に何をするのか不明
inventoryManager.processInventory(data)

// item: ただのデータ
// update: 何の目的で更新したか不明
item.updateData(value)

// util: 便利屋
// check: 何のルールでチェックするのか不明
util.checkValue(item)

→ 単語を見ても、それらの関係性(なぜ存在するか)が見えない

さらに深刻な問題:開発者の流動(入れ替わり)によって、ドメイン知識が薄い人が増えると、なおさらビジネスの本質から離れていきます。結果として、ドメインエキスパートの要望とシステムの断絶が広がります。

良い命名(関係性が見える):

// 「在庫切れ防止サービス」が、「補充の必要性」をチェックする
stockOutPreventionService.checkReplenishmentNeeds(inventory)

// 「予測ポリシー」が、在庫データを使って「需要」を算出する
forecastingPolicy.calculateForecast(inventory)

// 「在庫」から、注文分を「割り当てる」
inventory.allocate(orderAmount)

→ これらの名前を見れば、「予測 → 安全在庫確保 → 在庫切れ防止」という関係性が見えてくる

これが「コードが語る」の正体です。

アナログとデジタルの往還

ユビキタス言語のもう一つの重要な側面:一方通行ではなく、循環させる

これがシステム理論でいう循環するシステム(フィードバックループ)です。


Part 9: 実践―冗長性のあるドメインモデルの作り方

ステップ0:エキスパートのアナログ的全体像を理解する

最も重要なステップ: まず、ドメインエキスパートが持っている業務の全体像(アナログ的な像)を、開発者自身が理解することです。

これなくして、良い命名も、良いレイヤリングもありません。

具体的には:

  • エキスパートと一緒に業務を体験する
  • 業務フロー図を描いてもらう
  • 「なぜこの作業をするのか?」を繰り返し聞く

ステップ1:エキスパートの話をレベルで整理する

ドメインエキスパートとの会話で、常にこう自問します:

「今、どのレベルの話をしているのか?」

発言 レベル 対応
「在庫を切らしたくない」 L2(ビジネス意図) → コアドメインの候補
「毎週月曜に発注する」 L1(業務ルール) → 汎用サブドメイン
「今週は80個発注した」 L0(個別データ) → 実装詳細
「クリスマス商戦に向けて」 L2(市場環境・学習II) → 需要予測戦略

エキスパートが異なるレベルの話を同時にしたら、こう聞き返します:

開発者:「『在庫を切らさない』ためには、具体的にどんなルール(L1)があるんですか?」

ステップ2:モデルに「パターン認識の手がかり」を埋め込む

設計時のチェックリスト:

□ システムの存在理由(L2)を1文で言えるか?
  例:「在庫切れを防ぐための予測発注システム」

□ コアドメイン、汎用サブドメインが明確に分かれているか?
  - コアドメイン:予測発注ポリシー(ビジネス価値を生む)
  - 汎用サブドメイン:在庫数の増減、通知(必要だが差別化しない)

□ パッケージ構造が意図を反映しているか?
  src/
    domain/
      model/
        stock-out-prevention/  ← コアドメイン
        forecasting/           ← 凝縮されたメカニズム
        inventory/             ← 汎用
      service/
    application/
      usecase/
    infrastructure/
      repository/

ステップ3:命名で「関係性」を表現する

// システムの意図が見える命名
class StockOutPreventionService { }

// ビジネスルールが見える命名
class ForecastingPolicy { }
class ReorderRule { }

// データや処理が見える命名
class InventoryRepository { }
class NotificationSender { }

チェックリスト:冗長性があるか?

□ この1つのクラスを見れば、システムの意図が推測できるか?
□ 新しいメンバーが読んで、「ああ、○○システムだな」と分かるか?
□ ドメインエキスパートがコードを見て、業務の意図を理解できるか?

YESなら、あなたのドメインモデルは冗長性を持っています。


Part 10: よくある反論―「それ、ただの命名とレイヤリングの話では?」

ここまで読んで、こう思う方もいるでしょう:

「結局、良い名前をつけて、レイヤーを分ければいいだけでは?」

この反論の前提

この反論は、「設計とは表現技法の話である」という暗黙の世界観から来ています。

なぜそれがズレているのか

命名やレイヤリングは「結果」であり、本質は「ドメインエキスパートのアナログ的全体像を理解し、それを保存する」ことにある。

表面的な理解:

「preventStockOut という名前を付ければ、意図が表現できる」

実践的な理解:

1. ドメインエキスパートの持つ「在庫切れを防ぐ」という全体像を理解する
   (この過程がないと、次のステップは空疎になる)
2. その全体像をデジタル化の過程で保持する
3. 結果として preventStockOut という名前になる

違いは何か?

前者は「手段だけを真似る」アプローチです。良い名前とレイヤリングという目的だけを渡されても、そこに至る過程(エキスパートの全体像を理解する)がなければ、名前は空疎になります。

設計のレシピだけ真似ても、料理の味(システムの本質)は再現できません。

後者は「過程を経る」アプローチです。ドメインエキスパートのアナログ的全体像を理解し、それを保持しようとするから、自然と良い名前が生まれます。


まとめ:伝わる設計とは、「受け手がパターンを認識できる」設計

4つの断絶を振り返る

  1. ドメインエキスパートの頭の中:全体像とレベルの混在

    • 対策:「今どのレベル?」と聞き返す。そして、全体像を自分も理解する
  2. ドメインモデルへの翻訳:デジタル化で文脈が失われやすい

    • 対策:コアドメイン、汎用サブドメインを明確に分ける
  3. 開発者の解釈:断片だけでは全体が見えない

    • 対策:モデルに冗長性を持たせる(断片から全体を想起できるように)
  4. 時間経過による断絶:開発者の流動、業務の変化

    • 対策:ユビキタス言語の継続的な更新、変更に強い設計

優れたドメインモデルの条件

ベイトソンとエヴァンスから学ぶ、3つの条件:

  1. 情報の関係性が明確

    • 今回のサービスにおいて、L0(データ)、L1(ルール)、L2(意図)の違いが見える
  2. 冗長性がある

    • 部分(クラス名、関数名)を見れば、受け手がパターンを認識できる
    • 受け手の「ハートの理」が働く
  3. デジタルなのに、アナログ的全体性を想起させる

    • コード(デジタル)から、システムの「文脈」が伝わる

最後に:小説のように

優れた小説は、デジタルな文字の羅列です。しかし、読み手は文字の関係性から、情景や感情というアナログ的な全体像を想起します。

優れたドメインモデルも同じです。

コード(デジタル)でありながら、読み手がそこから業務の全体像(アナログ)を想起できる。

「部分を見れば全体が分かる」

これは、受け手のパターン認識能力(ハートの理)が働いた結果として現れる、実践的な設計の指標とも考えられます。


参考文献

  • グレゴリー・ベイトソン『精神の生態学』
  • エリック・エヴァンス『ドメイン駆動設計』

Discussion