Какие правила переживут тех, кто их придумал

1. Вопрос, который не задают

Любая система правил со временем разрастается. Регламент разработки, инструкция для цеха, порядок выпуска релиза, правила приёмки — всё это растёт одинаково: случается неприятность, после неё пишется правило, правило остаётся. Через три года в документе сорок пунктов, и никто не помнит, какие из них защищают от реальной опасности, а какие — от человека, который давно уволился, или от программы, которую давно заменили.

Обычный способ борьбы с этим — «давайте упростим». Он плох не потому, что упрощать не надо, а потому, что упрощающий не знает, что именно он выбрасывает. Правило «два человека проверяют расчёт» и правило «отчёт сдавать до четверга» выглядят одинаково — строчка в документе. Одно из них выведено из устройства мира, другое — из расписания бухгалтерии 2019 года. Выбросить второе — обычная уборка. Выбросить первое — ошибка, которая проявится позже, когда исправлять её будет дорого.

Так что вопрос стоит не «какие правила убрать», а другой, более точный: какие правила в принципе не могут устареть, пока существует сама задача? Такие правила я буду называть онтологическими константами — не потому, что слово красивое, а потому, что оно точное: они следуют из того, что есть задача, а не из того, кто и чем её сегодня выполняет.

Дальше — несколько историй, каждая стоила кому-то денег, репутации или жизней, и каждая показывает одну константу. А в конце — простой тест, который можно применить к любому пункту любого регламента.

===

2. Три вопроса

Прежде чем истории — инструмент. Чтобы отличить константу от временного правила, достаточно трёх вопросов.

Из какого свойства задачи это следует?

Если правило вытекает из неустранимого свойства самой работы — например, из того, что часть действий необратима, или из того, что исполнителю нельзя заглянуть в голову, — оно останется, пока остаётся работа. Если правило вытекает из свойства сегодняшнего исполнителя или инструмента — из того, что станок греется, программа теряет настройки при перезапуске, новичок путает единицы измерения, — оно уйдёт вместе с исполнителем. Второе не хуже первого. Просто у него есть срок годности, и его надо знать.

Переживёт ли правило замену исполнителя и замену инструмента?

Представьте, что завтра всех людей в процессе заменили на других людей, а все программы — на другие программы. Какие правила вы бы переписали, а какие оставили слово в слово? Оставленные — кандидаты в константы.

Это принцип или его сегодняшняя форма?

У большинства правил постоянен принцип, а форма сменится. «Подпись руководителя на приказе» — форма; «решение должно быть невозможно подделать задним числом» — принцип. Форма менялась от сургучной печати до электронной подписи; принцип не менялся с тех пор, как появились приказы.

Один побочный вывод из этих вопросов неприятен: дорогое и раздражающее правило не становится от этого временным. Наоборот, самые устойчивые правила обычно и самые неудобные: их вводили после инцидентов, и каждый следующий инцидент их подтверждал. А правило, которое все любят, может быть временным, если оно лечит сегодняшний симптом.

===

3. Заявить дешевле, чем доказать

Аппарат, который говорил «всё в порядке»

В середине 1980-х в США и Канаде работал медицинский аппарат лучевой терапии Therac-25. Его предшественники имели механические блокировки: если что-то в положении узлов было не так, физический замок не давал включить излучение. В новой модели от замков отказались — за безопасность отвечала программа. Программа проверяла состояние и сообщала оператору, что всё нормально.

В период с 1985 по 1987 год как минимум шесть пациентов получили дозы, многократно превышающие терапевтические; несколько погибли. Причина — классическая гонка в коде: если оператор быстро правил параметры на экране, программа успевала «увидеть» старое состояние и выдать разрешение. На экране при этом был сигнал, который оператор принимал за безобидный.

Урок, который из этого извлекла вся инженерия безопасности, звучит просто: самоотчёт исполнителя не является доказательством. Программа, которая проверяет сама себя и сама себе разрешает действие, не обеспечивает контроля: это одно и то же суждение, повторённое дважды. Механический замок был плох не потому, что он механический, а хорош потому, что он независим от программы и по умолчанию закрыт: нет подтверждения — нет луча.

