Что считать системой: элементы, связи, назначение
Слово «система» в инженерной речи почти ничего не значит. Системой называют монолит и набор микросервисов, процесс код-ревью и таблицу в Confluence, компанию и очередь сообщений. Когда слово применимо ко всему, оно перестаёт различать — а различение и есть единственная причина заводить термин.
Эта глава задаёт рабочее определение, которым можно пользоваться как инструментом: приложить к объекту, получить ответ «да / нет / не хватает данных» и понять, чего ожидать от поведения. Из определения сразу следуют предсказания, проверяемые логами и метриками; там, где предсказаний не следует, я это отмечаю прямо. Системное мышление легко превращается в производство схем, которые красиво выглядят и ничего не запрещают, — это его главный профессиональный риск, и разбираться с ним надо с первой главы.
Карта трека — в обзоре. Здесь важна одна разграничительная линия. Трек про логику занимается строгостью вывода: следует ли заключение из посылок. Системное мышление — тем, как ведёт себя целое во времени, когда все локальные шаги логичны, а результат противоположен намерению. Логика проверяет рассуждение, системная модель проверяется данными.
Определение: три составляющие
Определение, ставшее в дисциплине стандартным, дала Донелла Медоуз в «Thinking in Systems: A Primer» (2008):
Система — это набор элементов, связанных между собой так, что их взаимодействие порождает собственное устойчивое поведение.
- Элементы — то, из чего система состоит. Обычно их видно: сервисы, воркеры, таблицы, очереди, дежурные, тикеты, люди в команде.
- Взаимосвязи — кто на кого влияет, через что, с какой задержкой и по каким правилам. Видно хуже: половина связей не описана нигде, а живёт в привычках и конфигах.
- Назначение — что система устойчиво производит. Видно хуже всего: его почти никогда не проговаривают вслух, а декларации расходятся с фактом.
Порядок на схеме не случаен. Элементы менять легче всего и это меняет поведение реже всего; назначение меняют почти никогда, а меняет оно всё. Отсюда следствие, к которому трек вернётся в главе о точках воздействия: большинство попыток «починить систему» бьёт по верхнему слою, потому что он единственный доступен без разговора с людьми.
Пример — асинхронная обработка заказов. Элементы: API-эндпоинт, брокер, пул из 20 воркеров, база, клиентское приложение, автоскейлер, алерт на длину очереди, дежурный. Связи: клиент шлёт запрос → эндпоинт кладёт сообщение в очередь → воркер забирает и пишет в базу; клиент ждёт 2 секунды и повторяет; автоскейлер добавляет воркеров, если очередь держится выше порога 5 минут; алерт будит дежурного через 15 минут. Назначение: заявленное — «обработать все заказы»; фактическое — «не потерять заказ ценой любой задержки», потому что ретраи бесконечны, TTL сообщения не задан, таймаута обработки нет.
Заметьте: фактическое назначение мы прочитали не из документа, а из конфигурации. Это общий приём.
Тест на систему: три вопроса
Куча деталей — не система. Отличить можно тремя грубыми, но работающими проверками.
1. Заменим элемент — поведение сохранится? Если да, система существует и элемент в ней не определяющий. Замените все 20 воркеров на другие инстансы — очередь ведёт себя так же. Замените половину команды — процесс релиза в первый месяц будет тем же, потому что его держат правила и связи. Если поведение исчезает при замене одного элемента, вы смотрели не на систему, а на этот элемент с окружением.
2. Переставим связи, оставив элементы — поведение изменится? Тот же набор сервисов, но ретрай перенесён с клиента на шлюз с бюджетом попыток — и метастабильного отказа больше нет. Ничего не добавили и не убрали. Если перестановка связей ничего не меняет, элементы независимы: перед вами набор, а не система.
3. Есть ли что-то, что целое устойчиво производит? Если объект не производит ничего повторяемого, у него нет назначения, и говорить о его «поведении» бессмысленно. Ящик с болтами не система: болты не взаимодействуют.
Сведём в картинку: по горизонтали — насколько части влияют друг на друга, по вертикали — есть ли устойчиво воспроизводимый результат.
Правый нижний квадрант — самый неприятный. Части плотно связаны, работы много, устойчивого результата нет: планёрки, дашборды, отчётность, которая никуда не ведёт. Формально система есть, но её назначение — воспроизводить саму себя. Это не риторика, а проверяемое утверждение: отмените ритуал на два спринта и посмотрите, изменится ли хоть одна наблюдаемая метрика.
Левый верхний квадрант — ловушка атрибуции: результат стабилен, но производит его не то, на что вы смотрите. Команда внедрила процесс, в тот же квартал выросла конверсия, а сработал сезон. Логическая сторона ошибки — в главе о причинных и статистических ошибках; системная — в том, что поведение приписано не той системе из-за неверно проведённой границы.
Назначение: самое незаметное и самое сильное
С элементами и связями инженеры работают каждый день. Назначение пропускают — и именно из-за него системные разборы чаще всего расходятся с реальностью.
Полезная формулировка принадлежит Стаффорду Биру: назначение системы — это то, что она делает (POSIWID, «The Heart of Enterprise», 1979). С ней надо быть аккуратным: прочитанная буквально, она тавтологична и потому неопровержима — что бы система ни делала, объявим это её целью. Как аргумент она ничего не стоит. Как эвристика поиска работает: не спрашивайте людей о намерениях, смотрите, что система защищает, когда ресурсов не хватает на всё.
| Ситуация конфликта | Что выбрали | Фактическое назначение |
|---|---|---|
| Очередь растёт, ретраи усугубляют | Не отбрасывать сообщения, терпеть задержку | «Не потерять заказ любой ценой» |
| Релиз готов, упал флейки-тест | Выкатили, тест замьютили | «Не задерживать релиз» |
| Инцидент закрыт, постмортема нет | Закрыли задачу, разошлись | «Восстановить сервис», не «понять причину» |
| Ревью висит 3 дня, автор торопится | Апрув «на доверии» | «Не блокировать поток», не «найти дефекты» |
| Дежурный завален алертами | Порог поднят, алерт замьючен | «Спать ночью», не «замечать деградации» |
Ни одна строка сама по себе не приговор: «не задерживать релиз» — законное назначение, если выбрано осознанно. Проблема начинается, когда декларируется одно, а система настроена на другое. Тогда улучшения бьются о невидимое ограничение: вы поднимаете качество ревью, а система устроена так, чтобы ревью не задерживало поток, — и она вернёт всё обратно.
Отсюда первое проверяемое утверждение главы:
Гипотеза. Если декларируемое назначение расходится с фактическим, локальные улучшения под декларируемое назначение затухают за 1–3 итерации. Проверка. Возьмите три инициативы последнего года («ускорить ревью», «чинить флейки», «писать постмортемы»), найдите момент внедрения в истории репозитория и метрику, которую они должны были двигать; постройте её на 6 месяцев вперёд. Возврат к прежнему уровню — гипотеза выдержала проверку на ваших данных. Что опровергнет. Устойчивое улучшение без изменения правил приоритизации.
Это ещё не доказательство: выборка мала, объяснений может быть несколько. Но это уже измерение, а не рассуждение, — и в этом вся разница между системной моделью и красивой схемой.
Первый разбор: очередь, которая не восстанавливается
Средняя нагрузка 90 запросов в секунду, пул держит 100 — запас 10%. Всплеск на 30 секунд поднимает нагрузку до 160, потом всё возвращается к 90. Восстановится ли сервис сам? Интуиция говорит «конечно, нагрузка же вернулась». Системная модель отвечает: зависит от того, есть ли петля ретраев.
Здесь две петли. Q → S → Q со знаком минус — уравновешивающая: чем длиннее очередь, тем больше работы
из неё уходит, очередь сама себя укорачивает. A → Q → W → T → R → A — все связи положительные, петля
усиливающая: рост порождает рост. Правило чтения знаков: чётное число минусов в контуре — усиливающая
петля, нечётное — уравновешивающая. Подробно петли — в главе 03,
различие «запас против потока» — в главе 04; здесь достаточно
того, что очередь — это запас, а не поток, и она помнит прошлое.
Проверим численно. Модель намеренно грубая: шаги по секунде, ожидание оценивается по закону Литтла как
W = L / λ, клиент делает один повтор, если ожидание превысило таймаут.
from dataclasses import dataclass
@dataclass
class Params:
arrival: float = 90.0 # запросов в секунду в норме
capacity: float = 100.0 # запросов в секунду, которые вытягивает пул
timeout: float = 2.0 # секунд ждёт клиент до повтора
retries: float = 1.0 # сколько повторов делает клиент
burst_from: float = 60.0 # начало всплеска, секунда
burst_to: float = 90.0 # конец всплеска, секунда
burst_arrival: float = 160.0 # нагрузка во время всплеска
def simulate(p: Params, seconds: int = 600, with_retries: bool = True):
"""Дискретная модель очереди с петлёй клиентских ретраев.
Возвращает историю (t, длина очереди, оценка ожидания).
Сложность: O(seconds) по времени и памяти; O(1) по памяти, если не копить историю.
"""
queue = 0.0
history = []
for t in range(seconds):
base = p.burst_arrival if p.burst_from <= t < p.burst_to else p.arrival
wait = queue / p.capacity # закон Литтла: W = L / λ
# клиент повторяет запрос, только если уже ждал дольше таймаута
retry = base * p.retries if (with_retries and wait > p.timeout) else 0.0
inflow = base + retry # поток «в» запас
outflow = min(queue + inflow, p.capacity) # поток «из», ограничен пулом
queue = queue + inflow - outflow # запас = запас + приток − отток
history.append((t, queue, wait))
return history
| Момент | Без ретраев | С ретраями |
|---|---|---|
| t = 89 с (конец всплеска) | очередь 1800, ожидание 17 с | очередь 5960, ожидание 57 с |
| t = 120 с | очередь 1490, спадает | очередь 8440, растёт |
| t = 269 с | очередь 0, сервис в норме | очередь ~20 400, растёт |
| t = 599 с | очередь 0 | очередь ~46 800, ожидание 467 с |
Без ретраев система восстанавливается за 269 секунд после тридцатисекундного всплеска — уже интересно: причина исчезла за три минуты до того, как исчезло следствие. С ретраями система не восстанавливается никогда, хотя внешняя нагрузка вернулась к 90 из 100. Причина видна прямо в модели: 90 исходных плюс 90 повторных — это 180 против ёмкости 100, очередь растёт на 80 в секунду. Петля ретраев стала источником нагрузки, которая поддерживает сама себя.
Это не выдумка ради примера: явление известно как метастабильный отказ и описано на реальных системах в Bronson et al., «Metastable Failures in Distributed Systems» (HotOS 2021, PDF). Средства против него — бюджеты ретраев, jitter, circuit breaker, load shedding — разобраны в паттернах устойчивости и в моделях отказов.
Что здесь сделала системная модель: не назвала новое лекарство, а объяснила, почему восстановление не наступает само, и указала, куда смотреть — на контур, а не на элемент. Инстинкт «добавим воркеров» лечит симптом: при ёмкости 200 очередь рассосётся, но петля останется и сработает при всплеске побольше.
Переход Meta → Meta — главное на диаграмме. У системы два устойчивых режима при одной и той же входной
нагрузке, и в какой из них она попадёт, зависит от истории. Это уже про
нелинейность и пороги, но эффект виден уже из трёхкомпонентного
определения: у запаса есть память, у петли — знак.
Элементы менять легко, связи трудно, назначение почти невозможно
Замена элементов почти не меняет поведение. Заменили брокер, переписали сервис на другом языке, поменяли половину команды — если связи и назначение те же, система возвращается к прежнему поведению. Отсюда знакомое «переписали с нуля, а через год те же проблемы».
Перестройка связей меняет поведение резко. Перенос ретрая из клиента в шлюз убирает усиливающую петлю. Правило «алерт без владельца удаляется через месяц» меняет поведение дежурства сильнее, чем найм двух инженеров.
Это утверждение доводимо до проверяемого вида. Гипотеза Конвея — структура системы повторяет структуру коммуникаций создавшей её организации («How Do Committees Invent?», 1968, текст) — десятилетиями жила как афоризм, пока MacCormack, Rusnak и Baldwin не сравнили парные продукты, сделанные распределёнными сообществами и колокированными командами, и не нашли систематическую разницу в модульности в предсказанную сторону (Research Policy, 2012, препринт HBS). Это не эксперимент, контроля над отбором нет, но это данные, а не афоризм.
Смена назначения меняет всё, но её почти никогда не делают явно. Фраза «мы оптимизируем время до восстановления, а не количество инцидентов» — это смена назначения, и из неё следуют другие алерты, другие постмортемы, другой найм. Организационная сторона такого выбора — в главе про техдолг.
Система, подсистема, надсистема
Одно и то же можно рассматривать как элемент или как систему — в зависимости от вопроса: воркер — элемент очереди, очередь — система для команды платформы, платформа — элемент продукта, продукт — элемент бизнеса.
Полезное свойство таких иерархий описал Герберт Саймон в «The Architecture of Complexity» (1962, JSTOR): устойчивые сложные системы, как правило, почти разложимы — взаимодействия внутри подсистемы сильнее и быстрее, чем между подсистемами. Поэтому можно анализировать очередь, не моделируя биржу труда, и поэтому граница по «сильным быстрым связям» обычно даёт рабочую модель. Идея та же, что за ограниченными контекстами в DDD, только сформулированная про поведение, а не про модель предметной области.
Оговорка: почти разложимость — эмпирическое наблюдение, а не закон. Бывают системы, где слабая редкая связь решает всё: общая база у двух «независимых» сервисов, один сеньор, через которого идут все решения, общий пул соединений. Такие связи рвут модель — и именно их пропускают, когда рисуют схему по оргструктуре.
Что системой не является
Набор без взаимодействия. Список из 40 сервисов в вики — инвентарь. Он станет системой, когда вы добавите, кто кого вызывает и что происходит при отказе.
Поток без запаса. Если между частями ничего не накапливается (очередь, бэклог, долг, усталость, недоверие), интересной динамики не будет: выход мгновенно следует за входом. Запасы — источник инерции, а инерция — источник неожиданностей.
«Система» как синоним «сложно». Сложность не делает объект системой, а система не обязана быть сложной: термостат — система из трёх элементов, и он показывает всё интересное сразу.
Оргсхема. Она показывает подчинение, а не влияние. Реальные связи — кто кого зовёт при инциденте, чей апрув обязателен фактически, кто владеет общей базой. Как их собирать, разбирает глава про стейкхолдеров; там же — про нотации вроде BPMN, которые описывают процесс как он задуман. Системная модель нужна для другого — для поведения как оно есть.
Где модель проверяема, а где нет
Схема со стрелочками убедительна ровно настолько, насколько ничего не запрещает, — а неопровержимое объяснение бесполезно. Общая методология проверки гипотез разобрана в главе о научном и инженерном рассуждении; здесь — что можно требовать от системной модели.
Уровень 1. Предсказание знака. «При агрессивном ретрае без бюджета и всплеске выше 100% ёмкости очередь не вернётся к нулю после спада нагрузки». Проверяется нагрузочным тестом за час, запрещает наблюдаемый исход.
Уровень 2. Предсказание формы поведения. «После найма трёх инженеров скорость команды сначала упадёт и вернётся не раньше квартала». Форма — провал и восстановление — проверяется по трекеру; величина провала нет.
Уровень 3. Предсказание времени и величины. «Очередь восстановится за 269 секунд». В модели да, в реальности нет: числа зависят от распределения времени обработки, поведения клиентов, работы автоскейлера. Точное число здесь артефакт модели. Как отличать одно от другого — тема главы про моделирование и его пределы.
Уровень 0, непроверяемое. «Организация — живой организм, и техдолг — это её усталость». Метафора не запрещает ничего; из неё не следует ни одного наблюдения, которое могло бы её опровергнуть.
Рабочее правило: нарисовали схему — сформулируйте, какое наблюдение её опровергнет. Не нашли — вы нарисовали не модель, а иллюстрацию к своей интуиции; для разговора она полезна, за анализ выдавать нельзя. Второй способ проверки — сверка с уже измеренным: если модель очереди противоречит закону Литтла или базовой теории массового обслуживания, ошибка в модели, а не в теории (про измерения и их подводные камни — «Измерения»).
Честно про доказательную базу
Системная динамика выросла из работ Джея Форрестера в MIT: «Industrial Dynamics» (1961) — производственные цепочки, «Urban Dynamics» (1969) — города, «World Dynamics» (1971) — глобальные ресурсные ограничения. Донелла Медоуз сделала подход популярным: «The Limits to Growth» (1972, Club of Rome) и посмертный «Thinking in Systems» (2008). Учебник дисциплины — John Sterman, «Business Dynamics» (2000).
Есть воспроизводимый эксперимент. Beer Distribution Game — лабораторная цепочка поставок из четырёх звеньев с задержками. Стерман показал в «Modeling Managerial Behavior» (Management Science, 1989, DOI), что участники систематически переоценивают заказы, не учитывая уже отправленный, но не пришедший товар, — колебания возникают из структуры, а не из глупости игроков. Эксперимент повторяли десятилетиями на тысячах участников с устойчивым результатом. Это самое твёрдое, что есть в дисциплине, и это прямой аналог инженерных ситуаций с задержками — им посвящена глава 05.
Есть серьёзная критика моделей. Уильям Нордхаус в рецензии «World Dynamics: Measurement Without Data» (The Economic Journal, 1973, JSTOR) указал главное: уравнения содержат десятки коэффициентов, подобранных без эмпирической оценки, а поведение модели к ним чувствительно. Сборник «Models of Doom» (Cole, Freeman, Jahoda, Pavitt, 1973) показал, что при других допущениях о темпе технологического прогресса коллапс из модели исчезает. Отдельная претензия — что «Urban Dynamics» давала рекомендации по городской политике на модели, которая с городскими данными не сверялась.
Есть попытки сверки с реальностью, и они спорны. Грэм Тёрнер (Global Environmental Change, 2008, DOI) сопоставил сценарий «business as usual» с данными 1970–2000 и нашёл согласие по ряду агрегатов. Критики отвечают, что согласие на тридцатилетнем горизонте по медленно меняющимся агрегатам — слабый тест: сценарии расходятся позже, а сама книга подчёркивала, что это сценарии, а не прогнозы.
Вывод для инженера. Системная динамика — это язык для формулирования гипотез о поведении, а не машина предсказаний. Она хорошо отвечает на «какого рода поведение возможно при такой структуре» и «почему причина исчезла, а следствие осталось». Она плохо отвечает на «сколько именно» и «когда именно», если коэффициенты не измерены. Это не повод её не использовать — та же граница есть у любой модели с неоткалиброванными параметрами. Повод — не выдавать графики из модели за прогноз.
Отрезвляющее чтение с инженерной стороны: Richard Cook, «How Complex Systems Fail» (текст) — почему сложные системы всегда работают деградированными; и «Systemantics» Джона Голла (1975), откуда закон «сложная работающая система неизменно оказывается развитием простой работающей системы». Оба текста — наблюдения, а не исследования, и читать их надо соответственно.
Типовые ловушки
Подробно трек разбирает их в главах об архетипах, локальной оптимизации и причинных диаграммах — здесь важно узнавать их уже на этапе «что мы вообще описываем».
Описание вместо модели. Нарисовали все сервисы и все стрелки — получили карту архитектуры, а не модель поведения. Признак: на схеме нет ни одного запаса и ни одной петли. Модель отвечает на «что будет, если», а не на «что где лежит».
Оптимизация части в ущерб целому. Каждая команда улучшила свою метрику, сквозное время выросло. Классика — локальная утилизация: загрузили каждый узел на 90%, очереди перед узлами съели весь выигрыш. Опасность в том, что каждый шаг локально подтверждён данными.
Перенос проблемы. Симптом лечится обходным решением, обход обрастает процессом, процесс становится зависимостью. Инженерный вид: скрипт «перезапустить сервис при росте памяти» → он в кроне → на него алерт → на алерт регламент дежурного → через год про утечку никто не помнит, а в системе живёт подсистема обслуживания костыля. Признак: у обхода появился владелец и SLA.
Эскалация. Две стороны отвечают на действия друг друга усилением: команда A ставит ретраи, команда B — рейт-лимит, A увеличивает параллелизм, B ужесточает лимит. Каждый шаг рационален, контур усиливающий.
Трагедия общего ресурса. Общий пул соединений, общий кластер, общий эксперт. Потребитель выигрывает от своего роста и делит издержки со всеми, поэтому индивидуально рационально брать больше. Признак: ресурс общий, квоты нет.
Схема как аргумент. Самая коварная. Диаграмма выглядит убедительно, все кивают, решение принято — и никто не спросил, какое наблюдение её опровергло бы. Особенно опасно, когда схему рисует самый старший в комнате: разные участники видят разные системы, об этом — глава 08.
Практика: описать систему за 30 минут
В машиночитаемом виде — заготовка, которую удобно держать рядом с runbook:
system: "Асинхронная обработка заказов"
purpose:
declared: "Обработать все заказы за 5 секунд p99"
actual: "Не потерять заказ ценой любой задержки" # прочитано из конфигурации
evidence: "retries=infinite, ttl=none, dlq=отсутствует"
stocks: # то, что накапливается
- {name: "Очередь заказов", unit: "сообщений", normal: 0, observed_max: 46000}
- {name: "Незакрытые постмортемы", unit: "штук"}
flows:
- {from: "Клиент", to: "Очередь", rate: "90/с, всплески до 160/с"}
- {from: "Очередь", to: "База", rate: "100/с, ограничение пула"}
loops:
- {id: R1, kind: reinforcing, path: "очередь -> ожидание -> таймауты -> ретраи", trigger: "ожидание > 2 с"}
- {id: B1, kind: balancing, path: "очередь -> обработка -> очередь", limit: "ёмкость пула"}
delays:
- {what: "Автоскейлер", lag: "5 минут"}
- {what: "Пробуждение дежурного", lag: "15 минут"}
prediction: "После всплеска >100% ёмкости очередь не вернётся к нулю без вмешательства"
falsifier: "Очередь опустела сама в течение 10 минут после спада нагрузки"
check: "Нагрузочный тест 30 секунд на 160% ёмкости, наблюдать 20 минут"
Два поля важнее остальных — prediction и falsifier. Не удаётся заполнить — описание не превратилось в
модель, и честнее это признать, чем нести схему на архитектурное ревью; заполненные превращают спор в
эксперимент на час.
Порядок работы с нуля: (1) назовите поведение, которое хотите объяснить, — не «опишем систему», а «почему очередь не рассасывается»; (2) найдите запасы: очередь, бэклог, долг, незакрытые алерты, усталость — они скелет модели; (3) проведите границу — что внутри, что снаружи, что считаем константой (этому посвящена следующая глава); (4) ищите петли, а не стрелки — стрелка без обратного пути не объясняет динамику; (5) отметьте задержки: любая связь длиннее нескольких минут — кандидат в источник неожиданного поведения; (6) сформулируйте предсказание и опровержение и проверьте на данных, которые у вас уже есть. Полноразмерные разборы — инцидент, техдолг, найм, очередь — в главе 14; с чего начать практику и что читать дальше — в главе 15.
Мини-итог
- Система = элементы + связи + назначение; определение рабочее, потому что из него следуют проверяемые ожидания о поведении.
- Элементы менять почти бесполезно; связи менять трудно и это меняет поведение резко; назначение обсуждают редко, а определяет оно всё — и читается оно из выбора в конфликте ресурсов, а не из документов.
- Куча — не система: нужен и обмен влиянием между частями, и устойчиво воспроизводимый результат.
- Запас даёт системе память, петля даёт знак; вместе они объясняют, почему причина исчезает раньше следствия.
- Модель считается моделью, если сформулировано, какое наблюдение её опровергнет. Иначе это иллюстрация.
- Доказательная база неоднородна: лабораторные эффекты вроде beer game воспроизводимы, крупные модели вроде «Пределов роста» десятилетиями оспариваются по калибровке. Это язык гипотез, а не машина прогнозов.
Что дальше
Мы описали систему, но незаметно приняли ещё одно решение — выбрали, что считать внутренним, а что внешним. Очередь моделировали, поведение клиента нет; ёмкость пула считали константой. Каждое такое решение меняет вывод: при одной границе виноват всплеск, при другой — политика ретраев, при третьей — продуктовое решение о таймауте в мобильном приложении.
Границы системы: как выбор границы меняет вывод
Источники
- Donella H. Meadows. Thinking in Systems: A Primer. Chelsea Green, 2008; Leverage Points, 1999.
- Jay W. Forrester. Industrial Dynamics, 1961; Urban Dynamics, 1969; World Dynamics, 1971.
- Meadows et al. The Limits to Growth, 1972.
- William Nordhaus. World Dynamics: Measurement Without Data. The Economic Journal, 1973.
- Cole, Freeman, Jahoda, Pavitt (eds.). Models of Doom: A Critique of the Limits to Growth, 1973.
- Graham Turner. A Comparison of The Limits to Growth with Thirty Years of Reality. Global Environmental Change, 2008.
- John D. Sterman. Modeling Managerial Behavior. Management Science, 1989; Business Dynamics, 2000.
- Herbert A. Simon. The Architecture of Complexity. Proceedings of the APS, 1962.
- Melvin Conway. How Do Committees Invent?, 1968; MacCormack, Rusnak, Baldwin. Exploring the Duality Between Product and Organizational Architectures. Research Policy, 2012.
- Bronson et al. Metastable Failures in Distributed Systems. HotOS, 2021.
- Richard I. Cook. How Complex Systems Fail; W. Ross Ashby. An Introduction to Cybernetics, 1956.