Горящий маяк над тёмным опустевшим домом смотрителя в сумерках

Детектор отправляет компетенцию на пенсию

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

Read this in:English

Контейнер отказывается стартовать. Ошибка называет скрипт точки входа: no such file or directory. Скрипт существует. Он исполняемый. Он лежит прямо там, в образе, и его можно вывести в терминал и прочитать.

Кто-то тратит на этот скрипт полдня.

Скрипт никогда не был проблемой. Я видел, как этот отказ съедает полдня, и механизм хорошо известен. Конвертация переводов строк переписывает в файле каждый перенос, и первая строка теперь читается не как #!/bin/sh, а как #!/bin/sh плюс невидимый возврат каретки. Ядро идёт искать интерпретатор с таким именем, не находит его и сообщает об отказе, указывая на единственное имя файла, которое у него есть. Ошибка точна и бесполезна. Она указывает на файл, потому что отказал именно файл. Она не может указать на причину, потому что причиной была настройка в чьём-то окружении тремя шагами раньше.

Интересен вывод, который вы делаете в конце этих потерянных полдня.

Соблазнительный вывод — что разработчики обязаны знать про переводы строк. Опишите это. Добавьте в онбординг. Положите в вики, в раздел, который никто не открывает.

На самом деле починила это одна строка в файле .gitattributes, фиксирующая переводы строк в репозитории, закоммиченная один раз. После этого знать не нужно было никому. Ни тому, кто потерял полдня, ни следующему нанятому, ни человеку, который придёт через два года и никогда не услышит эту историю, потому что никакой истории не будет.

В этом весь аргумент, и я хочу сделать рутинным один вопрос: не кому нужно это знать?, а где живёт этот риск? Ответом должен быть путь проверки, сигнал времени выполнения или имя человека. Никогда — «надеемся, кто-нибудь вспомнит».

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

Проблему компетенции в разработке решили на заводе

Охрана труда закрыла этот спор ещё до нашего рождения, а разработка так и не прочитала служебную записку.

Иерархия мер защиты NIOSH состоит из пяти ступеней — устранение, замена, технические меры, административные меры, средства индивидуальной защиты, — отсортированных по принципу, который стандарт формулирует прямым текстом: верхние три «контролируют воздействие без существенного участия человека», а нижние две «полагаются на исполнительность человека». Лестница упорядочена по тому, насколько мало мера зависит от того, что человек поступит правильно.

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

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

Я хочу оставить версию этой лестницы для разработки, и ей нужны четыре ступени, а не пять:

  1. Устранить. Класс отказов не может возникнуть. Фича удалена; архитектура делает баг невозможным; недопустимое состояние невыразимо.
  2. Ограждение. Его обеспечивает машина — тип, проверка, лимит, операция, которая отказывается делать опасное, сигнал времени выполнения с определённой реакцией. Оно падает громко или не может упасть. Оно всегда исполняемо и никогда не является фразой в документе. (Сдерживание — откаты, канареечные выкатки, фиче-флаги — это вторая ось, а не более низкая ступень. Автоматический откат не зависит ни от кого, значит это вторая ступень. Откат, который живёт в ранбуке, который кто-то должен не забыть открыть, — это четвёртая ступень, и то, что он называется откатом, делу не помогает.)
  3. Компетенция. Её держит названный человек, и это удержание проверяется внешней проверкой, которую он не может оценить сам.
  4. Напоминание. Непроверенная человеческая память. Страница в вики. Правило, с которым все согласились.

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

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

Нижняя ступень тоже требует более резкого определения, потому что слабой вещь делает не то, что она «записана». Самое успешное вмешательство в безопасность в этом столетии — чек-лист. Хейнс с коллегами внедрили хирургический чек-лист из девятнадцати пунктов в восьми больницах в 2009 году и увидели падение смертности с 1,5% до 0,8%; сейчас он рекомендован ВОЗ и закреплён национальной политикой более чем в двадцати странах. Если напоминания так немощны, почему это сработало?

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

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

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

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

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

