コンセプトモデルとプロダクションモデル:ソフトウェア開発における認知構造の考察

1. はじめに

ソフトウェア開発において「認知負荷」という言葉がしばしば用いられる。Team Topologiesでは認知負荷をチーム設計の中心的な制約として扱い、Domain-Driven Designではユビキタス言語によって認知の共有コストを下げようとする。しかし、そもそも開発者の認知がどのような構造を持ち、どこから負荷が生じるのかについて、体系的に整理されたモデルは意外と少ないのではないかと思う。

本稿では、プロダクト開発における開発者の認知構造をモデル化し、認知負荷の源泉を明らかにすることを試みる。チーム設計や組織論は一旦スコープ外とし、単一の「万能な開発者」を想定した抽象モデルを構築する。これは、チーム設計や組織論だけでなく、開発プロセスの設計を考える前段階として、認知の基本構造を理解するための土台となることを意図している。開発プロセスにおけるイテレーションの設計、フィードバックループの短縮、見積もりと計画の考え方などは、いずれも開発者の認知構造と密接に関わっていると私は考えている。

その後、このモデルをベースに様々なプラクティスへの考察を深めていきます


2. 定義・概念の整理

2.1 開発者の認知における 2 つのモデル

開発者の認知は、2 つの異なるモデルから構成されると考えられる。

コンセプトモデル

プロダクションに反映していない、フィードバックや外部要因によって生じた「あるべき姿」のモデルである。仮説的な性質を持ち、検証はプロダクションへの反映後にしか得られない。

プロダクションモデル

現在稼働中のプロダクトを反映した「現状の理解」のモデルである。コードベースや稼働プロダクトとの相互作用を通じて、比較的即座にフィードバックが得られる。

2.2 開発者の認知とインタラクションする 4 つの領域

開発者の認知は、以下の 4 つの外部領域とインタラクションする。

領域 定義
ユーザー プロダクトの利用者。期待・行動・フィードバックの源泉
コードベース ソースコード、設計、ドキュメント。認知の外化であり、読解によって認知を得る対象でもある
稼働プロダクト 本番環境で動作するシステム。運用を通じて認知を検証する
環境 技術動向、法規制、市場・競合など。変化が認知更新を強制する外部要因。また、教養(一般常識として共有されるメンタルモデル)や専門知識(専門家間で通用するメンタルモデル)も環境に含まれる。これらはプロダクトのメンタルモデル構築におけるデザインセンスに大きく影響し、ユーザーにとって自然なインタラクションを設計する上での基盤となる

2.3 ドメイン知識の位置づけ

業務ルールやドメイン知識は、独立した領域としては扱わない。これらは法規制の範囲内でコントロール可能であり、開発者のメンタルモデル(コンセプトモデル/プロダクションモデル)に内包されるものとして扱うのが妥当だと思う。ドメイン知識の更新は、ユーザーからのフィードバックや環境(法改正など)を通じて発生する。


3. 本論

3.1 認知構造の全体像

開発者の認知構造を図示すると以下のようになる。

CognitiveModel.png

この図を見ると、開発者の認知が外部領域とどのようにインタラクションしているかがわかりやすいのではないだろうか。

3.2 フィードバックの経路と時間特性

各領域から開発者の認知へのフィードバックは、経路によって遅延特性が異なる。この違いが、認知負荷の性質にも影響を与えていると考えている。

即時〜短期のフィードバック

コードベースからプロダクションモデルへのフィードバックは比較的即座に得られる。ここで重要なのは、モデルとコードベースの間には抽象と具体の差があるということだ。モデルは抽象であり、コードベースはその具体化である。

コードを書く行為は「抽象的なモデルを具体化する」過程であり、この具体化の過程でモデルへのフィードバックが発生する。抽象的には成立していたはずの設計が、具体化しようとすると矛盾や曖昧さが露呈することがある。これは多くの開発者が経験的に知っていることだろう。コードを読む行為は「具体から抽象を再構築する」過程であり、コードベースからモデルを復元する。ビルドエラーテスト結果も、具体からのフィードバックとしてこのループに含まれる。

