Перейти к содержанию

E-01 · Что вскрыл прогон#

Все восемнадцать находок закрыты 2026-09-16 — см. итог ревизии и план. Три из них (2, 12, 13) план пропустил: они попали в правки уже при исполнении. Файл сохраняется как есть — он показывает, что именно прогон обнаружил и в каком порядке.

Копится по ходу, применяется на этапе 6. Правки в шаблоны не вносятся по ходу: иначе документы будут меняться под уже написанные ADR, и прогон перестанет быть проверкой.

После этапа 2 (D-01 → ADR-0001)#

№ Находка Где чинить
1 У гринфилда не существует пометки [замер] — измерять нечего. Пришлось объявить [расчёт W1] прямо в ADR. Словарь пометок молча предполагал существующую систему 00-template.md, правило о пометках
2 Все сработавшие дисквалификаторы — организационные, ни одного технического. В списке D-01 они перемешаны; на обычной системе технические не сработали вовсе D-01, порядок дисквалификаторов
3 [нет данных] не заблокировало решение. D-01 говорит, что пустая ячейка сообщает, какой замер нужен «прежде чем решать». Но ось «стоимость владения» не различала оставшиеся варианты — и пустота оказалась безвредной. Нужна оговорка: блокирует только та пустая ячейка, что стоит в оси, различающей кандидатов 00-template.md
4 Реестр ограничений перерос порог сразу. Правило D-01 обещало вынос «когда записей больше десятка»; четыре появились после первого же ADR. Порог завышен примерно втрое D-01, раздел 4
5 Пришлось явно написать, чего решение не решает. Выбор хранилища не закрывает 8 000 чтений/с — это уровень W5. В D-01 нет строки о границе решения, и без неё соблазн закрыть чтения выбором БД остаётся D-01, шапка
6 Ничья возникла там, где её не ждали. PostgreSQL и MySQL 8.0 совпали по обеим решающим осям (SKIP LOCKED есть у обоих [док]). Матрица отработала правильно — показала отсутствие различий, — но выбор сделала эвристика. Это не дефект: так и задумано —

После этапа 3 (D-02 → ADR-0002)#

№ Находка Где чинить
7 Раздел 1 D-02 целиком построен на истории, которой у гринфилда нет. Три вопроса из семи структурно [нет данных] — не по небрежности, а потому, что репозитория и трекера не существует. Эвристика «связность изменений считается за час по трекеру» даёт невыполнимую инструкцию, а не отсрочку D-02, раздел 1 и эвристики
8 Дисквалификация оставила один вариант — матрица выродилась в одну колонку. Шаблон не говорит, что делать: заполнять нечего, а пустой раздел выглядит как лень. Понадобилась оговорка прямо в ADR 00-template.md, раздел 3
9 Форма разреза «по профилю нагрузки» путается с решением о кэше. Разница чтений и записей в 27× выглядит как основание для границы сервиса, но путь чтения не имеет своего языка, инвариантов и владельца данных — это проекция, а не ограниченный контекст D-02, раздел 4
10 Самый ценный выход ADR оказался побочным: названа самая дорогая будущая граница (Инвентарь ↔ Заказы, по ней идёт транзакция подтверждения). Ни в D-02, ни в шаблоне ADR такого поля нет, а через год это ровно то, что нужно знать D-02, раздел 6 или 01-adr-template.md

Отрицательный результат, важный для метода. Гипотеза перед этапом была: «документ поддастся соблазну что-нибудь разрезать». Не поддался — три дисквалификатора сработали и отсекли саму идею разреза, ровно как D-02 и обещает («последние три отсекают саму идею разрезать сейчас»). Но выяснилось это не благодаря сравнению, а вместо него.

После этапа 4 (D-04 → ADR-0003)#

Самый урожайный этап: четыре находки, и две из них — противоречия внутри уже написанного.

№ Находка Где чинить
11 Условие применимости D-04 сформулировано неверно. Документ говорит «для каждого процесса, пересекающего границы сервисов». Сервисов у нас нет, но процесс пересекает границу внешнего платёжного провайдера — а там общая транзакция недостижима принципиально. Правильное условие: процесс пересекает границу, за которой нет общей транзакции, и своя это граница или чужая — неважно D-04, шапка и эвристика «отложить»
12 Оси согласованности не хватает третьего значения. Есть «атомарная» и «итоговая», а встретился третий случай: атомарность требуется бизнесом и недостижима технически (деньги в чужой системе). Записать пришлось как «итоговую», но это не то же самое: из недостижимости следуют обязательства, которых у обычной итоговой согласованности нет — состояние неизвестен и обязательная сверка D-04, раздел 1 и 3
13 Нулевой вариант в перечисляемом типе всё-таки есть. 00-template.md v3.0 утверждает: «Не бывает: в какой-то ячейке мы находимся всегда». Контрпример нашёлся сразу — участок «выбор места → резерв» это локальная транзакция в одном модуле, он не попадает в пространство восьми ячеек вообще. Правило, записанное четыре дня назад по рассуждению, опровергнуто первым же применением 00-template.md, таблица трёх типов
14 Один рабочий процесс распался на два решения. Область применения — не «процесс» как его называет продукт, а участок между границами. Документ нигде не говорит, как процесс делить перед применением D-04, раздел 1

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