Ваш список компетенций — это переменная

Вот следствие, и ради него это эссе и написано.

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

Инженерия безопасности точна в этом уже тридцать лет, и я предпочту позаимствовать словарь, чем делать вид, что изобрёл ось координат. МЭК 61508 раскладывает каждый отказ по четырём ячейкам вдоль двух осей: безопасный или опасный, обнаруженный или необнаруженный. Категория, вокруг которой организована вся дисциплина, — опасные необнаруженные: отказы, которые важны и которых ничто не замечает. Есть метрика того, какую долю этой категории ловит ваша собственная диагностика, — диагностическое покрытие, и стандарт приводит целевые диапазоны 60%, 90% и 99%. А стандартный ход по улучшению, описанный в литературе почти этими же словами, — преобразование опасных необнаруженных отказов в обнаруженные.

Это и есть тезис данного эссе, написанный тридцатью годами раньше людьми, которые работают с вещами, которые взрываются.

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

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

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

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

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

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

Очевидное возражение ко всему этому — что верхняя ступень неподъёмна по цене, что устранение класса отказов хорошо звучит для тех, у кого бесконечный бюджет. Android — контрпример, и он публичен. Примерно за шесть лет перевода нового кода на безопасный по памяти язык доля багов безопасности памяти упала с 76% уязвимостей Android до 24%, а в 2025 году впервые опустилась ниже 20%; в абсолютных числах — с 223 в 2019 году до менее чем 50 в 2024-м. Google оценивает плотность уязвимостей в Rust-коде примерно в одну тысячную от таковой в хозяйстве на C и C++.

Но для этого аргумента важны скучные цифры. Изменения на Rust в Google показывают примерно вчетверо меньшую частоту откатов, отнимают примерно на 25% меньше времени на код-ревью и требуют примерно на 20% меньше правок, чем сопоставимые изменения на C++. Устранение класса опасностей не стоило скорости. Оно её купило. Самая сильная мера на лестнице оказалась самой дешёвой в эксплуатации — и причина не загадочна: ревью стали короче, потому что человеку стало меньше что замечать.

Структура решает, сколько вы сможете упразднить

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

Мог бы существовать детектор? звучит как вопрос о риске. На самом деле это в основном вопрос о вашей кодовой базе.

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

Это обобщается дальше, чем кажется на первый взгляд. В модуле со спутанным состоянием вы не сделаете недопустимое состояние невыразимым, потому что нет единственного места, где состояние конструируется. В системе без границ вы не напишете правило, запрещающее нарушение границы, потому что правилу нечего называть. Без швов нечего инструментировать, нечего подменять заглушкой, не к чему предъявлять утверждения. Связность и связанность задают потолок достижимого диагностического покрытия. Каждой мере нужно к чему-то крепиться, а структура — это то, что производит точки крепления.

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

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

Процедура: пройти по лестнице на реальной задаче

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

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

  1. Могу ли я это удалить? Должна ли эта фича, поле, флаг или ветка кода вообще существовать? Самая дешёвая мера — та, где контролировать больше нечего. Этот вопрос все пропускают, поэтому задавайте его вслух один раз на задачу, иначе не зададите никогда.
  2. Могу ли я сделать отказ невыразимым? Не «буду ли я внимателен», а: существует ли тип, схема, более узкий интерфейс, инвариант, который делает неверное состояние невозможным для выражения? Это рефакторинг, и его место — на второй ступени. Бо́льшая часть того, что внимательный инженер делает с модулем под именем проектирования, — это устранение опасностей, которое никто не засчитал как работу по безопасности.
  3. Существует ли детектор или ограждение уже сейчас? Проверка типов, тест, линтер или сигнал времени выполнения, который громко падает на этой ошибке, — или операция, которая уже отказывается делать опасное. Тогда делегируйте работу и доверьтесь мере. Проверьте результат против контракта, а не просмотрите его по диагонали, и идите дальше.
  4. Мог бы он существовать — и можете ли вы построить его внутри этой задачи? Тогда задача не в том, чтобы «удержать эту компетенцию». Задача — построить меру: проверку или ограждение, — а затем делегировать. Это шаг, который сокращает список, и именно его пропускают под давлением срока в пользу человека, обещающего быть внимательным. Заметьте, что ответ здесь — не свойство риска. Это свойство вашей кодовой базы: мере нужен шов, к которому крепиться, а есть ли он, решил тот, кто последним придавал форму этому модулю.
  5. Отказ безмолвный, значимый и непокрытый? Все три сразу, и никакая мера, которую вы можете себе позволить сегодня, этого не меняет. Тогда вы держите её — больше её не удержит никто — и заводите тем же коммитом тот детектор, который не построили.
  6. Это ваша первая реализация в этой области? Тогда удержите один раз, под присмотром, независимо от ставок. Никогда не арендуйте свою первую реализацию. Это ограничено и датировано, а не постоянно.