短期〜中期のフィードバック

稼働プロダクトからプロダクションモデルへのフィードバックは、監視、ログ分析、障害対応などを通じて得られる。コードベースからのフィードバックよりは遅延があるが、比較的短いサイクルで認知が更新される。

中期〜長期のフィードバック

ユーザーからコンセプトモデルへのフィードバックは、要望、利用パターン分析、インタビューなどを通じて得られる。稼働プロダクトからコンセプトモデルへのフィードバック(仮説検証、A/B テスト結果など)も、この時間軸に属する。

不定期のフィードバック

環境からコンセプトモデルへのフィードバックは、法改正、技術の非推奨化、競合の動向など、予測困難なタイミングで発生する。これが厄介なのは、こちらの都合を待ってくれないという点だ。

フィードバック経路 遅延
コードベース 即時〜短(秒〜時間) 読解、ビルド、実装、テスト
稼働プロダクト 短〜中(時間〜日) 監視、障害、ログ分析
ユーザー 中〜長(週〜月) 要望、利用パターン
稼働プロダクト 長(週〜月) 仮説検証、A/B テスト
環境 不定 法改正、技術変化

3.3 認知負荷の源泉

このモデルから、認知負荷を 4 つのタイプに分類できると考えている。重要なのは、これらは特定の場所に固定されるものではなく、あらゆる認知境界で発生しうる汎用的な負荷タイプであるということだ。

タイプ 1:差分負荷

2 つの認知状態の間に乖離がある状態。コンセプトモデルとプロダクションモデルの間だけでなく、開発者の認知とコードベースの間、開発者の認知とユーザーの期待の間など、あらゆる境界で発生しうる。

タイプ 2:保持負荷

ある対象を認知として保持するコスト。コードベースの規模や結合度、稼働状態の複雑さ、ドメインルールの多さなど、境界の向こう側にある対象の複雑さに起因する。

タイプ 3:翻訳負荷

境界を越えて概念を変換する際の負荷。ユーザーの言葉を開発者の理解に変換する、コードを読解してプロダクションモデルを構築する、環境の変化を認知に取り込むなど、異なる領域間のインタラクションで発生する。

タイプ 4:不確実性

何がわからないかがわからない状態の処理コスト。各境界に「盲点」として潜在する。ジョハリの窓を応用すれば、「認知していないが実際に存在する差分」がこれに該当する。

3.4 境界における負荷の発生

4 つの負荷タイプは、以下のようなあらゆる境界で発生する。

開発者の認知内部

コンセプトモデルとプロダクションモデルの間。開発行為とは本質的に「コンセプトモデルをプロダクションモデルに収束させる」ことだと私は考えているが、その間にも新たなフィードバックによってコンセプトモデルは更新され続ける。よって差分は原理的にゼロにならず、常に追いかけ続ける構造となる。

開発者と 4 領域の間

ユーザー、コードベース、稼働プロダクト、環境との各境界で 4 つの負荷が発生する。

境界 差分負荷 保持負荷 翻訳負荷 不確実性
ユーザー 期待と実態の乖離 ユーザー像の複雑さ 要求の解釈 真のニーズ
コードベース 認知とコードの乖離 コードの規模・複雑さ 読解・記述 隠れた依存関係
稼働プロダクト 想定と実態の乖離 状態の複雑さ 観測の解釈 未知の障害パターン
環境 知識と現実の乖離 知識の広さ、複雑さ 追従・学習 未知のルール・知識の存在/発生

3.5 具体例による検証

ここまで抽象的な話が続いたので、具体例でモデルを検証してみたい。

例 1:法改正対応

