Когда приёмка устаревшей системы что-то доказывает?
Приёмка устаревшей системы требует повтора трафика, сверки до копейки, проверки отката и передачи, которую инженеры могут подтвердить.

Приёмка не сводится к совещанию, подписи или спокойной неделе после запуска. Переписанную систему можно принять, когда заказчик доказал, что она сохраняет нужное бизнесу поведение, объясняет каждое финансовое расхождение, выдерживает отрепетированный откат и работает без постоянного присутствия команды переписывания.
Такой критерий кажется строгим лишь до первого провала. Тогда недостаток доказательств проявляется сразу: никто не понимает, исправлена ошибка или возникла регрессия, итоги расходятся на несколько копеек в тысячах записей, инструкция по откату содержит команды, которые никто не запускал, а инженеры обнаруживают скрытую зависимость от авторов. Приёмка должна выявить это, пока проект ещё может исправить положение.
Приёмка начинается с договора о доказательствах
Определите условия до начала реализации. Команда должна заранее знать, какие утверждения ей предстоит доказать. Фразу «работает как старая система» проверить нельзя. Замените её наблюдаемыми правилами, именованными наборами данных, допусками, ответственными и материалами, которые сохранятся после решения.
Разделите четыре решения. Функциональный паритет отвечает на вопрос, даёт ли одинаковый допустимый запрос тот же бизнес-результат. Финансовая сверка проверяет проводки, остатки, налоги, округления и распределения на уровне, нужном бухгалтерии. Эксплуатационная приёмка подтверждает, что систему можно развернуть, наблюдать, восстановить и откатить. Приёмка владения показывает, сможет ли принимающая команда безопасно менять её после ухода авторов.
У каждого решения должен быть названный владелец. Продукт или операционный блок утверждает намеренные изменения поведения. Финансы задают допуски и подписывают сверку. Владелец сервиса принимает процедуры и остаточные риски. Безопасность проверяет новые границы доверия и пути доступа. Руководящий комитет может получить эти решения, но не заменить ответственных усреднённым мнением.
Оформите договор небольшой матрицей. Для каждого утверждения укажите источник доказательства, критерий прохождения, порядок исключений, утверждающего и место хранения. «Совпало 99 процентов» ничего не значит без объяснения допустимого одного процента. Одна ошибка в регуляторном отчёте важнее десяти тысяч отличий в пробелах.
Меняйте договор только через обычный контроль изменений. Новый крайний случай может потребовать нового правила, но нельзя ослаблять допуск потому, что новая система его не выдерживает. Запишите автора, причину и результаты, утратившие силу. Иначе цель будет сдвигаться при каждой неудобной ошибке.
Так же точно опишите среду: образы ОС, расширения базы, локали, базу часовых поясов, настройки брокера, флаги и справочники. Результат из безымянной среды нельзя воспроизвести. Слов «похоже на продакшен» недостаточно. Присвойте среде идентификатор и добавляйте хеш конфигурации в каждый пакет доказательств.
Производительность входит в договор, если время влияет на бизнес. Укажите нагрузку, параллелизм, объём, прогрев и процентили на настоящей границе. Ночной расчёт с верными итогами после утреннего срока уже провалился. Медленный запрос, который вызывает повторы и дубли, тоже. Производительность и функциональный паритет проверяются отдельно.
Зафиксируйте и отрицательную цель: новая архитектура не обязана повторять старую. Паритет поведения и реализации различаются. Копирование структуры COBOL-пакета в Go-сервис сохраняет случайное устройство и мешает владению. Принимайте наблюдаемое поведение на стабильных границах, а внутреннее устройство оценивайте по современным инженерным требованиям.
Договор также должен связывать доказательства с точной версией выпуска, схемы, среды и справочников. Укажите, кто вправе менять исключение и когда результат перестаёт действовать. Новая функция, канал, валютная таблица или бухгалтерское правило могут отменить часть приёмки. Прежняя подпись не распространяется автоматически на будущую версию с тем же названием.
Записанный производственный трафик не заменяет все тесты
Запись трафика даёт лучшую выборку реальных действий, но доказывает лишь поведение в период записи. Используйте её как большой корпус характеризационных тестов и добавляйте редкие, разрушительные, сезонные и юридически чувствительные пути.
В Working Effectively with Legacy Code Майкл Физерс описал характеризационные тесты как фиксацию того, что система делает сейчас. Для переписывания это полезно: старая реализация часто остаётся последней точной спецификацией. Но записанный результат доказывает текущее поведение, а не его правильность.
Снимайте запросы на границе с бизнес-смыслом. Это может быть HTTP-шлюз, тема сообщений, пакетный ввод, терминальная транзакция, файл, хранимая процедура или запуск задания. Сохраняйте маршрутизацию, класс доступа, локаль, бизнес-дату и состояние функций. Не собирайте секреты лишь потому, что они доступны. Токенизируйте счета, удаляйте учётные данные и храните контролируемое соответствие только для устойчивой личности между вызовами.
Каждому случаю нужны неизменный ID и происхождение: версия источника, время, форма запроса, снимок состояния, ожидаемые результаты и преобразование очистки. Вычислите хеш исходной записи и нормализованной фикстуры. Тогда проверяющий отличит изменение теста от изменения системы.
Полезная оболочка выглядит так:
{
"case_id": "close-004812",
"captured_at": "2026-03-31T23:58:14Z",
"business_date": "2026-03-31",
"request": {"operation": "post_invoice", "invoice_ref": "TKN-8821"},
"state_snapshot": "sha256:7d3f...",
"expected": {
"status": "posted",
"ledger_delta_minor": 18425,
"events": ["invoice.posted"]
}
}
Деньги хранятся в минимальных единицах: двоичная плавающая точка плохо подходит для границы приёмки. Событие названо, но одинаковые ID сообщения и метка времени не требуются. Правила для изменчивых полей задаёт политика сравнения.
У производственной выборки предсказуемые пробелы. В окно могут не попасть закрытие месяца и года, ошибки скрываются повторными попытками, редкие исправления выполняются в другой форме. Добавьте високосный день, пустой файл, максимальную длину, дубль, сторно, тайм-аут после commit и частичный пакет. Берите случаи из процедур, инцидентов, поддержки и ограничений схемы. Люди, закрывающие книги, обычно знают, где код лжёт.
Повтор не должен запускать внешние последствия. Направьте письма, платежи, файлы и сообщения в детерминированные заглушки. Если запрос нельзя обезвредить, выполняйте его в теневом пути без commit. Стенд, способный списать деньги клиента, для приёмки непригоден.
Разметьте корпус по операции, классу клиента, каналу, валюте, авторизации, границе даты, ошибке и типу эффекта. Голое число случаев вводит в заблуждение: тысячи простых чтений не покрывают ни одного сторно. Отчёт должен показывать пустые пересечения, чтобы владелец видел отсутствующие бизнес-сценарии, а не только красивый общий процент.
Паритету нужна явная политика сравнения
Побайтовое сравнение редко уместно. До запуска определите, какие различия имеют бизнес-смысл. Политика должна нормализовать изменчивое, точно сравнивать значимое и классифицировать всё остальное.
Сравнивайте полный наблюдаемый результат: ответ, изменения базы, сообщения, файлы, журналы аудита и видимое время. Одинаковый JSON может скрывать пропущенную проводку. Правильные строки могут сопровождаться неверным порядком событий. Проверка только удобной поверхности создаёт ложную уверенность.
Нормализация должна быть узкой. Заменяйте сгенерированные ID, только если личность не важна потребителям. Снижайте точность времени, только если порядок не важен. Сортируйте коллекции лишь по договору. Не исключайте поле потому, что оно часто меняется: сначала найдите зависимости и зафиксируйте правило.
Результат должен читаться без исходного кода стенда:
{
"case_id": "close-004812",
"result": "FAIL",
"comparisons": [
{"path": "$.status", "expected": "posted", "actual": "posted", "rule": "exact"},
{"path": "$.ledger_delta_minor", "expected": 18425, "actual": 18424, "rule": "exact"},
{"path": "$.processed_at", "expected": "<timestamp>", "actual": "<timestamp>", "rule": "normalized"}
]
}
Оставьте четыре исхода: пройдено, ожидаемое изменение, известный дефект и необъяснённое расхождение. «Почти совпало» не подходит. Изменение ссылается на решение и новый тест, дефект имеет владельца, необъяснённое расхождение блокирует утверждение.
Измеряйте покрытие по бизнес-измерениям: операция, класс счёта или клиента, канал, авторизация, валюта, граница даты, ошибка и побочный эффект. Показывайте пустые пересечения. Десять тысяч запросов счетов не заменят ни одного теста сторно.
Запускайте обе системы из контролируемого начального состояния. Общая изменяемая база исказит второй запуск. Восстанавливайте снимок или изолируйте копии. Фиксируйте часы, случайные числа, курсы и конфигурацию. Ответ изменяемого внешнего источника включайте в случай.
Не создавайте ожидаемый результат новой реализацией. Проверка её вывода на глаз и сохранение как эталона доказывают повторяемость, а не паритет. Оракулом служит старая система, независимо утверждённое правило или сверенные книги.
Отчёт хранит четыре состояния без смешения. Прошедший случай совпал по заранее заданному правилу. Ожидаемое изменение ссылается на утверждённое решение и новый тест. Известный дефект имеет владельца и срок. Необъяснённое расхождение остаётся блокирующим, даже если его переименование улучшило бы итоговую статистику.
Сверяйте деньги на границе проводки
Финансовая приёмка требует точного совпадения на бухгалтерской границе и объяснения каждого намеренного отличия. Общие итоги скрывают компенсирующие ошибки, дубли, неверные даты и суммы на чужих счетах.
Сравнивайте деньги в представлении бизнес-правила: целые копейки или фиксированный decimal с масштабом валюты. Не пропускайте расчёты через таблицы, которые молча меняют типы и показывают округлённое число поверх другого значения.
Сначала сравните число транзакций и бизнес-ID, затем каждую строку по организации, счёту, валюте, дате, дебету или кредиту и сумме. После этого сравните контрольные итоги, остатки и отчёты. Каждый слой находит свой класс ошибки.
Anti-join показывает недостающие и лишние проводки, группировка показывает суммы. Настройте этот запрос Postgres под настоящую бизнес-идентичность:
WITH old_totals AS (
SELECT entity_id, account_code, currency, effective_date,
SUM(amount_minor) AS amount_minor, COUNT(*) AS line_count
FROM old_postings
GROUP BY entity_id, account_code, currency, effective_date
),
new_totals AS (
SELECT entity_id, account_code, currency, effective_date,
SUM(amount_minor) AS amount_minor, COUNT(*) AS line_count
FROM new_postings
GROUP BY entity_id, account_code, currency, effective_date
)
SELECT COALESCE(o.entity_id, n.entity_id) AS entity_id,
COALESCE(o.account_code, n.account_code) AS account_code,
COALESCE(o.currency, n.currency) AS currency,
COALESCE(o.effective_date, n.effective_date) AS effective_date,
o.amount_minor AS old_amount, n.amount_minor AS new_amount,
o.line_count AS old_lines, n.line_count AS new_lines
FROM old_totals o
FULL OUTER JOIN new_totals n USING (entity_id, account_code, currency, effective_date)
WHERE o.amount_minor IS DISTINCT FROM n.amount_minor
OR o.line_count IS DISTINCT FROM n.line_count;
Для точных измерений запрос возвращает ноль строк. Разрешённый допуск кодируйте для конкретного правила и класса счетов, не глобально. Копейка на миллионе проводок не мала, а нулевой общий итог может скрыть две неверные записи.
Округление требует отдельных случаев. Укажите метод и этап: вверх от половины, к чётному, отсечение или правило валюты. round(sum(x), 2) может отличаться от sum(round(x, 2)). Воспроизводите распределение остатка, если Финансы не утвердили новое правило.
Сохраняйте ID снимка, версию запроса, количества строк, строки без пары, различия, итоги, исполнителя и утверждение. Нужен набор исключений, а не зелёный скриншот. Финансы должны проследить итог до проводок без помощи миграционной команды.
Сверяйте слоями и сохраняйте вывод каждого шага. После идентификаторов и количества идут строки, контрольные итоги и конечные остатки. Ищите взаимно компенсирующие ошибки, неверные эффективные даты и правильные суммы на неправильных счетах. Допуск для конкретного распределения не разрешает такое же отличие в налогах, денежных счетах или контрольном балансе.
Паритет не узаконивает каждый старый дефект
Неожиданный старый результат надо классифицировать как обязательный, терпимый, случайный или запрещённый. Каждому отклонению сопоставьте решение.
Обязательны договорные расчёты, потребляемые форматы, утверждённые процессы и контроли. Странное, но используемое поведение терпимо. Случайное не имеет потребителя и противоречит правилу. Запрещённое нарушает политику или создаёт неприемлемый риск.
Совет «заодно исправить всё» популярен: дефекты видны, новый код легко менять. Для приёмки он плох. Смешение поведения и платформы делает каждое расхождение двусмысленным и усложняет откат. Сохраните обязательное, изолируйте утверждённые исправления, остальное отложите до стабильной эксплуатации.
Для намеренного изменения сохраните старый случай и результат, утверждающего и новый результат. Отчёт отметит «ожидаемое изменение». Владельцы потребителей должны принять новый контракт. Исправленный налог всё равно ломает импортёр старого формата.
Исправления безопасности иногда ждать не могут. Не воспроизводите утечку или опасный ввод ради зелёного отчёта. Запишите обязательное изменение контроля, проверьте отказ и разрешённый путь, учтите риск отката.
Классификация не даёт молча транслитерировать устройство. Можно сохранить внешнее поведение, заменив таблицы очередями, разделив монолит или перенеся расчёт в Rust. Приёмка наблюдает контракты и эффекты, а не мёртвую структуру.
Журнал должен оставаться читаемым: ID случаев, старое и новое поведение, причина, утверждающий, влияние, откат и дата. Сотни необъяснённых строк не становятся принятыми после переименования в «известные различия».
Репетиция отката должна менять реальное состояние
Откат достоверен после выполнения в близкой к производственной среде, восстановления авторитетного состояния и продолжения без потерь и дублей. Чтение инструкции не проверяет доступы, артефакты, часы, очереди и людей.
До запуска выберите единицу отката и последнюю безопасную точку. После новых записей старая система сможет их прочитать или повторить? Если нет, выкладка должна остановиться до несовместимой записи.
Двойная запись добавляет третье поведение: восстановление при успехе только одной стороны. Без порядка, повторов и идемпотентности она увеличивает неопределённость. Надёжный журнал изменений с проверенным повтором часто понятнее двух синхронных commit.
Используйте производственные личности и контроли. Пусть запускает дежурный, а не автор автоматизации. Не выдавайте широкие временные права. Возьмите закреплённый артефакт, переключите маршрутизацию, восстановите данные и проведите пробные транзакции.
Запишите пять фактов:
- Условие и уполномоченный человек.
- Точные ID артефактов.
- Последнюю и первую подтверждённые транзакции.
- Сверку переходного интервала.
- Время и ручные действия.
Добавьте реалистичное осложнение: сообщение в пути, задержку зависимости, смену дежурных или обратимую запись новой схемы. Это проверяет границу, где аккуратные инструкции обычно ломаются.
После возврата сравните очереди, задания, контрольные итоги, авторизацию и подтверждения потребителей. Проверьте дубли и кэши. Сохраните время систем, а не составленный позже рассказ.
Если полный откат невозможен, называйте план восстановлением вперёд. Проверьте отключение неисправного пути, ремонт состояния и выпуск исправления. Нельзя подписывать несуществующую возможность отката.
После возврата маршрута одной проверки доступности мало. Сравните глубину очередей, плановые задания, авторизацию, контрольные итоги и подтверждения потребителей. Зафиксируйте последнюю транзакцию до переключения и первую после восстановления. Сверьте переходный интервал, чтобы доказать отсутствие потерянных сообщений, повторных списаний и старых данных из кэша.
Передача доказывает владение самостоятельными действиями
Инженеры владеют системой, когда могут объяснить, эксплуатировать, диагностировать, менять, развёртывать и восстанавливать её без привилегированной помощи авторов. Папка документов лишь помогает передаче.
Принимающая команда должна проследить запрос через сервис, очередь, базу и событие; найти внедрённый сбой; поменять правило и тест; собрать, развернуть и отменить изменение; затем выполнить восстановление и сверку.
Если команда не объясняет нормализацию, она не владеет политикой. Если только поставщик генерирует клиент или меняет секрет, сборка ему не передана. Неучтённая учётная запись означает непереданную эксплуатацию.
В пакет входят:
- Репозитории, файлы сборки, фиксация зависимостей, генерация и правила владения.
- Архитектурные решения, контракты, модели данных, угрозы и различия поведения.
- Точные инструкции по выпуску, откату, копированию, восстановлению, миграции, сверке и инцидентам.
- Панели, тревоги, цели сервиса, поля журналов и диагностические запросы.
- Доступы, ротация секретов, лицензии, границы поддержки и риски.
Закрепите версии и выполните чистую сборку в среде принимающей организации. Архивируйте инструменты, если лицензии разрешают. Сборка только на ноутбуке автора не закончена. Опишите, какие сгенерированные файлы хранятся и как создать остальные.
CodeHero привязывает поведение к оригиналу паритетным стендом на записанном производственном трафике и одновременно обновляет архитектуру; стенд должен остаться постоянной регрессией заказчика. В регулируемой среде изолированная установка требует владельцев для моделей, оборудования, обновлений, доступов и экспорта доказательств.
Перечислите технические и коммерческие зависимости: размещённую сборку, закрытый пакет, лицензию, учётные данные, получателя тревог, модель или скрытое утверждение. Удалите, передайте или явно примите их. Поддержка не заменяет инженерное владение.
Завершите обратным объяснением. Принимающие инженеры рассказывают авторам об архитектуре, рисках, границе отката, исключениях и первых действиях при инциденте. Пробелы получают владельцев и даты.
Принимающая команда должна самостоятельно внести небольшое изменение: поправить правило, обновить тест, собрать чистый артефакт, развернуть его в контролируемой среде и отменить. Затем она диагностирует внедрённый сбой по переданной телеметрии. Так обнаруживаются скрытые зависимости от закрытых пакетов, генераторов, лицензий, учётных записей и адресатов тревог, которые не видны в перечне документов.
Подпись должна фиксировать воспроизводимое решение
Финальная подпись называет точный выпуск, доказательства, исключения, риски и людей. Отсутствовавший человек должен восстановить причину решения и повторить основные проверки.
Создайте неизменный индекс: commit источника и цели, хеши артефактов, версии корпуса и политики, отчёт паритета, сверка, безопасность, производительность, репетиция, передача, решения и риски. Подпишите или хешируйте его и храните по правилам организации.
Не позволяйте одному проценту решать всё. Отчитывайтесь по утверждениям и измерениям с настоящими случаями. Финансам нужны строки и суммы, эксплуатации результат репетиции, владению выполненные задачи и пробелы.
Остаточный риск хранится в приёмке, а не в протоколе встречи. Опишите условие, влияние, обнаружение, ограничение, владельца и пересмотр. Риск без владельца остаётся незавершённой работой.
Задайте срок доказательствам. Новый выпуск, правило нормализации, схема, канал или бухгалтерская политика могут их отменить. Индекс говорит, что повторить. Приёмка относится к конкретной системе и условиям.
Порог запуска должен быть узким: нет необъяснённых отклонений обязательного поведения, сверка утверждена, восстановление выполнено, упражнения владения закончены. Для исключения нужен уполномоченный владелец.
Финальный индекс связывает commit, хеши артефактов, версию корпуса, политику сравнения, отчёт паритета, финансовый пакет, проверку безопасности, производительность, репетицию, передачу, решения и риски. Подпишите его или вычислите хеш. Человек, не присутствовавший на встрече, должен восстановить причину решения и повторить существенные проверки без памяти участников проекта.
Я отклонил бы красивый код со слабыми доказательствами. Короткий явный список дефектов допустим, если нужное поведение совпадает, книги сходятся, восстановление работает, а дежурные инженеры сами меняют систему. Подпись тогда фиксирует решение, уже доказанное машинами, счетами и практикой людей.
Вопросы
Что
должна
Достаточно
ли
Какой
процент
Нужно
ли
Как
сверить
Требует
ли
Как
проверить
Что
делать,
Какие
материалы
Кто
утверждает