Иначе — делегируйте. При отсутствии названной причины из пятого или шестого пункта удержание есть дефект.

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

Первый вопрос, который разрешается

Вердикт

Что вы делаете

Могу ли я это удалить?

Устранить

Удалите. Контролировать больше нечего.

Могу ли я сделать это невыразимым?

Спроектировать прочь

Тип, схема, более узкий интерфейс. Неверное состояние перестаёт компилироваться.

Детектор или ограждение уже есть?

Делегировать

Передайте. Проверяйте против контракта, не по диагонали.

Мог бы быть — и построите сейчас?

Построить, затем делегировать

Сначала напишите проверку или ограждение — отрефакторьте до шва, если шва нет. Это упраздняет компетенцию навсегда.

Безмолвный + значимый + непокрытый?

Держать, с долгом

Сделайте сами; заведите недостающий детектор тем же коммитом.

Первая реализация в области?

Удержать раз, под присмотром

Ограничено и датировано.

Ничего из перечисленного

Делегировать

Удержание без названной причины есть дефект.

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

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

Одно различение перед примерами, потому что «проверить» — самая размытая из трёх корзин:

  • Проверка результата — удовлетворяет ли это контракту? Дёшево, часто, необходимо — и не наращивает никакой компетенции. Это потребление.
  • Проверка компетенции — можете ли вы произвести или вывести это без посторонней помощи? Редко, намеренно, и это единственная проверка, которая доказывает, что вы чем-то владеете.

«Я посмотрел диф» — это не «я могу это сделать».

Шесть задач, шесть разных ответов

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

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

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

Писатель, дописывающий на диск, разделяемый с бэкапами, логами и медиа. Когда диск заполняется, машина перестаёт отдавать что бы то ни было. Записи нужны, а «слишком много накопленных данных» — не то состояние, которое можно сделать невыразимым, поэтому первый и второй вопросы отпадают. Третий тоже отпадает: сегодня это ничто не ловит, и соблазнительный ход в этой точке — перескочить вперёд и назвать это удержанием, что означает, что кто-то будет помнить про необходимость следить за диском. Четвёртый вопрос существует, чтобы вас остановить. Мера — это самоограничивающаяся запись: проверить свободное место, подчистить перед записью, отказать ниже порога, выдать сигнал о запасе. Она не может заполнить диск, поэтому никому не нужно помнить, что не надо. Вердикт: построить ограждение, затем делегировать. И обратите внимание, чем в итоге владеет человек: не «следить за диском», а способностью спроектировать эту меру. Компетенция — это способность сдвинуть риск на ступень вниз, а это совсем другая вещь, чем держать риск в голове.

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

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

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

Пять из шести закончились где-то в другом месте, а не в «человек обязан это знать». Из двух, где человек вообще участвует, одно временно — постройте три проверки, и оно сдвинется, — а одно постоянно. Я подобрал шесть так, чтобы они приземлились в шести разных местах, поэтому само по себе это распределение ничего не доказывает; оно показывает диапазон ответов, доступных до того, как «кто-то обязан это знать» станет одним из них. Прогоните свои шесть сейчас и ещё раз через полгода. Распределение должно сдвинуться. Если не сдвинулось — никто ничего не построил.