インボイス制度のような法改正が発生すると、環境からコンセプトモデルへフィードバックが入る。開発者は法の要件を理解し(翻訳負荷)、現状のプロダクションモデルとの差分を認識する(差分負荷)。この差分をコードベースに反映し、稼働プロダクトにデプロイすることで、プロダクションモデルが更新される。新規開発は法改正後を基準として、コンセプトモデルとプロダクションモデル間の差分に法改正要件は含まれなくなる。

例 2:ユーザーからの機能要望

ユーザーからのフィードバックがコンセプトモデルを更新する。しかし要望は曖昧なことが多く、翻訳負荷が高い。また、要望の背景にある真のニーズは盲点(不確実性)に属することがあり、稼働プロダクトでの仮説検証を経て初めて顕在化する。これは開発者なら誰しも経験があるのではないだろうか。コンセプトモデルを構築し検証を重ねることでよりよいプロダクションモデル構築を目指すこととなる。

例 3:レガシーコードの改修

コードベースの複雑さがプロダクションモデルの保持負荷を増大させる。コードを読解してもプロダクションモデルが正確に構築できず、変更の影響範囲が予測困難になる。これは翻訳負荷と保持負荷の複合であり、レガシーコードが「怖い」と感じる理由の一端かもしれない。プロダクションモデルの構築精度が低い状態でコンセプトモデルを構築する必要に迫られると当然コンセプトモデルの保持負荷・翻訳負荷も同様に高まる。


4. 考察

本章では、提示したモデルをもとに、いくつかの観点から考察を行う。

4.1 開発プロセスへの応用

コンセプトモデルとプロダクションモデルの差分負荷を小さく保つためには、開発プロセスの改善が不可欠である。イテレーションの短縮、継続的インテグレーション、小さなバッチサイズでのリリースなどは、いずれも差分が大きくなる前にプロダクションモデルを追従させる戦略として理解できるのではないだろうか。

この観点から、ウォーターフォールアジャイルの違いを再解釈できる。ウォーターフォールは、コンセプトモデルを大きく構築してからプロダクションモデルへの反映(実装・デプロイ)を行う。この間、フィードバックが得られないためコンセプトモデルの検証ができず、差分は蓄積し続ける。さらに、環境やユーザーからの変化は待ってくれないため、反映が完了する頃にはコンセプトモデル自体が陳腐化している可能性がある(開発者は開発中のコンセプトモデルとは別の、その先のコンセプトモデルを保持する羽目になる)。認知負荷の観点からは、ウォーターフォールは差分負荷と不確実性を最大化するプロセスと言えるかもしれない。

一方、アジャイルは小さな単位でコンセプトモデルをプロダクションモデルに反映し、フィードバックを得てから次のコンセプトを構築する。差分を小さく保ち、不確実性を早期に解消する構造になっている。明らかに合理的だ。

4.2 アーキテクチャ設計への応用

認知負荷の各源泉に対して、どのようなアーキテクチャ戦略が有効かを検討できる。例えば、保持負荷に対してはモジュール化や抽象化、翻訳負荷に対してはユビキタス言語やレイヤー整理、不確実性に対しては可観測性の向上といった対応が考えられる。

特に、認知負荷の大きさを踏まえたアプリケーション分割は重要な設計判断となる。Team Topologies では「チームが認知的に扱える範囲」を分割の基準とするが、これはアーキテクチャにも適用できると考えている。一人の開発者(または一つのチーム)がプロダクションモデルとして保持できる複雑さには限界がある。この限界を超えるシステムは、認知可能な単位に分割されるべきである。

この構造は Team Topologies と同様、フラクタル的な性質を持てると考える。システム全体を認知可能な単位に分割し、各単位の内部もまた認知可能な単位に分割する。各レベルで「コンセプトモデルとプロダクションモデルの差分」「4 領域とのインタラクション」「4 つの負荷タイプ」という同じ構造が現れる。上位レベルでは粗い粒度のモデルを扱い、下位レベルでは詳細なモデルを扱うが、認知の構造自体は相似形となり得る。

