Я согласовал это решение. Теперь вижу ошибку

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

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

Через несколько дней ему присылают выгрузку второго поставщика. У товара идентификатор A-17. Прежний контракт такой товар описать не может. Веб-разработчик тем временем уже связал список с карточкой товара, а в мобильном клиенте готов разбор ответа с числовым полем.

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

Согласие уже превратилось в работу

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

Я бы сначала вернулся к разработчикам обоих клиентов, с которыми его согласовывал:

Я согласовал числовой id по первой выгрузке. В новой есть A-17, и по нашему контракту такой товар не передать. Предлагаю проверить переход на строку. Веб-клиент уже использует число, поэтому до правки схемы хочу понять, что у вас готово и что придётся менять.

Разработчик признаёт прежнее участие и объясняет, что изменилось. При этом переход на строку пока остаётся предложением: ещё предстоит понять, сколько работы он потребует.

В ответ на «ты же сам согласовал» я бы не стал объяснять, что ошибиться может любой. Вопрос сейчас в последствиях нашего согласия:

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

Если после разговора авторам клиентов всё равно предложат «как-нибудь успеть», признание ошибки ничего не изменит в их работе.

Что именно придётся переделать

Чтобы понять объём переделки, разработчики открывают уже готовые изменения:

Часть работы Что уже сделано Что меняется
API Схема ответа и примеры с числовым id Схема с новыми примерами ответа и проверка входных данных
Веб-клиент Список с переходом к карточке; выбранный товар сохраняется Числовое преобразование в адресе карточки и сравнение сохранённого идентификатора
Мобильный клиент Модель ответа и разбор данных Тип поля и проверка ответа с буквами в идентификаторе
Общая проверка Подготовлены сценарии по первой выгрузке Сценарии повторяются для второго поставщика и для прежнего товара со строковым id

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

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

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

Мне здесь важно не обесценить уже сделанное словами «там только тип поменять». Для автора API это может быть одна строка схемы. У клиента значение прошло через несколько мест, и о них лучше спросить того, кто их писал.

Что остаётся от прежнего контракта

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

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

Команда выбирает строку. Источник по-прежнему передаётся отдельно; пара из источника и id определяет товар. Сам id клиент хранит и возвращает без преобразования в число. Старый товар тоже получает строковый идентификатор: смешивать числа и строки в одном поле не договаривались.

Чтобы эта договорённость не осталась фразой «сделаем строки», разработчик API показывает ответ для обоих случаев:

[
  {
    "source": "north",
    "id": "42",
    "name": "Лампа"
  },
  {
    "source": "south",
    "id": "A-17",
    "name": "Светильник"
  }
]

Названия источников и товары здесь вымышленные. В примере меняется только представление идентификатора. Поле названия остаётся прежним, порядок выдачи не пересматривается. Заодно переименовать половину ответа было бы удобно автору API, но это расширило бы переделку для обоих клиентов.

Буквенный идентификатор включают в общие тестовые данные. Проверяют и старый товар: он должен по-прежнему открываться из списка после перехода с числа 42 на строку "42". Иначе команда рискует исправить новый случай, сломав тот, ради которого начала разработку.

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

Как изменится срок

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

Можно сказать «учтите переделку в оценке» и оставить каждому неприятный разговор с руководителем. Тогда каждый будет отдельно объяснять задержку, хотя причина переделки у них общая.

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

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

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

Автор API участвует и в переделке, и в пересмотре срока. Это не обязывает его брать на себя все проблемы проекта. Здесь он пропустил ограничение контракта и помогает разобраться именно с последствиями этого решения.

Вернуться к реализации

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

Веб-разработчик продолжает карточку, которая не требовала переделки, и убирает найденное числовое преобразование. Автор мобильного клиента меняет модель до подключения следующих экранов. Во вторник они вместе проходят путь от списка до сохранённого товара на обоих источниках. Если проверка не проходит, задача остаётся незаконченной, даже если все уже согласились с новой схемой.

Я бы возвращался к ошибочному решению вместе с теми, кто уже начал по нему работать. Объяснить причину изменения мало: нужно решить, что переделываем и когда теперь сможем закончить. Тогда остальные смогут продолжить работу, не пытаясь молча успеть с новым объёмом к прежнему сроку.