Что моё прошлое эссе поняло неверно

Renting Competence (на английском) вышло двенадцать недель назад. В бо́льшую его часть я по-прежнему верю. Одна вещь в нём была неверна так, что стоит назвать это точно.

Дело не в том, что эссе игнорировало избыточную осторожность. Не игнорировало. Там есть раздел под названием AUTO is real, with preconditions, где прямо сказано, что «методология без режима AUTO — это просто „делай всё сам“, и реальность её отвергает», и говорится, что широкое поверхностное знание теперь бесплатно и что арендовать большинство компетенций нормально, пока вы честны в этом. Оба режима отказа названы.

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

Недоделегирование — это ещё и не массовый провал внедрения. Около 90% разработчиков сообщают о ежедневном использовании ИИ-инструментов в исследовании DORA за 2025 год; 84% респондентов Stack Overflow 2025 используют их или планируют. И инструменты работают: три рандомизированных контролируемых испытания на 4867 разработчиках в Microsoft, Accenture и компании из списка Fortune 100 показали прирост завершённых задач на 26%, сосредоточенный у менее опытных разработчиков, которые прибавили 27–39% против 8–13% у сеньоров. При этом доверие падает в обоих опросах: 46% респондентов Stack Overflow больше не доверяют точности того, что получают, против 31% годом ранее. Никто не отказывается от инструмента. Им пользуются и ему не верят.

И вот в этом настоящая форма проблемы. Генерация подешевела, а верификация — нет. Опрос Sonar более чем 1100 профессиональных разработчиков оценивает долю кода, написанного с помощью ИИ, в 42% от того, что они коммитят, обнаруживает, что 96% не доверяют ему полностью, и что только 48% всегда проверяют его перед коммитом, — а значит, большинство принимает решение о том, когда проверять, в каждом случае отдельно, суждением, без помощи, ровно по тому вопросу, в самооценке которого люди документированно хуже всего. 38% говорят, что ревью кода, написанного ИИ, требует больше усилий, чем ревью кода коллеги.

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

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

Два честных исключения, иначе правило на практике неверно.

Удержание ради роста законно. Иногда разработчик должен выучить то, что модель сделала бы целиком, — потому что через полгода это ему понадобится или потому что технология наказывает поверхностное понимание, и аренда порождает ровно ту поверхностность, которую эта технология наказывает. Это настоящая причина. Просто она должна быть подтверждена, датирована и исключена из арифметики рисков, чтобы «я это изучаю» не превратилось тихо в неограниченную лицензию писать всё руками.

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

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

Как сертифицировать то, что осталось — и как не надо

Когда остаток мал, проверьте его: самооценка не работает, а экзамен — единственная часть лестницы, которая измеряет человека.

Сначала делайте дешёвое. Именно его я действительно проводил.

Вычитывайте пробелы из истории мержей. Стоимость близка к нулю. Пройдите по реальным коммитам разработчика за квартал и спрашивайте о каждом: что он демонстрирует и чего избегает. За час вы узнаете больше, чем скажет любой экзамен, потому что это измеряет то, что человек делает в потоке, а это и есть то, что вас на самом деле волнует. Начинайте отсюда всегда.

Затем — устные зондирующие вопросы без ИИ и вообще без написания кода. Полчаса, доска и вопросы с определённым правильным ответом: Где выполняется этот код? Что протекает через эту границу? Зависло или отвалилось — как вы отличите одно от другого? Требует ли это изменение повышения версии? Дёшево, воспроизводимо, и они ловят большую часть того, что важно.

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

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

Режимы отказа полезнее самой конструкции, поэтому:

Не начинайте с него. Потянуться сперва к экзамену — значит потратить сеньоро-недели, чтобы узнать то, что история мержей сказала бы за час.

Не делайте его постройкой с нуля. Тогда вы проверяете упорство и выносливость, которые вся методология велит делегировать. Дайте каркас для всего, что не является рискованной поверхностью.

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

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