4.3 AI 活用への示唆

本稿で提示した認知構造のモデルは、AI(特に大規模言語モデル)の活用を考える上でも示唆を与えると思う。

認知負荷の問題は、本質的に「コンテキストの限定」の問題として翻訳可能である。人間の開発者がワーキングメモリの制約から認知負荷を受けるように、LLMもコンテキストウィンドウの制約を持つ。システム全体を一度に扱うことはできず、適切な境界で区切られた範囲内で作業する必要がある。

この観点から、認知負荷を最小化するための境界設計は、そのまま AI が効果的に作業できる単位の設計にもなるのではないだろうか。モジュール化され、明確な責務を持ち、限定されたコンテキストで理解可能なコードベースは、人間にとっても AI にとっても扱いやすい。

さらにフラクタル構造の考え方は AI 活用においても有効だろう。上位レイヤーでは抽象化された、粒度の荒いコンセプトモデルを扱い、必要に応じて下位レイヤーの詳細に降りていく。各レイヤーで同じ認知構造と 4 つの負荷タイプが適用されるため、AI は現在のコンテキストに集中しながら、必要な情報を適切な粒度で取得できるようにする。人間と AI の協働においても、どのレイヤーのどの範囲を扱っているかを明確にすることで、効果的な分担が可能になるかもしれない。

4.4 モデルの外化手段としての文書

コードベースは認知の外化手段として機能するが、設計文書やドキュメントも同様に外化手段となりうる。しかし、文書をモデルの外化として扱う場合、コードベースとは別のメンテナンスが必要になる点に注意が必要だ。

コードベースと文書の両方をメンテナンス対象とすると、「コードベースと文書の差分」という新たな認知負荷の源泉が生じる。開発者は、どちらが正しいのかを判断するコストを払わなければならない。この観点から、文書はあくまでコードベースを補助するものとして位置づけ、正の情報源(Source of Truth)はコードベースに限定すべきだと私は考えている。

コンセプトモデル検討段階で作成される文書(設計案、提案書、ADR など)については、プロダクションモデルへのマージ(実装・デプロイ)段階で役割を終えるものとして扱うのが妥当だろう。これらは「検討の記録」として残す価値はあるが、継続的なメンテナンス対象とはしない前提を明確にしておくことで、差分負荷の増大を防げる。

4.5 チーム開発における認知の差分

チーム開発においては、モデルの構築主体はチームや組織となる。モデルはチームの総意として抽出される。開発者間にも認知境界が存在するだろう。同じコードベースを見ていても、各開発者のプロダクションモデルは異なる。同じ要件を聞いていても、各開発者のコンセプトモデルは異なる。この差分がチーム内の認知負荷となる。

┌─────────────────┐              ┌─────────────────┐
│ 開発者Aの認知     │←─[4つの負荷]─→│ 開発者Bの認知      │
│ コンセプト/       │              │ コンセプト/       │
│ プロダクション     │              │ プロダクション    │
└─────────────────┘              └─────────────────┘

開発者によってモデル理解の精度は異なる。これは以下の要因に起因すると考えられる。

これらの差異により、同じコードベースを読んでも構築されるプロダクションモデルの精度が異なり、同じ要件を聞いても構築されるコンセプトモデルの解像度が異なる。これが表出するタイミングは外化が行われる時である。

この問題に対する戦略は、共通認識を深めることだ。ユビキタス言語、ペアプログラミングモブプログラミングコードレビュー、設計ディスカッションなどの実践は、開発者間のプロダクションモデルの差分を小さくする。そして、プロダクションモデルの共有度が高まると、新たなコンセプトモデルを抽出する際の認知差分も小さくなる。共通の土台があれば、「あるべき姿」についての議論もより精緻になり、翻訳負荷や不確実性が軽減されるのではないだろうか。

4.6 フィードバック遅延と目標設定

