{ "index": 40, "slug": "editorial-2026-11-field-technology-evaluation", "title": "Как сравнивать технологии, когда цена ошибки выше цены эксперимента", "excerpt": "Сравнение технологий начинается не с рейтинга. Сначала нужно определить симптом, стоимость ошибки, критерии, измерение и границы вывода.", "contentHtml": "

На встрече появляется таблица из двух технологий и итоговых баллов: 86 против 74. Через неделю никто не может ответить, откуда взялись числа. Не указаны версии, входные данные, число повторов и правило обработки разброса. Симптом простой: вывод выглядит точным, но его нельзя воспроизвести.

\n

Цена ошибки зависит от решения. Если команда выбирает библиотеку для короткого скрипта, потеря обычно ограничивается временем разработчика. Если выбор затрагивает данные, задержки, безопасность и обслуживание, ошибка переезжает в архитектуру. Она увеличивает стоимость миграции, усложняет диагностику и заставляет защищать решение, основанное на неизвестных предпосылках.

\n

Тезис: сравнивать нужно не названия, а условия

\n

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

\n

Сначала отделите четыре вещи. Симптом показывает, что в текущем решении болит. Критерий описывает, что важно для новой альтернативы. Измерение даёт наблюдаемый сигнал. Риск показывает, чем обернётся неверный вывод. Вес критерия выражает приоритет. Он не доказывает свойство инструмента.

\n

Механизм: четыре слоя решения

\n

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

\n

Поэтому вопрос формулируют уже: «Как меняется время обработки сообщения заданного размера при одинаковом числе потребителей и одинаковой политике подтверждения?» Вопрос задаёт границы. Он не обещает ответа до измерения.

\n

Критерии должны быть наблюдаемыми или проверяемыми отдельно. Например: p95 времени обработки, доля повторной доставки, сложность миграции, требования к операционному сопровождению. В эти критерии нельзя незаметно включить симпатию к знакомому API. Если удобство важнее задержки, его нужно назвать и объяснить.

\n

Измерение требует протокола. Зафиксируйте версии, размер и форму входа, число потребителей, длительность прогрева, число повторов и способ вычисления итогового значения. Низкое среднее не компенсирует длинный хвост, если именно хвост ломает пользовательский сценарий.

\n

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

\n
\"Схема
Существующая схема показывает границы сравнения: критерии и условия измерения должны быть видимыми до вывода.
\n

Учебный пример: матрица для двух библиотек

\n

Ниже приведён учебный пример с условными именами queue-a и queue-b. Он не описывает конкретный продукт и не содержит данных реальной системы. Числа весов нужны только для демонстрации расчёта. Их нельзя выдавать за измеренный результат.

\n
Границы сравнения до получения чисел
КритерийВесЧто наблюдаемЧто пока неизвестно
p95 времени обработки35Миллисекунды на одинаковом входеЗначение для реальной нагрузки
Повторная доставка25Доля сообщений с повторомПричины отказов за пределами теста
Стоимость миграции25Список изменений и трудоёмкость шаговФактическое время команды
Сопровождение15Количество обязательных компонентовДолгосрочная нагрузка на операторов
\n

Сумма весов равна 100. Это проверка полноты, а не доказательство правильности шкалы. Для каждой строки задайте шкалу от 0 до 3 и опишите смысл каждого балла. Нельзя ставить ноль только потому, что данных ещё нет. Отсутствие наблюдения — это unknown, а не плохое значение.

\n

Пример кода с явной границей

\n
const criteria = [\n  { id: 'p95-latency', weight: 35, scoreA: 0, scoreB: 0 },\n  { id: 'redelivery', weight: 25, scoreA: 0, scoreB: 0 },\n  { id: 'migration-cost', weight: 25, scoreA: 0, scoreB: 0 },\n  { id: 'operations', weight: 15, scoreA: 0, scoreB: 0 }\n];\n\nfunction weightedScore(items, side) {\n  const weightTotal = items.reduce((sum, item) => sum + item.weight, 0);\n  if (weightTotal !== 100) return { status: 'stop-invalid-weights' };\n\n  const hasUnknown = items.some((item) => item[side] === 'unknown');\n  if (hasUnknown) return { status: 'stop-missing-observation' };\n\n  const score = items.reduce(\n    (sum, item) => sum + item.weight * item[side] / 3,\n    0\n  );\n  return { status: 'score-available', score };\n}\n\nconsole.log(weightedScore(criteria, 'scoreA'));\n// { status: 'score-available', score: 0 }
\n

Этот код показывает арифметику матрицы. Нулевые баллы здесь означают начальное состояние примера, а не качество queue-a. До подстановки наблюдений функция не выбирает библиотеку. Если один критерий получает unknown, она останавливается. Это важнее красивого итогового числа: неизвестность не должна маскироваться под результат.

\n

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

\n

Симптом → причина → проверка → действие

\n
Диагностика неубедительного сравнения
СимптомПричинаПроверкаДействие
Есть победитель, но нет исходных чиселПредпочтение выдали за наблюдениеНайти входы, версии, протокол и результаты повторовУбрать вывод и вернуть статус unknown
Среднее улучшилось, а ошибки вырослиСмотрели один показательСравнить p95, p99, ошибки и повторы на одном наборе входовДобавить критерий надёжности и пересчитать решение
Числа меняются после каждого запускаНе зафиксированы прогрев и окружениеСверить версии, ресурсы, размер входа и число повторовУточнить протокол или признать результат несопоставимым
Неизвестное значение заменили нулёмПропуск смешали с плохим результатомПроверить источник каждого баллаИспользовать unknown и остановить итоговую оценку
Миграция выглядит дешёвой по одной строкеНе учли данные, откат и обучениеСоставить карту изменений, зависимостей и обратного путиСчитать стоимость диапазоном с явными допущениями
\n

Порядок действий

\n
  1. Опишите наблюдаемый симптом: что именно изменилось, где это видно и кому мешает.
  2. Назовите цену ошибки: задержка, потеря данных, трудоёмкость отката или дополнительное сопровождение.
  3. Сформулируйте один вопрос с измеримыми входами и двумя сравниваемыми альтернативами.
  4. Выберите критерии, задайте шкалы и веса; проверьте, что каждый вес имеет объяснение, а сумма равна 100.
  5. Зафиксируйте версии, окружение, входные данные, прогрев, повторы и формулу расчёта.
  6. Проведите одинаковые измерения для каждой альтернативы и сохраните исходные значения, а не только средний балл.
  7. Отдельно проверьте хвост распределения, ошибки, повторную доставку и стоимость изменений.
  8. Отметьте неизвестные поля как unknown. Не делайте вывод, пока критичный критерий не получил наблюдение.
  9. Сравните результат с порогом решения и укажите, какие условия ограничивают перенос вывода.
\n

Ограничения и отрицательный путь

\n

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

\n

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

\n

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

\n

Проверяемый критерий готовности

\n

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

\n

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

\n

Проверяемые источники

" }