Не проверяйте то, что мог бы поймать детектор, — и заметьте, что из этого следует. Это самоликвидирующаяся часть, и она снимает самое острое возражение к экзамену. Если вы можете построить стенд, механически оценивающий отказ, вы обычно можете построить тот же стенд как тест. А значит, механическая половина вашего экзамена — это список дел для вашего CI, и она должна сокращаться каждый год по мере того, как её пункты выпускаются в проверки, выполняющиеся на каждом коммите. Только для экзамена остаётся половина с суждением, потому что ни один стенд не оценит «потребует ли это повышения версии» или «что бы вы делегировали».

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

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

Остаётся возражение Парасурамана и Манзи — то самое, которое должно было беспокоить вас с первого раздела. Автоматизационное смещение не предотвращается обучением или инструкцией. Так почему сертификация должна помочь?

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

Две поправки к сказанному, обе против меня же.

Утверждение про ручное пилотирование было неверным. В Renting Competence я написал, что ручные навыки пилотов измеримо затухают за два месяца без практики, сославшись на Каснера с коллегами. Исследование обнаружило не это. Тестируя пилотов авиалиний на тренажёре Boeing 747-400, они нашли, что сканирование приборов и навыки ручного управления в основном сохранны, даже когда пилоты сообщали о малом объёме недавней практики. Деградировала когнитивная сторона — знание того, что делать, и принятие решений, которого требует ручной полёт, — и её удержание зависело от того, насколько активно пилоты оставались вовлечены в надзор за автоматикой.

Поправка улучшает аргумент — потому её и не жалко вносить. Атрофируется модель, а не движения. Модель — это ровно то, что содержит остаточный список компетенций, и ровно то, что не тренируется просмотром дифа.

И я слишком сильно опирался на METR. Их вывод — что опытные разработчики были на 19% медленнее с ИИ-инструментами, считая при этом, что стали на 20% быстрее, — самое цитируемое число в этой дискуссии, в том числе у меня. Это 16 разработчиков, в зрелых репозиториях, которые они хорошо знали, в препринте, авторы которого явным образом отказываются обобщать, и измерялась самооценка скорости, а не навыка. Это ближайшее измерение, которое у меня есть, и оно не измеряет то, что мне нужно. Утверждение, которое оно действительно поддерживает, узкое: люди плохо судят о собственной результативности с этими инструментами. Для более сильного утверждения — что беглость чтения принимают за понимание — лучшая ссылка это Бьорк и Бьорк о желательных трудностях и иллюзии беглости, и она всегда была лучшей ссылкой.

Где аналогия ломается

Я заимствовал у дисциплины, у которой есть преимущество, которого у меня нет.

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

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

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

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

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

Обратим правило на само это эссе

Правило под всем вышесказанным таково: каждый дефект должен ловиться чем-то, кроме человека, который заметил.

Применим его к этому эссе.

Механизм

Чем он на самом деле является

Шлюз делегирования

Человек, читающий самоотчётное обоснование

Счётчик удержаний

Состояние, поддерживаемое вручную, дублирующее выводимое

Проверка в начале задачи

Человек, который помнит, что надо открыть реестр

Сбор уроков из инцидентов

Человек, проводящий разбор по шаблону

Экзамен

Сеньор, оценивающий по ключу, который сам же написал

Линтер на снятие ограждений

Исполняемый машиной — и не построенный

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

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

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

Поэтому фраза, ради которой это эссе строилось, должна быть направлена сначала сюда: если вы не можете назвать детектор, вы написали напоминание и назвали его методологией. Я написал напоминание.

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

А потом идите и стройте вместо этого его.


Заимствованное и своё