遅延の大きい領域(ユーザーや環境)からのフィードバックを開発者の目標として設定した場合の影響について考察する。

フィードバックが遅延するということは、不確実性が大きいということでもある。コンセプトモデルが正しいかったかどうかの検証に時間がかかり、その間に差分が蓄積しやすい。もし「ユーザー価値の最大化」のような遅延フィードバックに依存する目標を短期的な評価指標として採用すると、開発者は検証を待たずにコンセプトモデルを拡大させるインセンティブを持ちかねない。結果として差分負荷が増大し、認知負荷の観点からは逆効果になる可能性がある。

ここから示唆されるのは、長期目標と短期目標の分離である。ユーザー価値や市場での成功といった遅延フィードバックに依存する目標は長期的な方向性として設定しつつ、短期的な目標はフィードバック遅延の小さい領域(コードベースの品質、デプロイ頻度、障害復旧時間など)に設定すべきではないだろうか。これにより、不確実性の高いコンセプトを検証可能な単位に分解し、差分負荷を制御しながら長期目標に向かうことができると考えている。これはダブルループ学習そのものである。

4.7 プロダクトの価値最大化とユーザー認知

本稿では開発者の認知構造に焦点を当ててきたが、プロダクトの価値最大化を考える上では、ユーザー側の認知も重要な考察対象となる。

ユーザーはプロダクトを「道具」として使用する。このとき、ユーザーはプロダクトを通じてその背後にあるモデル(業務ルール、概念構造)を認知する。優れたプロダクトとは、ユーザーがモデルを自然に理解し、意図した操作を迷いなく行えるものだと私は考えている。

ここで重要になるのが、プロダクトの「モデルに対する透過性」である。プロダクトがモデルを忠実に、余計なノイズなく伝達できるかどうか。モードレスデザインの考え方はこの文脈で理解できる。モードが存在すると、ユーザーは「今どのモードにいるか」という余分な状態を認知しなければならず、本来のタスクへの認知資源が削がれる。モードレスなインターフェースは、プロダクトの透過性を高め、ユーザーがモデルそのものに集中できる状態を作る。

ユーザー価値の最大化や市場インパクトは、このユーザー認知の質に大きく依存する。優れたモデルは透過的であり、それは開発者から見た時も同じように認知負荷の低いものになり得るだろう。


5. まとめ・所感

本稿では、ソフトウェア開発における開発者の認知構造を以下のようにモデル化した。

5.1 所感

本稿のモデル化を通じて、「開発」という行為の本質が少し明確になった気がする。開発とは「コンセプトモデルをプロダクションモデルに収束させる」ことであり、しかしその収束は原理的に完了しない。常に外部から新たなフィードバックが入り、コンセプトモデルが先に進んでしまうからだ。

この「永遠に追いかけ続ける構造」を前提としたとき、認知負荷を最小化する戦略は「差分をゼロにする」ことではなく「差分を扱いやすく保つ」ことになるのではないだろうか。これは技術的負債の議論にも通じるが、今回は認知の観点に限定した。負債としての評価は、このモデルの上に構築される次の層の話になるだろう。

認知の構造をモデリングすることで、もう一つ見えてきたことがある。それは、ソフトウェア開発における様々なエンジニアリングプラクティスが、認知負荷を最小化し、不確実性に対処するためのものとして体系的に理解できるということだ。アジャイル開発は差分負荷を小さく保つ戦略であり、継続的インテグレーションはフィードバックループを短縮する仕組みであり、ペアプログラミングやモブプログラミングは開発者間の認知差分を縮小する実践であり、ユビキタス言語は翻訳負荷を下げる試みであり、可観測性は不確実性を顕在化させる手段である。

これらは個別のベストプラクティスとして語られることが多いが、認知構造のモデルを通して見ると、同じ目的に向かう異なるアプローチとして統一的に理解できる。本稿で提示したモデルが、そうした体系的理解の一助となれば幸いです。