Диаграммы причинных связей: как строить и как проверять
Одиннадцать предыдущих глав дали язык: границы, петли, запасы, задержки, пороги, архетипы, точки воздействия. Этой главой мы переходим к вопросу, который решает судьбу всего остального: как записать своё понимание системы так, чтобы его можно было оспорить.
Разница между схемой и картинкой примерно такая же, как между тестом и комментарием в коде. Комментарий сообщает, что автор думал. Тест падает, когда автор ошибся. Причинная диаграмма (causal loop diagram, CLD) существует, чтобы быть тестом: каждая стрелка в ней — утверждение вида «изменение здесь через такое-то время меняет вон то в такую-то сторону», и каждое такое утверждение может оказаться ложным.
Проблема жанра в том, что диаграммы редко строят так. Типичная схема из презентации содержит пятнадцать облачков, стрелки без знаков, узлы «культура», «мотивация», «качество» — и абсолютную неуязвимость к любым данным. Она объясняет всё, что уже случилось, и не запрещает ничего из того, что случится завтра. Это дорогой способ выглядеть умным. Дальше — как получить обратное: нотация, процедура построения от наблюдаемого поведения, полный разбор с двумя версиями схемы (до проверок и после), батарея тестов, часть которых запускается в CI, и честный разговор о том, чего диаграмма не умеет в принципе.
Что такое причинная диаграмма
Причинная диаграмма — ориентированный граф, где вершины суть величины, а рёбра — утверждения о причинном влиянии с указанным знаком. Циклы разрешены и составляют весь смысл конструкции: именно замкнутые контуры порождают поведение во времени.
Три свойства отличают CLD от произвольной схемы со стрелками:
- Вершина — величина, а не событие и не сущность. «Очередь PR» — величина. «Релиз 4.2» — событие. «Команда платформы» — сущность. Величина растёт и падает; событие случается; сущность просто есть.
- Ребро — причинное утверждение со знаком, а не поток данных, не последовательность шагов и не «связано с».
- Граф замкнут хотя бы в одном месте. Дерево причин без обратных связей — не системная диаграмма, а разбор одного случая: полезная вещь, но другая.
Механику знаков и полярности контуров разбирала глава «Петли обратной связи»; здесь важнее то, чему там не хватило места: как эти графы собирать и как их ломать.
Соседние нотации, которые постоянно путают
Половина плохих схем плоха не из-за ошибок, а из-за смешения трёх разных языков в одном рисунке.
CLD отвечает на вопрос «какая структура могла бы породить наблюдаемое поведение». Она качественная: знаки есть, величин нет. Циклы допускает. Её проверка — сравнение предсказанной формы поведения с фактической.
Диаграмма запасов и потоков (stock-and-flow, SFD) отвечает на вопрос «какие будут числа во времени». Она различает уровень и темп, требует единиц измерения и начальных условий и переводится в систему уравнений напрямую; разница между уровнем и темпом разобрана в «Запасах и потоках».
Ациклический причинный граф (DAG в смысле Перла) отвечает на третий вопрос: «каков размер эффекта X на Y по наблюдательным данным». У него есть строгое исчисление вмешательств, критерий «заднего пути» и правила, когда контроль переменной помогает, а когда портит оценку. Цена строгости — запрет на циклы.
Отсюда самая дорогая методическая ошибка темы: инструменты причинного вывода к схеме с петлями напрямую неприменимы. Если в CLD есть контур A → B → A, никакой backdoor-критерий к нему не относится, пока вы не развернёте петлю во времени: $A_t \to B_{t+1} \to A_{t+2}$. Развёрнутая версия ациклична, и вот на ней машинерия работает. Практический вывод: хотите оценивать эффекты статистически — стройте не CLD, а временной DAG; хотите рассуждать о режимах поведения — стройте CLD и не притворяйтесь, что у вас есть оценка эффекта. Про подмену причинности корреляцией — «Причинные, вероятностные и статистические ошибки». Четвёртый язык, который тоже путают с CLD, — процессные и структурные схемы: BPMN, диаграммы последовательности, C4. Там стрелка означает «поток управления» или «вызов», а не «увеличивает»; схема архитектуры и причинная диаграмма одной системы похожи внешне и не совпадают почти нигде (см. BPMN).
| Нотация | Стрелка означает | Циклы | Что даёт на выходе |
|---|---|---|---|
| CLD | «увеличивает / уменьшает» | обязательны | гипотезу о режиме поведения |
| SFD | «поток вещества» или «информационная связь» | да | численный прогноз при заданных параметрах |
| Causal DAG | «прямая причина» | запрещены | оценку эффекта из данных |
| BPMN / activity | «дальше по процессу» | да, как ветвления | описание порядка действий |
| C4 / архитектура | «вызывает / зависит» | да | карту компонентов |
Минимальная нотация: шесть элементов
Двадцати обозначений не нужно. Рабочий набор помещается в шесть пунктов, и каждый должен быть читаем без легенды.
- Переменная — существительное-величина без оценки, названная так, чтобы рост был осмыслен: «длина очереди», а не «проблемы с очередью».
- Связь со знаком. «+» — при прочих равных рост причины повышает следствие; «−» — понижает. Формально это знак частной производной $\partial, \text{следствие} / \partial, \text{причина}$ в текущей рабочей точке.
- Метка задержки — две поперечные чёрточки на стрелке плюс порядок величины словами: «≈ дни», «≈ два спринта». Без порядка величины метка бесполезна.
- Ярлык контура —
R1,B2и короткое имя-история: «B1: очередь спускают через слияния без ревью». Полярность — произведение знаков $s = \prod_i s_i$: чётное число минусов даёт R, нечётное — B. - Внешняя переменная (exogenous) — то, что входит в схему, но не объясняется ею: сезонность, решение сверху, курс валюты. Помечайте явно, иначе читатель решит, что вы просто не дорисовали.
- Статус стрелки —
измерено(есть метрика и оценка),гипотеза(правдоподобно, не проверено),тождество(следует из определения: «пропускная способность падает — очередь растёт» по закону Литтла). Самый недооценённый элемент нотации: без него схема выглядит однородно достоверной, хотя половина её — догадки. А чего быть не должно: цвета как смысла, стрелок без знака, узлов-действий, «двойных» стрелок вместо двух отдельных связей и подписей длиннее пяти слов.
Правила именования переменных
Восемьдесят процентов негодных схем негодны из-за имён. Пять правил, каждое проверяется механически.
Правило 1. Тест роста. Про переменную должно быть осмысленно сказать «она выросла» и «она упала». «Время ожидания ревью выросло» — да. «Внедрить обязательное ревью выросло» — бессмыслица, значит, это действие, а не переменная. Действия на CLD не рисуют: их эффект выражается изменением какой-то величины.
Правило 2. Нейтральность. Имя не содержит оценки и отрицания. «Недостаток ревьюеров» — плохо: рост недостатка означает падение числа ревьюеров, и через два звена вы обязательно ошибётесь в знаке. Пишите «число доступных ревьюеров». Двойные отрицания в цепочке — самая частая причина неверной полярности.
Правило 3. Операционализуемость. У переменной есть ответ на вопрос «чем мерить и где это лежит». Не «качество кода», а «доля PR, потребовавших более двух раундов ревью»; не «мотивация», а «доля дежурств, закрытых добровольцами без напоминания». Прокси несовершенны, и это нормально: несовершенный измеримый прокси лучше идеального неизмеримого понятия. Как выбирать метрики и не разрушить их наблюдением — «Метрики» и «Измерение производительности».
Правило 4. Одна размерность на узел. «Нагрузка» — не переменная, а слово: это может быть RPS (темп), число активных задач (уровень) или доля занятого времени (безразмерная). Смешение уровня и темпа делает знаки бессмысленными. Правило 5. Одинаковый уровень агрегации: «латентность запроса к Redis» и «эффективность инженерной культуры» на одной схеме — верный признак, что границы не выбраны («Границы системы»).
Процедура построения: от поведения, а не от структуры
Пункт, который меняет качество результата сильнее всех остальных: начинать надо не с рисования узлов, а с графика. Если начать со структуры, вы нарисуете то, что и так знаете, и никогда не выясните, была ли схема нужна. Если начать с наблюдаемого поведения — реального графика реальной метрики за реальный период, — у схемы появляется мишень: она обязана это поведение воспроизвести хотя бы качественно. Такой график в системной динамике называют опорным режимом (reference mode).
Шаги, которые обычно делают плохо:
Горизонт определяет, что вообще попадёт в схему. Для шторма ретраев горизонт — минуты, и наём людей там не нужен; для техдолга горизонт — кварталы, и миллисекунды бессмысленны. Задаётся до переменных и пишется на самой схеме. Граница ведётся тремя явными списками: эндогенное (объясняем структурой), экзогенное (входы, принимаем как данность), исключённое (сознательно за бортом, с одной строкой обоснования). Третий список пропускают все — и потом ссорятся на разборе.
Замыкание. Не пытайтесь замкнуть всё: честная схема состоит из двух-четырёх контуров и нескольких открытых веток к исходам; если замкнулось абсолютно всё — вы дорисовали связи ради красоты. Предсказание формулируется до того, как вы посмотрели на данные после вмешательства, и записывается с датой: «если сделать X, метрика M за срок T изменится в сторону D не менее чем на V; если этого не произойдёт, я вычёркиваю стрелку A → B». Без последней части предсказание не считается.
Разбор: очередь ревью, версия первая
Возьмём знакомую боль: ревью пул-реквестов стало занимать дни, люди жалуются, «надо что-то делать». Вот схема, которую команда рисует на первой встрече за десять минут.
Схема выглядит осмысленно и никуда не годится — каждая из её ошибок встречается в девяти схемах из десяти.
- «Внедрить обязательное ревью» — действие, а не переменная. Тест роста провален; на схеме должна быть «доля PR, слитых с апрувом» — величина, зависящая и от политики, и от поведения людей.
- «Качество кода» и «мотивация» не операционализованы. Знак стрелки
мотивация → качествоне определён ни в какую сторону: он зависит от того, что имел в виду говорящий. Стрелка со знаком «?» — не осторожность, а признание, что связь не сформулирована. - «Нагрузка на команду» смешивает уровень и темп, а задержек и статусов нет вовсе: связь
качество → баги— правдоподобная гипотеза,баги → время на исправления— почти тождество, но выглядят они одинаково. - Главное: схема не отвечает на исходный вопрос. Проблема была про время ожидания ревью — этой величины на схеме нет. Классический признак того, что рисовали от знакомых слов, а не от опорного режима.
Контур в схеме, впрочем, есть, и он верный: качество → баги → время на исправления → нагрузка → качество, два минуса, усиливающая петля. Тот случай, когда верная деталь не спасает целое — потому что вся конструкция не привязана ни к одному наблюдаемому графику.
Опорный режим и различающее предсказание
Вернёмся к шагу 0 и сделаем его как надо: берём одну метрику — медиану времени от открытия PR до первого ревью — и рисуем её за двадцать четыре недели.
График показывает рост с одного дня до почти четырёх за квартал. Дальше — важнейший приём главы: сформулируйте не одну гипотезу о структуре, а две, и найдите наблюдение, которое их разводит.
- Гипотеза A: «узкое место — мощность ревью». Заявок больше, чем часов у ревьюеров; петля одна, очередь растёт, пока приток превышает отток. Предсказание: добавьте двух ревьюеров — ожидание упадёт и останется низким.
- Гипотеза B: «есть компенсирующая петля через размер PR». Когда ревью долгое, авторы копят изменения и шлют более крупные PR; крупный PR ревьюится дольше. Предсказание: добавьте двух ревьюеров — ожидание упадёт на две-три недели, затем размер PR подрастёт и ожидание вернётся почти к прежнему уровню.
До вмешательства обе гипотезы объясняют график одинаково хорошо, и спорить о них на словах бессмысленно — ровно этим обычно занимаются полтора часа на ретро. Различает их только область после вмешательства, и различает надёжно: разрыв между предсказаниями к двадцатой неделе — около двух дней, заметно больше недельного шума. Так системное мышление и превращается из разговора в работу: не «нарисуем схему и обсудим», а «запишем две конкурирующие структуры, каждая из которых что-то запрещает, и посмотрим, какая переживёт квартал». Логика здесь обычная гипотетико-дедуктивная — см. «Научное и инженерное рассуждение».
Разбор: очередь ревью, версия вторая
Та же тема после правил именования, разметки задержек и статусов.
шт."] W["Время ожидания ревью
p50, дни"] BYPASS["Доля слияний без апрува
%"] SIZE["Размер PR
строк, медиана"] COST["Время на один ревью
минут"] CAP["Пропускная способность ревью
PR/день"] DEF["Дефекты в проде
шт./неделя"] FIRE["Разбор инцидентов
часов/неделя"] URG["Срочность релиза
внешняя"] Q -->|"+ измерено"| W W -->|"+ задержка ~дни"| BYPASS BYPASS -->|"− тождество: B1"| Q W -->|"+ гипотеза, задержка ~недели"| SIZE SIZE -->|"+ измерено"| COST COST -->|"− тождество"| CAP CAP -->|"− закон Литтла: R1"| Q BYPASS -->|"+ гипотеза, задержка ~недели"| DEF DEF -->|"+ измерено"| FIRE FIRE -->|"− тождество: R2"| CAP URG -->|"+ внешняя"| SIZE
Что изменилось по существу. Первое: появилась переменная из исходного вопроса — «время ожидания ревью», метрика опорного режима; схема без величины из наблюдаемого графика не проверяема в принципе. Второе: три контура вместо одного, и у каждого есть история:
- B1 — «спускаем очередь через обход». Ждать долго → часть PR сливают без апрува → очередь короче. Уравновешивающая петля, работает быстро и действительно снимает симптом: тот самый архетип «перенос проблемы» из главы «Системные архетипы».
- R1 — «крупные PR». Ждать долго → авторы копят изменения → ревью каждого дороже → пропускная способность ниже → очередь длиннее. Усиливающая: два минуса.
- R2 — «побочный эффект костыля». Обход ревью → дефекты в проде → люди заняты разбором инцидентов → пропускная способность ревью ниже → очередь длиннее → ещё больше обходов. Цена, которую B1 перекладывает на будущее.
Третье: видно соотношение времён — B1 действует за дни, R1 за недели, R2 за недели и месяцы, что проверяемо объясняет паттерн «сначала стало лучше, через квартал стало хуже, чем было»; при обратном соотношении времён паттерн был бы другим («Задержки»). Четвёртое: статусы честные — две связи помечены как гипотезы, время ожидания → размер PR и обход ревью → дефекты. Обе проверяются на исторических данных Git и трекера за пару часов, и до проверки конструкция остаётся правдоподобной догадкой. Схема с честными статусами сразу даёт план работ: не «обсудим ещё раз», а «выгрузим PR за год и посчитаем связь размера и задержки с поправкой на срочность релиза».
Батарея проверок
Схема готова не тогда, когда она красивая, а когда прошла проверки. Ниже — тесты, сгруппированные по тому, что они ловят.
схемы)) Имена Тест роста — величина, а не событие Тест нейтральности — без оценок и отрицаний Тест измеримости — чем мерить и где лежит Тест размерности — уровень или темп Структура Тест замыкания — есть ли контуры Тест висячих узлов — истоки и стоки Тест скрытого запаса — где накопление Динамика Тест знака при прочих равных Тест монотонности — знак не переворачивается Тест времён — порядок величины по стрелке Эмпирика Тест соперника — альтернативная структура Тест опровержения — что стирает стрелку Тест опорного режима — воспроизводится ли график
Разберём те, что не сводятся к правилам именования.
Тест замыкания и висячих узлов. Если в графе нет ни одного цикла — это не CLD; возможно, она вам и не нужна (диаграмма Исикавы или дерево причин честнее описывают одноразовый разбор), но тогда не называйте схему системной и не делайте из неё выводов о динамике. У каждой вершины должен быть хотя бы один вход и один выход внутри схемы, иначе она обязана быть помечена как внешняя или как исход: висячий исток без пометки означает «я не подумал, откуда это берётся», висячий сток — «я не подумал, зачем это здесь».
Тест скрытого запаса — самая коварная ошибка CLD. Если между двумя переменными на самом деле стоит накопление, знак связи вводит в заблуждение: найм → численность команды — не «плюс», а поток, наполняющий запас, и при постоянном найме численность не постоянна, а растёт линейно. Правило: если фраза «A увеличивает B» корректнее звучит как «A увеличивает скорость роста B» — там запас, и его нужно либо отметить явно, либо переходить к диаграмме запасов и потоков. Именно эту слабость нотации разбирал Джордж Ричардсон в статье «Problems with causal-loop diagrams» (System Dynamics Review, 1986): полярность контура читается неоднозначно, когда связь проходит через уровень, и по одной CLD нельзя надёжно определить доминирующий контур.
Тест знака при прочих равных. На каждую стрелку — вопрос буквально: «если я подниму A и заморожу всё остальное, B станет больше или меньше?» Если для ответа приходится рассказывать историю через третью переменную, стрелка не элементарная — разбейте её. Рядом идёт тест монотонности. Знак не должен переворачиваться в рабочем диапазоне. Контрпример: число реплик → латентность отрицательно, пока реплики не начинают конкурировать за пул соединений к базе, и положительно после. Такую связь нельзя пометить одним знаком: либо сузьте диапазон и напишите его на схеме («верно до 40 реплик»), либо разбейте переменную, либо пометьте связь как нелинейную («Нелинейность и пороги»). Схема с фиксированными знаками всегда молча предполагает линейность.
Тест времён. У каждой стрелки — порядок величины: секунды, часы, недели, кварталы. Если у конкурирующих контуров времена различаются на порядок, исход определяет быстрый, и это важнее полярности. Нет ни одной оценки времени — схема не предсказывает даже качественно.
Тест соперника и тест опровержения. Нарисуйте вторую схему, объясняющую те же данные другой структурой. Не можете придумать соперника — вы не понимаете предметную область достаточно, чтобы что-то утверждать; можете, но не находите различающего наблюдения — обе схемы бесполезны для решений, и это надо сказать вслух. Затем на каждую стрелку — ответ на вопрос «какое наблюдение заставит меня её стереть»; стрелки без ответа декоративны: удалять не обязательно, опираться нельзя.
Тест опорного режима — самый строгий: воспроизводит ли предполагаемая структура хотя бы качественную форму наблюдаемого графика (рост, полку, колебания, всплеск с возвратом)? Проверяется прикидочной численной моделью на двадцать строк — это уже мостик в следующую главу.
| Тест | Время | Что ловит | Как часто срабатывает |
|---|---|---|---|
| Рост, нейтральность, измеримость | минуты | негодные узлы | почти всегда на первой версии |
| Размерность, скрытый запас | минуты | подмену уровня темпом | часто |
| Замыкание, висячие узлы, размер | автоматически | недорисованность | часто |
| Знак при прочих равных | 10–20 минут | неявные третьи переменные | часто |
| Монотонность | 10 минут | молчаливое допущение линейности | почти всегда там, где есть насыщение |
| Времена | 15 минут | неверный вывод о доминирующем контуре | часто |
| Соперник, опровержение | 30 минут | нефальсифицируемость | всегда, если раньше не делали |
| Опорный режим | часы | схему, которая не объясняет данные | реже, но это самый дорогой провал |
Что можно проверить автоматически
Структурные тесты незачем делать глазами. Если схема хранится как данные, проверки становятся обычным линтером в CI рядом с проверками разметки. Формат — текстовый, чтобы схема жила в репозитории и ревьюилась как код:
# docs/systems/review-queue.cld.yaml
horizon: "1-2 квартала"
exogenous: ["срочность релиза"]
outcomes: ["дефекты в проде"]
links:
- {from: "очередь PR", to: "время ожидания ревью", sign: +1,
evidence: "GitHub API: p50 времени до первого ревью"}
- {from: "время ожидания ревью", to: "доля слияний без ревью", sign: +1, delay: "дни",
evidence: "audit log: merge без approve"}
- {from: "доля слияний без ревью", to: "очередь PR", sign: -1,
evidence: "тождество: PR уходит из очереди"}
Псевдокод проверок:
для каждой вершины:
нет исходящих и не помечена как исход -> ошибка «висячий сток»
нет входящих и не помечена как внешняя -> ошибка «висячий исток»
имя похоже на действие -> ошибка «не величина»
для каждой связи:
знак = 0 -> ошибка «немонотонная или несформулированная связь»
нет обоснования -> ошибка «стрелка без статуса»
вершин больше 12 -> предупреждение «столько никто не проверит»
циклы <- все простые циклы графа связей
для каждого цикла:
полярность <- произведение знаков рёбер # чётное число минусов -> R, нечётное -> B
вывести полярность, состав цикла и размеченные задержки
циклов нет -> ошибка «это дерево причин, а не системная диаграмма»
Нетривиальна здесь только одна часть — перечисление контуров; остальное сводится к пробегу по спискам. Разметка читается из YAML выше:
from dataclasses import dataclass
@dataclass(frozen=True)
class Link:
"""Причинная связь: «рост src меняет dst при прочих равных»."""
src: str
dst: str
sign: int # +1, -1 или 0 — «знак не определён»
delay: str = "" # порядок величины: "", "минуты", "дни", "недели"
evidence: str = "" # чем подтверждена: метрика, эксперимент, тождество
def build_graph(links):
"""Список смежности. O(V + E) по времени и памяти."""
graph = {}
for link in links:
graph.setdefault(link.src, []).append(link)
graph.setdefault(link.dst, [])
return graph
def find_cycles(graph):
"""Все простые циклы. Каждый выдаётся один раз — начиная с минимальной вершины."""
order = {name: i for i, name in enumerate(sorted(graph))}
cycles, path, on_path = [], [], set()
def dfs(start, node):
for link in graph[node]:
if order[link.dst] < order[start]:
continue # вершины «младше» старта уже разобраны
if link.dst == start:
cycles.append(list(path) + [link])
elif link.dst not in on_path:
path.append(link)
on_path.add(link.dst)
dfs(start, link.dst)
on_path.discard(link.dst)
path.pop()
for start in sorted(graph, key=lambda name: order[name]):
on_path.add(start)
dfs(start, start)
on_path.discard(start)
return cycles
def polarity(cycle):
"""Полярность контура — произведение знаков; ноль означает «неизвестна»."""
product = 1
for link in cycle:
product *= link.sign
return {1: "R (усиливающая)", -1: "B (уравновешивающая)", 0: "неопределена"}[product]
def report(links):
for cycle in find_cycles(build_graph(links)):
chain = " → ".join(link.src for link in cycle) + f" → {cycle[-1].dst}"
delays = [link.delay for link in cycle if link.delay] or ["не размечены"]
print(f"[петля] {polarity(cycle)}: {chain}; задержки: {delays}")
На схеме версии 2 линтер находит ровно три контура — уравновешивающий через долю слияний без ревью и два усиливающих, через размер PR и через разбор инцидентов, — и два предупреждения о непроверенных гипотезах. На схеме версии 1 он выдаёт восемь ошибок, включая узел-действие «внедрить обязательное ревью», висячие истоки и связь мотивация → качество кода без знака. Полсотни строк кода отсеивают целый класс негодных схем до того, как их покажут людям.
Сложность. Построение графа — $O(V + E)$ по времени и памяти. Перечисление простых циклов в общем случае экспоненциально: циклов может быть экспоненциально много, и наивный DFS вдобавок тратит время на бесплодные ветви. Классическое решение — алгоритм Джонсона, $O((V + E)(C + 1))$ по времени и $O(V + E)$ по памяти, где $C$ — число найденных циклов; в NetworkX он доступен как simple_cycles. Для CLD это академическая забота: при $V > 12$ схему всё равно надо резать, и не из соображений производительности (теория графов).
Чего автоматика не проверит: правильность знаков, осмысленность имён, отсутствие пропущенных переменных и соответствие реальности. Эвристика «имя похоже на глагол» даёт ложные срабатывания на нормальных существительных. Линтер ловит форму, а не содержание — как и линтер кода.
Диаграмма как артефакт репозитория
Схема, нарисованная на доске и сфотографированная, умирает за неделю. Схема в репозитории живёт ровно столько, сколько за ней следят, и у неё есть явный жизненный цикл.
Что делает это работающим:
- Схема — текстовый файл, а не картинка. Формат неважен (YAML выше, mermaid, DSL инструмента) — важно, чтобы diff был читаемым и чтобы правка схемы попадала в тот же PR, что и правка системы.
- Дата и автор на схеме. Схему без даты нельзя опровергнуть: всегда найдётся тот, кто скажет «мы это иначе имели в виду».
- Журнал предсказаний рядом — файл со строками «дата — предсказание — срок — результат»; практика разобрана в «Ментальных моделях».
- Опровергнутые схемы не удаляют. Запись «мы думали, что дело в мощности ревью, оказалось — в размере PR» стоит дороже трёх правильных схем: она экономит следующему человеку квартал.
- Пересмотр — по событиям, а не по календарю: после крупного инцидента, при смене границы (реорганизация, вынос сервиса), при появлении данных по помеченным гипотезам.
Ревью схемы вместе с командой
Схема, построенная одним человеком, воспроизводит его ментальную модель со всеми пробелами. Схема, построенная голосованием, воспроизводит компромисс между моделями — обычно худший, чем любая из них. Рабочий формат посередине: один автор ведёт схему, команда атакует её по протоколу.
Три правила, без которых сессия вырождается в спор: атакуют стрелки, а не людей (возражение обязано быть в форме «эта стрелка неверна, потому что…» или «здесь пропущена переменная…»); у каждой правки есть автор и статус («все согласились» — не статус); сессия заканчивается предсказанием или списком запросов к данным — если не вышло ни того, ни другого, встреча была бесполезной, и это нормально признать. Про несовпадающие описания одной системы — «Ментальные модели», про расходящиеся интересы участников — «Стейкхолдеры» и «Конфликты».
Пределы метода
Теперь честная часть, без которой глава была бы рекламой.
Диаграмма не даёт величин и потому не выбирает между режимами. Одна и та же схема описывает конфигурацию, которая работает годами, и конфигурацию, которая падает за сорок секунд. Наличие контура — не предсказание; предсказание требует чисел.
Полярность контура не равна доминированию. Наличие усиливающей петли не означает, что система пойдёт вразнос: рядом почти всегда есть уравновешивающая, и исход определяет соотношение усилений и времён. Это и есть основная претензия Ричардсона к нотации: доминирующий контур по CLD в общем случае не читается, особенно когда связь проходит через запас. И статистический причинный вывод схема с петлями не поддерживает: «контроля на конфаундер» в цикле не существует, пока цикл не развёрнут во времени, а регрессия, приложенная к CLD, — самая частая методическая ошибка в этой области.
Диаграмма убеждает сильнее, чем обосновывает. Стрелки создают ощущение механизма независимо от того, есть ли за ними данные, и схема из пятнадцати узлов производит впечатление глубокого анализа при нулевой информативности. Учитывайте это, когда показываете схему руководству: вы применяете риторический инструмент («Когнитивные искажения»).
Воспроизводимость низкая. Два аналитика, независимо строящие схему одной ситуации, получают разные схемы. Насколько разные — систематически не измерено, по крайней мере мне такие измерения неизвестны; считайте совпадение неизвестной величиной, а не ожидаемым результатом. Следствие: совпадение двух независимых схем — слабое, но настоящее подтверждение; несовпадение не доказывает ошибочность ни одной из них.
Ретроспективная подгонка почти неизбежна. После инцидента любая схема отлично объясняет случившееся; ценность имеет только схема, нарисованная до, и предсказание, записанное до. Про обманчивость разбора через цепочку причин хорошо написано у Джона Оллспо в «The Infinite Hows» и у Ричарда Кука в «How Complex Systems Fail».
Границы применимости жанра. Решение уже принято и вопрос в исполнении — схема не нужна. Проблема одноразовая — не нужна. Нет ни одной метрики по теме — сначала метрики. Причинные диаграммы окупаются там, где проблема повторяется, разворачивается во времени и сопротивляется очевидным решениям. В остальных случаях это дорогая форма прокрастинации.
Честно про доказательную базу
У нотации есть история, и в ней есть содержательный спор, о котором обычно умалчивают.
Что стоит твёрдо. Правило полярности как произведения знаков — арифметика; различение уровня и темпа — математика, а не мнение; ограничения нотации, описанные Ричардсоном, воспроизводятся на контрпримерах — можно построить две схемы с одинаковой петлевой структурой и разным поведением. На эксперименте стоит другое: систематическая неверная оценка обратной связи и задержек людьми — воспроизводимый лабораторный результат (Sterman, Management Science, 1989). Это довод за то, что интуиция здесь подводит и внешняя запись нужна, но не довод за конкретную нотацию.
Что остаётся спорным — и это главное. В 2000 году Джеффри Койл в System Dynamics Review поставил вопрос прямо: можно ли делать выводы, ограничиваясь качественными схемами без счёта? Джек Хомер и Роджелио Олива в ответной статье (2001) утверждали, что нельзя: без количественной модели выводы о динамике систематически ненадёжны, потому что человек не умеет в уме сворачивать несколько контуров с разными задержками. Спор не закрыт, и практическая позиция, которой стоит держаться: качественная схема — законный промежуточный артефакт и незаконный конечный результат. Как средство собрать гипотезу и договориться о словах — да; как основание для решения ценой в квартал — нет, если её никак не приземлили.
Что слабее, чем принято думать. Эффективность группового построения моделей оценивалась в основном по самоотчётам участников: люди сообщают, что стали лучше понимать проблему и охотнее принимают решение. Это правдоподобно и почти ничего не говорит о том, стали ли решения лучше; контролируемых сравнений «схема против отсутствия схемы» по объективным исходам практически нет. Отдельно про книги: Медоуз («Thinking in Systems») даёт лучший вводный язык и не даёт метода проверки. Сенге («Пятая дисциплина») популяризировал архетипы и вместе с ними стиль, где схема заменяет доказательство. Стерман («Business Dynamics») — единственный из массовых источников, где валидации отведена отдельная большая глава: если читать одну книгу по теме, читать стоит эту, но ради глав о проверке, а не ради красивых петель. Полемику вокруг «Пределов роста» разбирала глава о петлях; вывод тот же — чем крупнее объект модели, тем слабее её предсказательная сила и тем осторожнее должен быть тон.
Типичные ошибки
- Рисовать от структуры, а не от графика. Схеме без опорного режима нечего воспроизводить, значит, её нечем проверить.
- Узлы-действия и узлы-события. «Внедрить ревью», «случился инцидент» — не величины.
- Оценочные имена. «Проблемы с качеством», «недостаток людей» — гарантированная ошибка в знаках через два звена.
- Стрелка «связано с». Не можете сказать, в какую сторону влияет рост, — связи нет, есть ощущение.
- Смешение уровня и темпа в одном узле. «Нагрузка» — самый частый нарушитель; рядом стоит пропущенный запас между причиной и следствием (признак: фраза корректнее звучит как «увеличивает скорость роста»).
- Схема на двадцать пять узлов. Её никто не проверит, включая автора: режьте по границе на несколько схем с разными горизонтами.
- Одинаковый статус у измеренных связей и у догадок. Схема выглядит достовернее, чем есть, ровно на долю догадок.
- Отсутствие времён. Без них вывод о победившем контуре берётся из воздуха.
- Ретроспективная схема, выданная за предсказание. Нарисована после события — так и напишите на ней.
- Регрессия поверх схемы с петлями. Разверните во времени или не считайте.
- Схема как результат встречи. Результат — предсказание, запрос к данным или решение; схема — побочный продукт.
Инструменты
- Текст + mermaid (mermaid.js.org) — если схема живёт в репозитории и её достаточно читать; все диаграммы этой главы сделаны так.
- PySD (pysd.readthedocs.io) — Python-библиотека, читает модели Vensim и XMILE и считает их в обычном пайплайне с pandas: лучший способ перейти от схемы к числам, не покидая инженерных инструментов.
- Vensim (vensim.com), Stella, Insight Maker (insightmaker.com) — среды с симуляцией и анализом чувствительности; Insight Maker бесплатен и работает в браузере. LOOPY (ncase.me/loopy) — игрушечный, но сразу показывает поведение петли во времени. Kumu (kumu.io) — для больших карт со стейкхолдерами, легко скатывается в декоративность.
- STPA — метод анализа безопасности Нэнси Левесон, где вместо цепочек отказов рассматриваются петли управления и небезопасные управляющие воздействия («Engineering a Safer World» доступна свободно). Хороший пример того, как выглядит системное мышление, доведённое до проверяемой процедуры с чеклистами.
Чеклист перед тем, как показывать схему
- Есть ли график опорного режима и указан ли горизонт?
- Выписаны ли три списка: эндогенное, экзогенное, исключённое?
- Проходит ли каждый узел тесты роста, нейтральности и измеримости?
- Есть ли узел с метрикой из исходного вопроса?
- Знаки расставлены «от роста» и «при прочих равных»; помечены ли связи, знак которых переворачивается в рабочем диапазоне?
- Проставлены ли порядки величины задержек?
- У каждой стрелки есть статус: измерено / гипотеза / тождество?
- Замкнулось ли что-нибудь и названы ли контуры историями?
- Нет ли скрытого запаса между причиной и следствием?
- Нарисована ли альтернативная структура и найдено ли различающее наблюдение?
- Записано ли опровержимое предсказание с датой и сроком?
- Умещается ли схема в двенадцать узлов, объясняется ли за три минуты и лежит ли в репозитории в текстовом виде?
Если пунктов 10 и 11 нет — вы показываете не результат анализа, а рисунок.
Мини-итог
- Причинная диаграмма — записанная гипотеза о структуре, а не иллюстрация; её ценность равна тому, что она запрещает.
- CLD, диаграмма запасов и потоков и ациклический причинный граф отвечают на три разных вопроса; смешение — источник самых дорогих ошибок, включая попытки считать эффекты в графе с петлями.
- Строить надо от наблюдаемого поведения: график, горизонт, граница, переменные, знаки, замыкание, задержки, предсказание.
- Имена решают всё: величина, а не действие; нейтральное, а не оценочное; измеримое, а не концептуальное; одна размерность на узел.
- Статус каждой стрелки — измерено, гипотеза или тождество — обязателен: без него схема выглядит достовернее, чем есть. Структурные проверки автоматизируются полусотней строк кода; содержательные — нет.
- Главный приём: две конкурирующие структуры и наблюдение, которое их различает. Без соперника гипотеза не проверяется, а иллюстрируется.
- Полярность контура не равна доминированию, а схема без чисел не выбирает между «работает годами» и «падает за минуту».
- Спор о достаточности качественных схем идёт с 2000 года и не закрыт. Рабочая позиция: законный промежуточный артефакт, незаконный конечный результат.
Источники
- John Sterman. Business Dynamics: Systems Thinking and Modeling for a Complex World (2000) — главы о причинных диаграммах и о валидации моделей.
- George Richardson. Problems with causal-loop diagrams — System Dynamics Review, 1986; и его же возврат к теме в 1997. Журнал: onlinelibrary.wiley.com/journal/10991727.
- Geoff Coyle. Qualitative and quantitative modelling in system dynamics: some research questions — System Dynamics Review, 2000; ответ: Jack Homer, Rogelio Oliva. Maps and models in system dynamics: a response to Coyle — там же, 2001.
- John Sterman. Modeling Managerial Behavior: Misperceptions of Feedback in a Dynamic Decision Making Experiment — Management Science, 1989.
- Donella Meadows. Thinking in Systems: A Primer (2008) — chelseagreen.com; Judea Pearl, Madelyn Glymour, Nicholas Jewell. Causal Inference in Statistics: A Primer — bayes.cs.ucla.edu/PRIMER.
- Nancy Leveson. Engineering a Safer World — PDF, MIT.
- John Allspaw. The Infinite Hows — O’Reilly Radar; Richard Cook. How Complex Systems Fail — how.complexsystems.fail.
- Google SRE Book: Postmortem Culture. System Dynamics Society — systemdynamics.org.
Что дальше
Мы дошли до границы качественного жанра. Проверки этой главы отсеивают схемы, заведомо негодные, но ни одна из них не отвечает на вопрос «что будет и когда». Ответ требует чисел: уравнений, параметров, начальных условий — и вместе с ними приходит новый класс самообмана, где модель подогнана под прошлое и уверенно ошибается в будущем.
Дальше — Моделирование и его пределы: что модель не покажет.