Читаю книгу Егора “Наш код”. Хорошая книга, местами спорная, но ничего — просто держите в голове, что это Егор. Есть, однако, момент, мимо которого я не мог пройти молча — это эпизод с переговорами между двумя группами.

Я хотел привести оригинальный текст, однако электронной версии, откуда можно скопировать и вставить, в интернете нет. Поэтому расскажу завязку своими словами.

Есть группа разработчиков, которые пилят REST API, и есть группа потребителей. Понадобилась доработка сервиса, и потребители выдвигают условие: чтобы новые данные можно было забрать одним запросом. Разработчикам сервиса это неудобно: они сделали несколько новых методов, полагая, что потребители пошлют несколько запросов. Группы не сошлись во мнении, и начинается совещание.

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

Совещание идет по этим стадиям. Глава потребителей, азиат Бао, требует, чтобы сервис отдавал данные одним запросом. Это win-lose, потому что груз падает на плечи разработчиков. Адриан, их глава, торгуется: предлагает уменьшить число запросов с пяти до трех. Это lose-lose, потому что обе стороны вынуждены дорабатывать свой код, плюс уменьшение числа методов не решает главного конфликта: метод должен быть один.

И вот стороны находят решение, которое герой книги расценивает как win-win. Расширить один из написанных методов необязательным параметром. Если он передан, вдобавок к старым данным метод добавляет новые.

Теперь когда вы знаете сюжет, объясните мне, где здесь win-win и почему так считает герой книги? Спрашиваю, потому что никакого win-win нет не только в этой ситуации — его не существует в мире.

Если вы читали Джима Кемпа, то наверное помните, что половину книги он борется со стратегией win-win, доказывая, что она приводит к проигрышу. Я бы не повторял этот тезис, если бы не убедился в его правоте. Никакого win-win не бывает. Сложные переговоры не могут завершиться решением, которое одинаково устраивает всех. Если бы такое решение было, не понадобились бы и преговоры! Это же очевидно.

На практике одной из сторон всегда приходится уступить. Другими словами, win-win — это завуалированный win-lose, при этом lose приходится на ту сторону, которая искренне верит, что получила win. Если оппонент предлагает решение и утверждает, что это win-win, перед вами манипулятор. Win достанется только ему.

Сказанное не значит, что в каждых переговорах нужно стоять насмерть. Иногда приходится уступать, при этом из уступки можно извлечь пользу. Например, если доработка на моей стороне ничтожна, я соглашусь, сделав вид, что взваливаю на себя огромную ношу. В будущем это окупится: дадут премию, увеличат отпуск или освободят от внеурочной работы. Но в терминах переговоров это win-lose, потому что я взял обязательства к удовольствию другой стороны.

Вернемся к ситуации из книжки. Какие вышли итоги? Группа Бао хотела один вызов к сервису и получила его. Для них это однозначный win. Группе Адриана выпала доработка сервиса так, чтобы при необязательном параметре метод возвращал новые данные. Герой книги оценивает это как win, потому что API Адриана остался “правильно” спроектированным и его репутация не пострадала.

Тот, кто писал и поддерживал API, знает, что опциональные параметры крайне нежелательны. Каждый такой параметр порождает развилку if/else в коде, что усложняет его понимание. Больше ветвлений → больше кода → больше багов. Опциональный аргумент требует больше тестов. Исправляя уже написанный метод, есть шанс сломать его и выкатить ошибку на прод, особенно если не было тестов — а именно этот случай описан в книге.

Наконец, поведение, когда метод возвращает X, а при foo=true — связку (X + Y), говорит о плохом дизайне API. Каждый метод должен делать что-то одно, в том числе возвращать данные одной семантики. Если метод GET /users выводит пользователей и статистику покупок, он явно избыточен. Старому методу пришили вторую голову, но от этого он не стал лучше. Пишу это по следам похожих историй, когда в отлаженный API добавляли “маленький необязательный параметр”, от которого сложность росла кратно.

Кроме вреда от win-win, Кемп пишет о том, как важно придерживаться миссии на переговорах. Миссия — это не сиюминутная цель вроде “показать уродам, кто здесь главный”. Миссию Адриана можно сформулировать так: грамотно развивать сервис платежей, избегая спонтанных решений, с целью как можно дольше поддерживать код в читаемом виде, чтобы с легкостью адаптировать требования бизнеса.

Длинновато, но суть ясна. Как ясно и то, что решение о новом параметре противоречит миссии. Если бы Адриан следовал ей, вот что он бы сказал Бао.

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

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

Но в книге не так: Бао получил один запрос, группа Адриана выкатила неуклюжий метод “два в одном”. А поскольку герой относится к группе Адриана, я не понимаю, где здесь win. Может быть, вы понимаете?

В заключение напомню про книжку Кемпа. Горячо советую прочитать хотя бы первую ее половину. Тезисы удивительно точны и подтверждаются жизнью.