---

Резервные копии, которых не было

31 января 2017 года инженер крупного сервиса для разработчиков, уставший после долгого инцидента, выполнил удаление данных не на том сервере. Потеряно было около шести часов пользовательской работы — не катастрофа по меркам отрасли. Катастрофой было другое: у компании было пять разных механизмов резервного копирования, и, как выяснилось в ту ночь, ни один из них не работал так, как предполагалось. Копии либо не создавались, либо создавались в несовместимом формате, либо уведомления об ошибках уходили в никуда.

Пять механизмов, ноль работающих. Все пять «сообщали», что работают, — в том смысле, что никто не получал сообщений о сбоях. Отсутствие сообщений об ошибках принимали за подтверждение работоспособности.

Это та же константа, что у Therac-25, только с другой стороны: отсутствие доказательства — это отказ, а не «вероятно, нормально». Резервная копия, которую не восстанавливали, — не копия. Тест, который не запускали, — не тест. Отчёт о пройденной проверке без самой проверки — это утверждение, а не свидетельство.

---

Старое правило, которое стоило бы помнить

Эти истории были бы менее удивительны, если бы отрасль читала собственную классику. В 1975 году два исследователя из MIT, Джером Зальцер и Майкл Шрёдер, опубликовали восемь принципов защиты информации. Первый из них — fail-safe defaults: по умолчанию доступ закрыт, разрешение должно быть явным и доказанным. В 2022 году вышла ретроспектива двух крупнейших инцидентов десятилетия — компрометации цепочки поставок SolarWinds и уязвимости Log4Shell — с простым выводом: оба инцидента объясняются нарушением тех самых принципов 1975 года, и ни один из принципов не потребовалось переписывать.

Принципы, которые за пятьдесят лет не потребовали пересмотра, — сильные кандидаты в константы.

Константа 1. Нет доказательства — нет действия. Самоотчёт исполнителя не доказательство. Форма доказательства (замок, подпись, хэш, тест) будет меняться; требование — нет.

===

4. Полномочие — это то, что держишь, а не то, что говоришь

Сорок пять минут и четыреста миллионов

1 августа 2012 года торговая фирма Knight Capital, один из крупнейших участников американского рынка акций, за сорок пять минут потеряла около 440 миллионов долларов и перестала существовать как независимая компания. Никто не взламывал систему. Инженеры выкатывали обновление торгового модуля на восемь серверов и на один из них по ошибке не выкатили.

Дальше — цепочка, которая стоит того, чтобы её проследить. В обновлении повторно использовали флаг конфигурации, который много лет назад включал старую тестовую функцию — она давно не использовалась, но код её остался. На семи серверах флаг включал новую функцию. На восьмом, где стоял старый код, тот же флаг включил старую — и старая функция начала выставлять заявки на рынок по логике, предназначенной для тестовой среды девятилетней давности.

Здесь не одна ошибка, а три константы сразу. Первая: мёртвый код сохраняет живые полномочия. Функция, которой «никто не пользуется», всё ещё умеет торговать, и ей всё ещё можно случайно дать команду. Вторая: одно и то же слово — флаг — означало разное на разных машинах, то есть имя полномочия и само полномочие разошлись. Третья: откат не был единицей: обновление ставилось по серверам, а откатить надо было бы всё сразу, но первые минуты команда, наоборот, откатывала новый код, тем самым «чиня» семь серверов до состояния восьмого.

---

Шестьдесят лет одной идеи

В 1966 году Джек Деннис и Эрл Ван Хорн описали модель, которую потом назвали capability-based security, «безопасность на основе способностей». Её суть помещается в одну фразу: право на действие — это неподделываемый предмет, который можно только держать или передать, но нельзя назвать. Нельзя получить доступ, сказав «я администратор»; можно — предъявив то, что подделать невозможно. У этой модели было много воплощений, от операционных систем до современных песочниц для кода, и она не устарела, потому что опирается на простое различие: утверждение можно повторить без затрат, а неподделываемый объект нужно предъявить.

