ソフトウェア開発における不確実性
ソフトウェア開発に不確実性はつきものである。仕様も、技術選定も、本番での振る舞いも、利用者の反応も、開発を始める時点で全部わかっていることはない。だから開発アクティビティの多くが「不確実性を扱う」と説明される。
やっかいなのは、こうしたアクティビティを一通りやって「これで大丈夫」と思ったあとに、想定していなかったところで問題が出ることである。アジャイル開発でイテレーションを刻んでも、市場の変化や規制の変更はその外側で起きる。「不確実性」とひとくくりにしていると、取りこぼしが見えてこないので、ここでは不確実性の解像度を高めるためのレンズを考える。
不確実性の構造
不確実性は構造によって性質が違う。何が起こりうるか、なぜ起こるか、減らせるか。切り分けることで、どこに対処するかが決まる。
https://gyazo.com/4987d3ccd20f290bb0b29eb583c9e755
何が起こりうるか (認知・表現)
不確実性をどこまで捉え、記述できるかを問う。
具体的なまずい事態を列挙できるか
列挙できないなら、無知のレベルはどこか。知らないと気づいているのか、気づいてすらいないのか、原理的に知り得ないのか
列挙できるなら、尤度を表現できるか。確率分布で書けるのか、区間や順位までなのか、定性的にしか言えないのか
なぜ起こるか (発生要因)
不確実性が生じている理由を問う。いずれか、あるいは複数が重なる。
曖昧: 言葉や概念の境界が決まっていない。「完了」「重要」「例外」が何を指すのか合っていない
不一致: 関係者の見方が揃っていない。営業・業務・開発で同じ事象を別物として扱っている
複雑: 何が何に影響するか分からない。変更の波及や障害の連鎖が読めない
外部依存・環境変化: 不確実性の出所が自分たちの外側にある。規制、外部API、本番負荷、市場、ユーザー行動
減らせるか (介入可能性)
その不確実性に手が出せるかを問う。学習や観測で減らせるものは Spike や PoC や調査で減らす。減らせないものは、影響を吸収したり、範囲を局所化したり、判断を遅延したり、観測で備えたりする。減らせないものに調査を重ねても、不確実性は減らずコストだけがかかる。
切り分ける前に確かめる前提
不確実性の構造を切り分ける前に、確かめておくべき前提がある。何をまずいとみなすかと、その切り分け自体がどれだけ確かか、である。
何を「まずい」とみなすか (価値判断)
そもそも「障害」「失敗」「まずい」の定義は中立ではない。納期遅延も、運用負荷の上昇も、技術的負債も、例外業務を業務側で吸収させることも、一部利用者の利便性低下も、立場によって「まずい」かどうかが変わる。ここが定まらないまま不確実性の切り分けに入っても、何を切り分けようとしているのかが定まらない。
その切り分けはどれだけ信用できるか (根拠の確かさ)
状態空間の列挙、尤度の推定、合意の根拠、観測値、過去事例の参照。それぞれがどの程度確からしいかという問いで、不確実性のあらゆる切り分けに乗ってくる。「列挙したリスクは網羅されているか」「合意の根拠はどれだけ堅いか」「観測値は計装範囲を超えていないか」のように、切り分け結果そのものに対する確からしさを問い続ける。根拠の確かさは独立した層ではなく、各層の切り分けに常に付随する問いである。
アクティビティの作用は「減らす」だけではない
不確実性を扱うと言っても、アクティビティが実際に何をしているかは様々である。
減らす: 調査や実験で分からなさを縮める
露出させる: 気づいていない不確実性を可視化する
局所化する: 影響範囲を閉じ込める
吸収する: 起きても壊れにくくする
遅延する: 今決めずに選択肢を保持する
合意する: 意味や価値や判断基準を揃える
構造ごとのアクティビティ
価値判断を揃えるアクティビティ
ここで揃えるのは、何をまずいとみなすか、何を望ましいとみなすかである。受け入れ基準も SLO も、技術的な良し悪しではなく、関係者の判断軸をひとつに収束させるための道具である。
受け入れ基準: 「この機能が完成した」と言える条件を関係者で確定する
固定しすぎると未知の例外に追従できない
Done の定義: 開発タスクとして「完了」と呼ぶ状態を揃える
チーム横断で揃わないとリリース判断がぶれる
User Story: 誰のために何を実現するかを記述して、価値の単位を揃える
実装可能性や運用負荷は扱わない
要求優先順位付け (MoSCoW / Kano 分析): 望ましさの強弱を関係者間で揃える
優先順位は時間とともに変わる
品質特性の優先順位付け: 速度・可用性・セキュリティなどのトレードオフを事前に並べて選ぶ
時間とともに優先順位が変わると追従しにくい
NFR 明文化: 機能要件に乗らない制約 (応答時間、稼働率など) を文書として残す
数値が独り歩きして根拠が忘れられがち
責任分界点の設計: 「誰がどこまでを引き受けるか」の合意を文書化する
事前に決められない事案は残る
ステークホルダー熟議: 利害が衝突する局面で、何を優先するかを場で決める
場が設けられないと機能しない
SLO: 維持したいサービスレベルの目標値を関係者で合意する
エラーバジェット: SLO の許容違反量を数値化して、開発速度と信頼性のトレードオフを運用判断に変える
SLO と SLI が合意されていることが前提
認知・表現に効くアクティビティ (列挙できる場合)
まずい事態が列挙でき、それぞれに確率や影響度を付与できる。状態空間が閉じている前提があって初めて、数値化や順位付けが意味を持つ。
見積もり手法そのもの (3点見積、Monte Carlo、Reference Class Forecasting、Contingency / Management Reserve など) も状態空間が閉じている前提で動く道具だが、層が独立した話題なので ソフトウェアの見積もり で扱う。
リスク登録簿 (Risk Register): 識別したリスク事象を一覧化して、発生確率・影響度・対応方針を紐付ける
SRE では SLO のエラーバジェット消費を脅かす事象を継続的に登録・レビューする運用と組み合わせる
登録した時点で状態空間を閉じてしまう側面があり、列挙漏れには別の道具 (Premortem や Red Team など) が要る
確率・影響度マトリクス: 列挙したリスクを縦軸 (発生確率) × 横軸 (影響度) で並べて優先順位を付ける
インシデント対応の優先度判定 (impact × urgency) や脅威モデリング (DREAD など) でも同じ枠組みが流用される
数値の粒度を細かくしても根拠が伴わなければ精度の幻想を生む
FMEA (Failure Mode and Effects Analysis): コンポーネントごとに故障モード・影響・検知性を表で列挙し、Risk Priority Number で順位を付ける
元は航空・自動車の手法だが、クラウド分散システムでは Chaos Engineering と組み合わせる実践が広まっている。FMEA で列挙した故障モードを Chaos 実験で実際に発火させて検証する
Microsoft Azure Well-Architected Framework は failure mode analysis を信頼性設計の標準ステップに組み込んでいる
STPA (Systems-Theoretic Process Analysis): MIT の Nancy Leveson が Engineering a Safer World (MIT Press 2011) で体系化したシステム理論ベースのハザード分析。コンポーネント故障ではなく、コントロール構造の不在や相互作用に着目してハザードを列挙する
Google SRE が社内研修と実プロダクション運用に組み込んでいる (SREcon 2025 で Google Maps チームが事例発表)
単一コンポーネントの故障モードに分解しきれない、システム間の相互作用由来のハザードを拾える点が FMEA と相補的
認知・表現に効くアクティビティ (列挙できない場合)
まずい事態をまだ列挙できていない領域は、Cynefin の Complicated と Complex に分かれる。それぞれ処方が違うので、別々に置く。Chaotic はソフトウェアプロジェクトに頻出する領域ではないので扱わない。認知フレーム自体の詳細 (Five Orders of Ignorance, Cynefin の全体像など) は Unknown Unknowns にまとめている。
Complicated (sense → analyze → respond)
因果はあるが、見るには専門家の分析を経ないといけない。専門家の観点を仕組みに埋め込んで運用する。
網羅的チェックリストによる点検: 専門家が積み上げた観点リストで、設計や運用を系統的に点検する
ソフトウェア開発では IPA 非機能要求グレード が代表例で、可用性・性能拡張性・運用保守性・移行性・セキュリティ・システム環境/エコロジーの6カテゴリにわたって専門家観点が体系化されている。クラウド領域では AWS/Azure/GCP の Well-Architected Framework、セキュリティ領域では OWASP ASVS、CIS Benchmarks などが同じ系譜
系譜としては Fagan inspection (IBM 1976) を起点とするソフトウェア・インスペクション文化や、Michael Nygard の Release It! の運用観点が直接の原典に近い
リストにない観点は点検されない。チェックリストが固定化すると、想定外への感度が下がる副作用がある
Architecture Advice Process: Andrew Harmel-Law のFacilitating Software Architecture (O'Reilly 2024) で提示。決定権を分散させつつ、影響を受ける人と専門家には必ず助言を求めるというルール
専門家を「ボトルネックである意思決定者」から「助言者」に置き換えるので、専門家分析を保ったまま組織にスケールする
Architecture Review Board 型のゲート式と対をなす。ゲート式はスケール時にボトルネック化することが Xapo Bank の導入事例 などで検証されている
Complex (probe → sense → respond)
因果は事前には特定できないが、仮説は立てられる。仮説を probe で試して結果から創発するパターンを観察する。Snowden は safe-to-fail probes と呼んで、複数の小さな実験を並列に走らせることを推奨する。
A/B テスト (オンライン制御実験): Ron Kohavi/Diane Tang/Ya Xu のTrustworthy Online Controlled Experiments (2020) が Microsoft/Google/LinkedIn での運用を扱う一次資料
Booking.com は常時 1,000 実験を並行して走らせ、「idea ではなく hypothesis」を必須要件として明文化している。Snowden の probe に最も忠実な実装
Hypothesis-Driven Development: Thoughtworks が公式手法として整備
Jeff Gothelf の Hypothesis Prioritization Canvas が実務テンプレートとして広く使われる
Spike Solution: Kent Beck XP 起源。技術的不確実性に対する短い実装で仮説を試す
Beck 自身が「Spikes are good when you are knowledge-limited, not time-limited」と書いている通り、知識不足の解消手段
検証範囲を超えた一般化はできない
PoC: 実現可能性そのものを確かめるための部分実装をする
本番品質や運用面まではカバーしない
Walking Skeleton / Tracer Bullet: Alistair Cockburn と Pragmatic Programmer。エンドツーエンドで貫通させる細い実装でアーキテクチャ仮説を probe する
アジャイル反復: 短いサイクルで作って試して、その結果で次のサイクルを決める
学習で減らせる種類の不確実性が前提
インクリメンタル開発: 機能を段階的に積み増して、各段階でリリース可能な状態を保つ
完成像が固まっていないと部分の方向が定まらない
MVP: 最小の機能から本物の利用者に出して、実地の反応で次の不確実性を露出させる
リリース基準を満たさないものしか作れない恐れ
Continuous Discovery: Teresa Torres の Continuous Discovery Habits。週次の顧客インタビューと opportunity solution tree で probe を継続更新する
Spotify/Tesco/CarMax での採用事例があり、Stack Overflow も 2025 年に採用事例を公開している
Dual Track Development: Marty Cagan/Jeff Patton。Discovery トラックで仮説を継続的に probe しつつ、Delivery トラックで確定したものを出す
発生要因が曖昧なときのアクティビティ
「完了」「重要」「例外」「ランダム」のような言葉は、関係者の間で同じ意味で使われているとは限らない。顧客が「ランダムに表示してほしい」と言ったとき、技術者の Random (独立試行で重複あり) ではなく Shuffle (順列のランダム化で重複なし) を意図していた、というすれ違いよくある。使っている語と意図がずれているのを、要件として受け取った時点で気づきたい。
具体例による要件確認 (Example Mapping / Specification by Example): 抽象用語のまま受け取らず、具体例を書き出して確認する規律を組み込む
「ランダムに表示」と言われたら、「同じ要素が連続で出てもいいか」「全要素を1巡したら2周目もランダムか」と具体例を書き出す。書き出す過程で本来の意図 (Shuffle) が露わになる
Three Amigos (BA/Dev/QA の三者セッション) でテスター視点の境界質問を入れると、ズレが浮かびやすい
Falsehoods 系リストの参照: 開発者が無意識に置いている前提を、領域別に反証の箇条書きで列挙したもの。
Patrick McKenzie "Falsehoods Programmers Believe About Names"
Noah Sussman "Falsehoods programmers believe about time"
メタリストの awesome-falsehood が22カテゴリで網羅。Names・Time・Phone Numbers・Addresses・Email・Human Identity・Business・Internationalization などをカバーし、日本固有のものとしては「Parsing the Infamous Japanese Postal CSV」「Top 5 most insane kanji place names in Japan」が含まれる
要件ヒアリングで該当領域の語が出たら、該当の Falsehoods リストを開いて一つずつ確認する運用ができる
Requirements Smells (Henning Femmer ら) の辞書による検出: 要件文書から fast easy user-friendly approximately flexible のような測定不能な形容詞・主観語を機械的に検出する
検出ツール Smella と組み合わせる。IEEE 830 でも weasel words の排除が推奨されている
発生要因が不一致のときのアクティビティ
関係者で世界の見え方が違っている。場を作って見方を揃える。ユビキタス言語の lexicon (語彙) と pragmatics (文脈による意味の使い分け) 層を決めるドメインモデリングがここに該当する。
複数の関係者が同じ場で協働してモデルを作る Collaborative Modeling が、この層の主流処方になる。DDD コミュニティの ddd-crew/como-prep-canvas が正典的なリストを管理しており、ファシリテーション側は Evelyn van Kelle・Kenny Baas-Schwegler・Gien Verschatse Collaborative Software Design (Manning 2024) が認知バイアス対策・心理的安全性・Deep Democracy のランキング技法までカバーしている。
Event Storming: Alberto Brandolini。業務イベントを時系列でオレンジ付箋に書き出し、関係者の認識を一枚絵に揃える。Big Picture / Process Modelling / Software Design Level の3階層で粒度を切り替える
Domain Storytelling: Stefan Hofer & Henning Schwentner (Addison-Wesley 2021)。アクター・作業対象・活動をピクトグラムと矢印で接続して、業務シナリオを domain expert に語らせる
イベント時系列の Event Storming と違って「業務の語り」を単位にする
Impact Mapping: Gojko Adzic。Why (目的) → Who (誰の) → What (どんな振る舞いの変化を起こせば) → How (どう実現するか) のツリーで、目的と実装の対応を関係者で描く
機能要求の背後にある目的のズレを露出させる
User Story Mapping: Jeff Patton。ユーザーの行動を時系列で並べて、機能の全体像と優先順位を関係者で揃える
「何を最小で出すか」の合意形成と組み合わせて使う
発生要因が複雑なときのアクティビティ
何が何に影響するか分からない。コードや業務の構造を取り出して見える形にする。ユビキタス言語の syntax (概念の構成規則) と semantics (構成された概念が指すもの) 層を決めるドメインモデリングがここに該当する。
ドメインモデル: 概念・状態遷移・制約を整理して、変更の波及範囲を読めるようにする
価値判断や外部環境変化は別途扱う
Bounded Context 分割: 別のモデルで動く領域を分けて、相互の影響を断つ。因果構造を局所化する道具で、副作用として外部依存の遮断にも効く
分割自体の妥当性は継続検証が必要
本質的複雑さの可視化 (スタンプ結合解消・全域性・命名): コードに埋もれた構造を取り出す
本質的複雑さの総量は減らせない
リファクタリング: Fowler の定義では「外部から見た振る舞いを変えずに、内部構造を改善する」一連の小さな変換。読み取れる構造を整える
要求変化には追従しない
発生要因が外部依存・環境変化のときのアクティビティ
不確実性の出所が自分たちの外側にある。規制、外部API、市場、ユーザー行動、本番負荷など。外側に何があるかを把握し、変化に追随するアクティビティを並べる。
Wardley Mapping: Simon Wardley。ユーザーニーズから始まる価値連鎖を縦軸 (可視性) × 横軸 (進化段階: Genesis → Custom → Product → Commodity) で配置する
各構成要素が「今どこにいるか」「今後どう動くか」を読む道具。コモディティ化や移行のタイミングが見えるので、外部環境の変化に対して自分たちがどこにいるかを把握できる
ADR の棚卸し: 過去の判断を Superseded ステータスに変えるなどして、判断時点の前提が今も成り立っているかを定期的に見直す
Michael Nygard の原典が「the time to change old decisions will be clear from changes in the project's context」とプロジェクトの文脈変化を見直しトリガーに置く
Joel Parker Henderson の ADR 実践集は ADR ライフサイクルに Maintaining と Sunsetting を含め、「年1回以上のレビュー」と「最終的な Sunset」を明文化する
log4brains は「ADR は immutable で、ステータスだけが変わる」という運用思想をツール側から支える
介入可能性が低いときのアクティビティ (減らせない)
学習や観測では縮められない不確実性に対しては、減らそうとする代わりに、バッファで吸収するか、第三者に転嫁するかの判断になる。リスクマネジメントの古典的な4対策 (回避・低減・転嫁・保有) で言えば、転嫁と保有がここに該当する。
Contingency Reserve: 既知のリスク (known-unknowns) に備えるバッファを計画に組み込む保有の処方。確率分布があれば期待値ベースで算出できるが、定性評価でも置ける
Unknown Unknownsに備えるのは別枠の Management Reserve であり、両者を混ぜると枯渇したときの説明がつかない
タスク個別ではなく工程末や全体に集約する方が消費を観測しやすい
詳しい運用は ソフトウェアの見積もり を参照
エラーバジェット: SLO の許容違反量を数値化して、明示的に「ここまでは受け入れる」と決める保有の処方
SLO と SLI が合意されていることが前提
「価値判断を揃えるアクティビティ」節とも重なるが、こちらは保有量の明文化として扱う
SLA 契約: 外部サービスの品質と障害時の補償を契約で担保する転嫁の処方
契約上の損害賠償上限を明示しておくと、転嫁できる範囲とできない範囲の境界が事前に分かる
「価値判断を揃えるアクティビティ」節の責任分界点の設計が合意形成の側を扱うのに対し、こちらは合意済みの分界を契約として転嫁する側を扱う
マネージドサービス利用: 自前で持たず、AWS RDS のようなマネージドサービスに運用責任を転嫁する
メンテナンス・パッチ適用・冗長化を提供側に預ける代わりに、ベンダーロックインのリスクは保有する
保険 (サイバー保険、システム障害保険): 金銭的影響を保険会社に転嫁する
国内では損害保険ジャパン・東京海上日動などが提供するサイバー保険が代表例。免責条項と補償上限を事前に確認する必要がある
#現代的システム開発概論