Почти вся механика здесь заимствована, и важно сказать, у кого. Иерархия мер защиты принадлежит NIOSH, без изменений, кроме сжатия до четырёх ступеней, которое я обосновал и обозначил. Классификация обнаруженный/необнаруженный и диагностическое покрытие — из МЭК 61508. Пока-ёкэ — спроектировать задачу так, чтобы промах не мог случиться или ловился в момент совершения, — принадлежит Синго, с 1963 года, и его каталог из 112 цеховых приспособлений, большинство дешевле ста долларов, служит постоянным опровержением идеи, что ограждения дороги. Иронии автоматизации — Бейнбридж, и её идея самая острая в этом эссе. Управление изменениями — нельзя снять меру, не переоткрыв опасность, которую она упразднила, — не метафора, а регламент: OSHA 29 CFR 1910.119(l). «Сделай это проверкой в пайплайне, а не страницей в вики» — фольклор SRE. А сертификация без ИИ с внешней оценкой — не новация; так работала любая профессиональная сертификация до всего этого.

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


Источники

  • NIOSH / CDC, Hierarchy of Controls — пять ступеней и принцип упорядочивания: верхние три работают «без существенного участия человека». cdc.gov/niosh
  • IEC 61508 — классификация безопасный/опасный × обнаруженный/необнаруженный, диагностическое покрытие и целевые диапазоны 60/90/99%. Обзор Risknowlogy , позиционный документ exida
  • Parasuraman & Manzey (2010), Complacency and Bias in Human Use of Automation: An Attentional Integration, Human Factors 52(3):381–410 — беспечность у экспертов «не преодолевается простой практикой»; смещение «не предотвращается обучением или инструкциями». journals.sagepub.com
  • Bainbridge (1983), Ironies of Automation, Automatica — остаток, полученный вычитанием. обзор
  • Haynes et al. (2009), A Surgical Safety Checklist to Reduce Morbidity and Mortality in a Global Population, NEJM 360:491–9 — смертность 1,5% → 0,8%. nejm.org
  • Google (2025), Rust in Android: move fast and fix things — доля багов безопасности памяти ниже 20%, снижение плотности примерно в 1000 раз, вчетверо меньше откатов, на ~25% меньше времени на ревью, на ~20% меньше правок. blog.google
  • CISA/NSA/FBI, The Case for Memory Safe Roadmaps — устранение класса как политика. cisa.gov
  • Shingo, Zero Quality Control: Source Inspection and the Poka-Yoke System — 112 приспособлений, большинство дешевле 100 долларов. taylorfrancis.com
  • OSHA, 29 CFR 1910.119(l) — управление изменениями как письменная обязательная процедура. osha.gov
  • Cui, Demirer, Jaffe, Musolff, Peng & Salz (2026), The Effects of Generative AI on High-Skilled Work, Management Science — три РКИ, 4867 разработчиков, +26,08% завершённых задач. pubsonline.informs.org
  • DORA (2025), State of AI-assisted Software Development — ~90% ежедневного использования; 30% сообщают о низком доверии или его отсутствии к коду, сгенерированному ИИ. dora.dev
  • Stack Overflow (2025), Developer Survey — 84% используют ИИ или планируют; 46% больше не доверяют точности вывода ИИ против 31% годом ранее. stackoverflow.blog
  • Sonar (2026), State of Code Developer Survey, более 1100 профессиональных разработчиков — 42% закоммиченного кода написано с помощью ИИ; 96% не доверяют ему полностью; только 48% всегда проверяют перед коммитом; 38% говорят, что ревью ИИ-кода требует больше усилий, чем ревью кода коллеги. sonarsource.com
  • METR (2025), Measuring the Impact of Early-2025 AI on Experienced Open-Source Developer Productivity — на 19% медленнее при уверенности, что на 20% быстрее; 16 разработчиков, и измерялась скорость. arxiv.org/abs/2507.09089
  • Casner, Geven, Recker & Schooler (2014), The Retention of Manual Flying Skills in the Automated Cockpit, Human Factors — ручное управление в основном сохраняется; деградирует когнитивная сторона. journals.sagepub.com
  • Bjork & Bjork (2011), Making Things Hard on Yourself, But in a Good Way — желательные трудности и иллюзия беглости.

No comments yet