В языке современных систем «неподделываемый предмет» — это, например, контрольная сумма: число, которое вычисляется из самих байтов документа и меняется от любой правки. Полномочие, привязанное к контрольной сумме, нельзя перенести на «похожий» документ. Полномочие, выраженное словами («разрешаю выкатить обновление»), переносится на что угодно — в том числе на восьмой сервер.

---

Экономия механизма

Восемь принципов 1975 года содержат ещё один, который реже цитируют: economy of mechanism — механизм должен быть настолько простым и маленьким, насколько возможно. Не из эстетики: каждый лишний механизм — это ещё одно место, где полномочие может оказаться не там, где его ищут. История Knight Capital — это история о механизме (старой функции), который никому не был нужен и у которого никто не отобрал права. Ретроспектива SolarWinds и Log4j называет economy of mechanism среди четырёх решающих нарушений в обоих случаях.

Это неудобная константа, потому что она требует не добавлять, а убирать, а убирать всегда рискованнее. Но следствие из неё практичное: у каждого механизма должна быть дата, после которой его существование нужно заново обосновать. Не удалить, а обосновать. Опыт показывает, что большинство механизмов такого обоснования не получает.

Константа 2. Полномочие привязывается к тому, что нельзя подделать, а не к словам; у мёртвого механизма отбираются права; механизмов должно быть столько, сколько функций, и не больше.

===

5. Тот, кто сделал, не принимает

Самолёт, который был «слишком сложен для одного человека»

30 октября 1935 года на испытаниях нового бомбардировщика Boeing Model 299 — будущей «Летающей крепости» — самолёт разбился сразу после взлёта. Экипаж во главе с одним из самых опытных лётчиков армии забыл снять блокировку рулей. Самолёт был лучше конкурентов по всем параметрам, и первая реакция комиссии была честной: он слишком сложен, чтобы им мог управлять человек.

Решение, которое нашли пилоты, оказалось одним из самых долгоживущих в истории управления: контрольный список. Не «быть внимательнее» и не «нанять лучших» — список, по которому второй человек вслух проверяет первого. Самолёт остался таким же сложным; изменилось одно: проверка перестала зависеть от памяти того, кто выполняет действие.

Через девяносто лет чек-листы — обязательная часть авиации, хирургии, атомной энергетики. Их форма менялась много раз. Принцип — действующий не проверяет сам себя — не менялся ни разу.

---

Нормализация отклонения

28 января 1986 года шаттл «Челленджер» разрушился через 73 секунды после старта из-за прогара уплотнительного кольца в холодную погоду. Социолог Диана Воган, изучив документы, ввела термин, который с тех пор используют далеко за пределами космонавтики: нормализация отклонения. Кольца прогорали и раньше, в нескольких полётах, но каждый раз полёт заканчивался благополучно — и каждый благополучный исход становился «доказательством» того, что прогар допустим. Прошлые успехи стали использоваться как основание для разрешения.

Это зеркальная сторона чек-листа. Проверять должен не только другой человек; проверять должно текущее состояние, а не история. Прошлый успех не является свидетельством о сегодняшней безопасности. Девять удачных стартов не доказывают, что десятый безопасен: они говорят только о том, что в девяти случаях условия оказались допустимыми.

---

Уровни доверия

В 2021 году отрасль разработки формализовала эту константу в виде шкалы — стандарта защищённости цепочки поставок программ. На нижнем уровне исполнитель сам сообщает, как собрал продукт; стандарт прямо говорит, что такой отчёт «не защищает от подделки». На верхнем уровне требуются два независимых человека на каждое изменение и сборка в изолированной среде, где список зависимостей гарантированно полон. Между ними — ступени, на каждой из которых доверие к заявлению исполнителя заменяется проверкой кем-то другим.

Константа 3. Принимает результат не тот, кто его произвёл. Проверяется текущее состояние, а не история успехов. Число проверяющих и форма проверки — изменяемы; факт независимости — нет.

===

6. Одно событие — одно действие, один источник правды