После этапа 5 (D-03 → ADR-0004)#

№ Находка Где чинить
15 D-03 противоречит сам себе на гринфилде. Дисквалификатор: «узкое место не подтверждено замером» — решение принимать нельзя. Эвристика: «"нет данных" здесь не повод откладывать, включить умолчание и померить». Оба про одну ситуацию, выводы противоположные D-03, дисквалификаторы и эвристики
16 В таблице отклонений нет главной развилки читающего кэша: инвалидация против короткого TTL. Отклонения D-03 описывают стратегии записи и размещение. Для данных, меняющихся 300 раз в секунду, «удаление ключа при записи» — не стратегия, а отказ кэша работать: ключ живёт 3 мс D-03, раздел 3
17 Дисквалификатор выдавил наружу решение, которого в наборе нет. «Система не переживает отказа кэша» → нужна деградация. Проектирование деградации продуктовое, необратимое одним коммитом и принимается на W7 — то есть это отдельное полное решение, а не строка в короткой записи новый документ решения, W7
18 Короткая форма и короткая запись — разные вещи. Решение по короткой форме оказалось несущим, и пять строк не вместили обоснования отказа от умолчания. Правило «если запись разрослась, проверьте, не полная ли это форма» дало ложный сигнал: форма верна, вырос не метод, а обоснование 00-template.md, 01-adr-template.md

Сквозная закономерность: документы двоичны там, где реальность троична#

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

Документ Два значения в документе Третье, встреченное в прогоне
D-01 [замер] · [нет данных] [расчёт] — выведено арифметически, слабее замера, сильнее догадки
D-04 атомарная · итоговая требуется, но недостижима — с обязательной сверкой
D-03 узкое место подтверждено · не подтверждено выведено расчётом: 8 000 чтений/с против одного узла — не догадка и не замер

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

Принятая позиция: стадия проекта — отдельное решение, а не ветка внутри#

Записана 2026-09-16, до этапа 5. Определяет, как чинить находки 1 и 7 на этапе 6.

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

Прогон подтвердил это раньше, чем позиция была сформулирована. Находка 7: раздел 1 D-02 на гринфилде не «работает наполовину», он не работает вовсе — измерять связность изменений не по чему. Ветка «если системы ещё нет, пропустите вопросы 1, 3 и 7» превратила бы документ в такой, где половина вопросов помечена «(если система уже работает)» — классический способ сгнить.

Различаются не ответы, а метод#

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

Это не одно решение с разными числами. Это разные вопросы.

Разделяющий признак — чтобы не расплодить документы#

Дробить по стадиям всё подряд нельзя: четыре решения на три стадии дадут двенадцать документов. Признак разделения:

Разделять, если меняется источник фактов, дисквалификаторы или эвристики. Не разделять, если меняются только значения в ячейках.

Проверка на том, что уже есть в прогоне:

Документ На гринфилде Вердикт
D-01 хранилище Метод тот же; понадобился только свой словарь пометок — [расчёт W1] вместо [замер] Не разделять
D-02 границы Нет источника фактов, другие дисквалификаторы, эвристика даёт невыполнимую инструкцию Разделять

Признак различил оба случая правильно, не будучи под них подогнан.

Стадий, похоже, три#

Стадия Чем отличается для решений
Гринфилд Фактов нет, они предсказываются. Пометки [расчёт], не [замер]
Работающая система Факты измеряются. Появляется история, появляется «посчитать за час»
Система под изменением Есть работающая система и обязательство её не сломать: миграция, обратная совместимость, окно перехода, откат

Третьей стадии в decisions/ нет вовсе, а именно на ней принимается большинство решений в живых проектах.

Как называть#

Не D-02a / D-02b. Буквенный суффикс намекает, что один документ — вариант другого, и провоцирует прочесть только один. Отдельные номера плюс строка «Не путать с» в шапке, рядом с уже существующей «Известно также как»: первая ловит синонимы, вторая — соседей, которых легко перепутать.

Оговорка#

Два этапа назад я возражал против расширения набора вширь. Здесь противоречия нет: это не новые решения, а разделение существующих там, где метод действительно разный, и разделяющий признак держит рост ограниченным. Но правило стоит проверить на E-02: если на другом кейсе оно начнёт делить всё подряд, признак слишком слабый.

Наблюдение, не требующее правки#

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

Урок о проверках, не о документе#

Первый негативный тест новой проверки ADR не сработал, и это выглядело как «проверка не ловит ошибку». На деле не совпали пробелы в sed, и подсадить ошибку не удалось — файл остался нетронутым. Тот же класс ошибки, что две ложные метрики ревизии №2: тест, который не сработал, может означать сломанный тест, а не рабочий код. Правило: подсадка ошибки обязана сама себя проверять (assert, что файл изменился).