8 lines
19 KiB
JSON
8 lines
19 KiB
JSON
{
|
||
"index": 119,
|
||
"slug": "editorial-2024-09-mechanism-adr-decisions",
|
||
"title": "ADR без иллюзии выбора: как записать решение, его цену и путь назад",
|
||
"excerpt": "Архитектурное решение теряет смысл, если в записи виден только победивший вариант. Разбираем, как сравнить альтернативы по одной схеме, проверить отрицательный путь и оставить условие для пересмотра.",
|
||
"contentHtml": "<p>В review появляется знакомый симптом: команда обсуждает не условие задачи, а вкус. Один вариант называют простым, другой — надёжным, третий — слишком дорогим. В ADR уже записан победитель, но альтернативы сведены к двум словам. Через месяц авторы помнят контекст, а остальные видят только решение. Через год никто не знает, какую проблему оно закрывало и что делать, если исходное условие изменилось.</p>\n<p>Цена ошибки растёт вместе с границей решения. Неудачный выбор может закрепить общий протокол, миграцию, формат данных или операционную обязанность. Тогда быстрый первый merge скрывает дорогой rollback. Ошибка не в том, что команда выбрала неидеальный вариант. Ошибка в том, что запись не показывает принятый компромисс и не даёт проверить, когда его пора пересмотреть.</p>\n<p><strong>Тезис:</strong> хороший ADR не доказывает, что выбранный вариант лучший вообще. Он связывает наблюдаемую проблему с конкретным ограничением, одинаково описывает альтернативы, называет цену выбора и задаёт сигнал для возврата к решению. Числа могут помочь в учебной модели, но не заменяют факты и не превращают мнение в production-метрику.</p>\n<h2>Механизм: от симптома к решению</h2>\n<p>ADR полезен как короткая цепочка причин. Сначала автор отделяет факт от объяснения. Факт можно наблюдать: caller должен получить статус, пока фоновая операция продолжается; данные нельзя отдавать старше заданной границы; изменение должно откатываться без записи нового формата. Гипотеза объясняет, почему текущий путь не подходит. Решение отвечает на ограничение, а не на абстрактную цель вроде «улучшить архитектуру».</p>\n<p>У каждой альтернативы должна быть одна и та же карточка. Запишите, какой constraint она закрывает, где находится её граница, кто владеет дополнительной работой, как выглядит возврат и какое evidence уже есть. Отсутствующее evidence тоже является результатом сравнения. Оно ограничивает уверенность, но не доказывает безопасность или опасность варианта.</p>\n<p>Статус помогает не смешивать обсуждение и историю. <em>Proposed</em> означает, что запись готова к проверке. <em>Accepted</em> фиксирует принятое решение. <em>Superseded</em> означает, что новый ADR заменил старый и объяснил причину. Статус не запускает миграцию, не назначает approval и не проверяет rollback автоматически. Эти действия должны иметь отдельного владельца и отдельный сигнал.</p>\n<pre><code>symptom = caller не получает понятный status\nconstraint = acknowledgement не должен зависеть от business completion\nalternatives = direct response | bounded async state | shared workflow\ndecision = bounded async state у границы сервиса\nprice = expiry, owner состояния, cleanup и отдельная проверка retry\nreassess = меняется контракт caller или срок хранения состояния</code></pre>\n<p>Этот фрагмент — учебный пример формы. Он не описывает реальный сервис, трафик, SLO или production-результат. Его задача — показать, как решение связывает симптом, условие, цену и отрицательный путь. В настоящем ADR вместо учебных утверждений нужны ссылки на контракт, issue, тест, threat model или другой разрешённый источник evidence.</p>\n<h2>Как сравнить альтернативы честно</h2>\n<p>Сначала выровняйте уровень вариантов. Нельзя сравнивать «локальный cache» с «переделать платформу»: это разные масштабы и владельцы. Сформулируйте варианты на уровне решения, а затем укажите реализацию как следствие. Для asynchronous boundary это могут быть прямой ответ после завершения работы, bounded state с выдачей статуса и общий workflow с отдельным хранением состояния.</p>\n<p>Constraint fit отвечает на вопрос «закрывает ли вариант обязательное условие». Reversibility описывает не наличие кнопки undo, а область возврата, порядок действий и владельца. Evidence fit показывает, какие факты поддерживают выбор и какой вопрос остался открытым. Operating cost называет долг: expiry, retry, cleanup, миграцию, поддержку контракта или ручной review. Reassessment показывает, что должно измениться, чтобы открыть новый ADR.</p>\n<table><thead><tr><th>Критерий</th><th>Вопрос к каждому варианту</th><th>Проверяемый артефакт</th><th>Чего нельзя утверждать</th></tr></thead><tbody><tr><td>Constraint fit</td><td>Какое объявленное условие выполняется?</td><td>Контракт, problem statement или acceptance question</td><td>Что вариант оптимален для всех целей</td></tr><tr><td>Reversibility</td><td>Какой scope возврата, кто его выполняет и что останавливает change?</td><td>План rollback и граница затронутого состояния</td><td>Что rollback уже проверен в production</td></tr><tr><td>Evidence fit</td><td>Какой факт поддерживает выбор и чего пока не хватает?</td><td>Ссылка на источник, controlled test или явное unknown</td><td>Что отсутствие данных равно безопасному результату</td></tr><tr><td>Operating cost</td><td>Кто поддерживает status, expiry, retry, cleanup или migration?</td><td>Owner и consequence в ADR</td><td>Что стоимость измерена в часах или деньгах</td></tr><tr><td>Reassessment</td><td>Какой сигнал отменяет исходное предположение?</td><td>Review condition, metric question или contract link</td><td>Что дата сама запустит пересмотр</td></tr></tbody></table>\n<p>Таблица не требует единой оценки. Она делает пропуски видимыми. Если у одного варианта есть контракт, а у другого только слово «сложно», сравнение ещё не началось. Если команда всё же применяет score, заранее закрепите шкалу, веса и смысл баллов. Рядом напишите, какие данные модель не учитывает. Итоговый балл может быть tie-breaker для обсуждения, но не доказательством корректности.</p>\n<figure><img src=\"/assets/editorial/2024/adr-decisions-2024-alternatives-matrix.svg\" alt=\"Синтетическая матрица сравнения альтернатив ADR по ограничениям, обратимости, evidence и операционной цене\"><figcaption>Иллюстрация показывает синтетическую матрицу. Значения помогают увидеть форму сравнения и не являются метриками реальной команды или production-системы.</figcaption></figure>\n<h2>Пример записи с отрицательным путём</h2>\n<p>Предположим, synchronous caller ждёт результат долгой операции. Прямой ответ сохраняет простую модель, но не выдерживает границу времени. Shared workflow даёт общий status, но добавляет cross-service owner и отдельный контракт. Bounded state у границы сервиса отделяет acknowledgement от business completion. Это может закрыть исходное условие, если срок хранения, повтор запроса и очистка состояния определены явно.</p>\n<pre><code>## Decision\nВыбираем bounded state у границы сервиса.\n\n## Consequences\nПоложительные: caller получает отдельный status.\nЦена: owner хранит expiry и cleanup; retry должен быть идемпотентным.\n\n## Не делаем\nНе вводим shared workflow и не считаем локальное состояние\nуниверсальным механизмом координации.\n\n## Reassessment\nОткрываем новый ADR, если caller требует общего status между\nсервисами или срок хранения превышает допустимую границу.</code></pre>\n<p>Отрицательный путь защищает запись от незаметного расширения. Без него локальное решение постепенно начинает обслуживать новые callers, а временное поле превращается в общий протокол. Если новое требование действительно появилось, это не повод молча дописывать старый ADR. Нужен successor с новым контекстом, альтернативами и ценой. Старый record остаётся историей прежнего компромисса.</p>\n<h2>Симптом → причина → проверка → действие</h2>\n<table><thead><tr><th>Симптом</th><th>Причина</th><th>Проверка</th><th>Действие</th></tr></thead><tbody><tr><td>Выбранный вариант подробно описан, остальные названы «сложными»</td><td>Автор сравнил не варианты, а привлекательность собственного решения</td><td>Заполнить одну карточку criteria для каждой альтернативы</td><td>Переписать ADR и назвать explicit downside победителя</td></tr><tr><td>После merge спорят, что на самом деле означал ADR</td><td>В записи смешаны факт, гипотеза и implementation detail</td><td>Пометить источник каждого важного утверждения</td><td>Вынести неизвестное в evidence gap и добавить owner проверки</td></tr><tr><td>Rollback существует только как фраза</td><td>Не определены scope, порядок и stop condition</td><td>Провести dry run на учебной копии или описать точную границу</td><td>Связать ADR с отдельным rollback-планом и не объявлять его проверенным без evidence</td></tr><tr><td>Локальный механизм используют новые callers</td><td>Отрицательный путь и граница применимости не записаны</td><td>Проверить список потребителей и контракт состояния</td><td>Остановить расширение, создать successor ADR при новом требовании</td></tr><tr><td>Дата review прошла, но никто не вернулся к решению</td><td>Дата ошибочно принята за автоматический процесс</td><td>Найти владельца сигнала и фактическое событие пересмотра</td><td>Назначить действие отдельно или заменить дату проверяемым trigger</td></tr></tbody></table>\n<h2>Порядок работы</h2>\n<ol><li><strong>Сузьте вопрос.</strong> Опишите одну границу: какой caller, какое состояние и какое обязательное условие создают проблему.</li><li><strong>Зафиксируйте наблюдаемый симптом и цену.</strong> Отделите факт от гипотезы. Назовите, что станет дороже или опаснее при неверном выборе.</li><li><strong>Соберите три разумные альтернативы.</strong> Приведите их к одному уровню и не добавляйте вариант, который не может закрыть constraint.</li><li><strong>Заполните одинаковые поля.</strong> Укажите constraint fit, reversibility, evidence gap, operating cost, owner и отрицательный путь.</li><li><strong>Сформулируйте decision как компромисс.</strong> Запишите, что реализуем и чего намеренно не делаем.</li><li><strong>Назначьте проверяемый сигнал.</strong> Это может быть изменение контракта, новый потребитель, исчерпание срока хранения или конкретный вопрос к метрике.</li><li><strong>Проверьте запись до implementation.</strong> Reviewer должен суметь назвать выбранный вариант, его цену и условие пересмотра, не открывая код.</li><li><strong>Свяжите запись с реализацией отдельно.</strong> ADR не заменяет тест, threat model, migration plan, benchmark, runbook или incident review.</li></ol>\n<h2>Ограничения и критерий готовности</h2>\n<p>ADR не делает решение истинным и не заменяет исследование. Он не измеряет latency, надёжность, стоимость или безопасность, если рядом нет соответствующего evidence. Он не гарантирует, что команда найдёт все альтернативы. Формат может различаться: важнее сохранить контекст, выбор, статус, последствия, границы и путь пересмотра. Для legal, security, privacy и data boundary нужны отдельные проверки с отдельными владельцами.</p>\n<p>Не добавляйте в учебный пример вымышленные traffic, error rate, savings или outcome. Если число нужно для объяснения score, пометьте его как синтетическое и не переносите вывод за пределы модели. Если production-данных нет, честная формулировка — «данных пока недостаточно», а не «вариант доказанно безопасен».</p>\n<p>Запись готова, когда независимый читатель может ответить на пять вопросов: какой симптом наблюдали; какое constraint обязателен; почему сравнивали именно эти варианты; какую цену принимает выбранный путь; какой сигнал заставит открыть новое решение. Проверка проста: уберите из текста заголовок <em>Decision</em> и попросите коллегу восстановить его из context, alternatives и consequences. Если он не может назвать отрицательный путь или owner, ADR ещё не готов.</p>\n<h2>Проверяемые источники</h2>\n<ul><li><a href=\"https://adr.github.io/\" target=\"_blank\" rel=\"noopener noreferrer\">Architectural Decision Records</a> — официальный сайт сообщества ADR с материалами о формате и практике.</li><li><a href=\"https://github.com/adr/madr\" target=\"_blank\" rel=\"noopener noreferrer\">MADR: Markdown Architectural Decision Records</a> — репозиторий шаблонов и документации Markdown-формата.</li><li><a href=\"https://www.gov.uk/government/publications/architectural-decision-record-framework\" target=\"_blank\" rel=\"noopener noreferrer\">Architectural Decision Record Framework</a> — официальный framework Government Digital Service и Department for Science, Innovation and Technology.</li></ul>"
|
||
}
|