Орбитальный аппарат и два набора единиц

В сентябре 1999 года американский зонд Mars Climate Orbiter сгорел в атмосфере Марса, подойдя к планете на 57 километров вместо расчётных 150 с лишним. Одна команда передавала данные об импульсах двигателей в фунт-секундах, другая считала их ньютон-секундами. Обе стороны работали правильно — по своим документам. Не существовало одного места, где было бы записано, в каких единицах измеряется эта величина, и не существовало проверки на стыке.

Суть этой истории не в единицах измерения. Это история про две копии одной величины, которые неизбежно разошлись, потому что ни одна из них не была назначена главной.

---

Платёж, который нельзя провести дважды

Любой, кто проектировал платёжную систему, знает задачу: клиент нажал «оплатить», связь оборвалась, ответ не пришёл. Платёж прошёл или нет? Если повторить запрос — можно снять деньги дважды. Если не повторять — можно не снять вовсе. Отраслевое решение называется ключом идемпотентности: каждому намерению заплатить присваивается уникальный ключ, и сколько бы раз ни пришёл запрос с этим ключом, сервер выполнит его один раз, а остальные разы вернёт сохранённый результат. Так работают все крупные платёжные интерфейсы.

Важен сдвиг, который здесь произошёл. Система считает не запросы, а события: один клиент, один раз нажал. Сколько документов (запросов, писем, отчётов) об этом событии существует — неважно. Событие и запись о событии — разные вещи, и считать надо события. Та же логика в управлении: один инцидент, о котором написали пять отчётов, — один инцидент. Один отчёт о пяти инцидентах — пять.

---

Одна точка, которая знает, зачем

В 1984 году те же Зальцер и его коллеги сформулировали «сквозной аргумент» (end-to-end argument), который с тех пор лежит в основе проектирования сетей: проверку правильности можно по-настоящему сделать только в той точке, которая знает, что считается правильным. Промежуточные звенья могут проверять что-то своё — это полезно как оптимизация, но не как гарантия. Файл, переданный по сети, проверяет на целостность получатель, который знает, что он ждал, — а не каждый маршрутизатор по дороге.

Для управления это переводится так: итоговую приёмку делает тот, кто знает требование, по тому самому результату, который передают, — а не по похожему. Проверка «черновика, который почти такой же» ничего не гарантирует о чистовике.

Константа 4. Один источник правды на каждую величину; одно событие — одно действие; окончательная проверка — у того, кто знает требование, на том, что реально передаётся.

===

7. Бюджет вместо нуля

Почему сто процентов — неправильная цель

Когда крупные интернет-компании в 2000-х учились держать сервисы, работающие круглосуточно, они столкнулись с конфликтом, который знает каждый руководитель: разработчики хотят выпускать быстрее, эксплуатация хочет, чтобы ничего не ломалось. Переговоры между ними — бесконечны, потому что у сторон нет общей меры.

Решение, которое позже описали в книге по инженерии надёжности, оказалось контринтуитивным: сто процентов надёжности — почти никогда не правильная цель. Вместо этого задаётся допустимая доля отказов — «бюджет ошибок» — и он становится общей валютой. Пока бюджет не исчерпан, выпускаем. Исчерпан — выпуск останавливается, и у разработчиков появляется собственный интерес вложиться в тестирование. Никто не спорит, потому что число измеряет система, а не одна из сторон. А если бюджет исчерпывается каждый квартал, пересматривают не людей, а саму цель.

Почему это константа, а не приём? Потому что она следует из двух неустранимых свойств: ресурсы конечны и часть действий необратима. Система, в которой необратимое действие можно повторять без учёта, рано или поздно повторяет его до катастрофы; в случае Knight Capital это заняло сорок пять минут непрерывных повторений. Любая система, где отказ запрещён вовсе, останавливается навсегда.

Числа в бюджете — 0,1 %, двадцать попыток, три повтора — будут меняться всегда. Сам институт бюджета — нет.

Константа 5. У необратимого действия есть явный лимит попыток и явная точка возврата. Лимит — общая мера для всех сторон, а не наказание.

===

8. Что точно устареет

Теперь о другой половине — о правилах, у которых есть срок годности. Их не меньше, и они не хуже; просто про них надо знать, что они временные.

Правила, которые компенсируют слабости сегодняшнего исполнителя. Условный пример: в инструкции цеха есть пункт о защите от сквозняков, введённый когда-то из-за деревянных шаблонов, которые коробило; шаблоны давно металлические, а пункт остаётся, потому что никто не записал, зачем он был нужен. Сегодняшний аналог: правила, которые компенсируют известные слабости конкретных программ, конкретных моделей, конкретных версий. Они необходимы ровно до тех пор, пока существует слабость, — и имеют свойство переживать её на десятилетия, потому что никто не записал, почему они появились.

Числа. Любой порог — двадцать, пять процентов, три дня — это форма. Принцип «порог есть» — константа; его значение — всегда временное.

Роли в сегодняшнем составе. «Проверяет начальник смены» — форма принципа «проверяет не тот, кто делал». Когда сменится структура, проверять будет кто-то другой, и это не отмена правила.

Носители. Журнал в тетради, журнал в таблице, журнал в базе — всё формы. Содержание журнала («одно событие — одна запись, с датой и свидетелем») переживёт их все.

Есть и общий закон, который всё это предсказывает. В 1970-х Мэир Леман сформулировал законы эволюции программ, два из которых подтверждаются на всех изученных с тех пор системах: любая используемая система непрерывно меняется, и её сложность непрерывно растёт, если не тратить специальных усилий на её снижение. Отсюда следует вывод, который полезно принять заранее: ни одна форма правила не вечна. Это не предмет спора, а условие, которое надо учитывать при планировании.

И есть эвристика, помогающая отличать одно от другого без долгих размышлений, — её называют эффектом Линди: чем дольше идея уже существует, тем дольше она, вероятно, просуществует ещё. У пяти констант из этой статьи отраслевые корни возрастом от десяти до шестидесяти лет. У правил, которые лечат сегодняшний инструмент, — год-два, или корней нет вовсе. Это не доказательство, но это дешёвый первый фильтр: найдите, из чего выросло правило, и посмотрите, сколько этому лет.

===

9. Конституция и регламент

Из всего сказанного следует практика, которая стоит недорого и экономит много споров.

Правила стоит хранить в двух разных документах с разными режимами изменения. В первом — константы: короткий список принципов, которые следуют из устройства задачи и не меняются волнами, релизами и реорганизациями. У каждого — одна строка «из чего следует». Этот документ меняют редко и с опасением. Во втором — регламент: формы, числа, роли, носители. У каждого пункта — три поля: какой принцип он реализует, какова его сегодняшняя форма и при каком условии его следует снять. Последнее поле — самое важное и самое редкое. Правило «после каждого инцидента с программой X перезапускать Y» должно нести пометку «действует, пока используется X». Тогда снятие правила становится штатным событием, а не спором о том, «устарело ли».

Три вопроса из второй главы — это и есть процедура заполнения этих полей. Их можно задавать при введении любого нового пункта, и это не гейт, а строка в описании. Она ничего не запрещает. Она только требует от автора правила один раз определить, записывает он свойство задачи или текущие обстоятельства.

Пять констант, к которым сходятся истории выше, можно уместить на одной карточке:

1. Нет доказательства — нет действия; самоотчёт не доказательство.
2. Полномочие — это то, что нельзя подделать, а не то, что можно сказать; мёртвый механизм лишается прав; механизмов не больше, чем функций.
3. Принимает не тот, кто делал; проверяется текущее состояние, а не история успехов.
4. Один источник правды; одно событие — одно действие; итоговая проверка у того, кто знает требование.
5. У необратимого — лимит и точка возврата, общие для всех сторон.

Во всех описанных случаях их нарушали опытные и добросовестные специалисты. Именно поэтому их стоит записать отдельно от остальных правил: не как чьё-то решение, а как свойства задачи, подтверждённые дорогими ошибками.


Рецензии