В любой дискуссии о версионировании — самые горячие споры обычно ведутся вокруг надуманной проблемы: «как нам при помощи правильной заверсионированности нивелировать нерадивость и низкую компетенцию наших сотрудников, не способных создавать обратно-совместимый код?».
Смотрите:
Не существует алгоритма, который позволяет определить, совместимые или же нет сделаны доработки по отношению в предыдущей версии. И более того, даже сами разработчики не всегда это могут определить. — https://habr.com/ru/articles/982740/
Это позор.
Да, обратная совместимость — как та самая сволочь с кафедры прикладной казуистики, превращает любую техническую дискуссию в философский трактат о природе времени и неизбежности смерти. Стоит кому-нибудь предложить сломать API, как тут же находится человек с горящими глазами, готовый час рассказывать о том, как это невозможно, как это разрушит экосистему и погубит всех котят в радиусе километра. Но правда в том, что большинство страхов об обратной совместимости — это именно мифы, подпитываемые ленью, невежеством или банальным нежеланием разбираться в проблеме.
Итак.
Миф №1: «Обратная совместимость требует сохранения всего старого кода навечно»
Нет. Обратная совместимость — это не мавзолей, где каждая строчка кода бальзамируется и выставляется на всеобщее обозрение. Это искусство создания переходных периодов, когда старое и новое существуют параллельно достаточно долго, чтобы пользователи успели мигрировать. Никто не требует держать костыли десятилетиями — достаточно дать людям полгода или год, четко объявить о deprecation, предоставить инструменты миграции и затем спокойно удалить устаревший код. Или не удалять — будьте уверены, в Уренгое есть КБ, инженеры которого все еще используют версию 0.1.0 вашего API; просто удалите документацию и вываливайте ворнинги прямо им в дышло^W терминал¹.
Проблема не в обратной совместимости как таковой, а в отсутствии политики версионирования и доверия к пользователям.
Миф №2: «Поддержка старых версий делает код нечитаемым»
Плохой код делает код нечитаемым. Обратная совместимость делает его просто немного более многословным. Если у вас функция превращается в монстра Франкенштейна только потому, что вы добавили опциональный параметр с дефолтным значением, проблема не в обратной совместимости, а в архитектуре. Хорошо спроектированный интерфейс позволяет расширяться без превращения в помойку. Да, придется написать пару adapter-функций, да, придется держать в голове контракт. Но это не магия и не квантовая физика — это обычная инженерная работа, которую делают миллионы программистов каждый день.
Кроме того, абстракции в виде адаптеров — нужны и так, если вы не на скрауливаете интернет на перле, конечно.
Миф №3: «Нельзя исправить старые ошибки, не сломав совместимости»
Да окститесь. Можно, разумеется. Более того, это делается постоянно. Добавьте новую функцию с исправленным поведением, пометьте старую как deprecated, дайте людям время перейти. Или используйте флаги совместимости, которые позволяют явно выбрать новое поведение. Или версионируйте API так, чтобы v2 жил рядом с v1, не мешая ему гнить в покое. Единственное, что действительно нельзя — это исправить ошибку так, чтобы об этом никто не узнал. Но это и не нужно: пользователи не идиоты, они понимают, что ошибки бывают, если только вы не пытаетесь делать вид, что ошибки — это фичи.
Не существует багов, вызванных тем, что вы принимаете в функции не те параметры, которые ей нужны для нормальной работы. Бывает мало параметров, бывают лишние, — но обе эти ситуации не требуют ничего ломать.
Миф №4: «Обратная совместимость душит инновации»
Муа-ха-ха. Инновации душит неумение думать. Обратная совместимость — это просто одно из ограничений, с которым нужно работать, как с производительностью или безопасностью. Да, она накладывает определенные рамки, но эти рамки не запрещают делать что-то новое — они требуют делать это аккуратно. История полна примеров систем, которые развивались десятилетиями, оставаясь обратно совместимыми: от HTTP до Linux kernel. Erlang обратно-совместим до первой публичной версии 80-х годов.
Если Google может добавлять новые фичи в Chrome, не ломая половину интернета, то и вы справитесь со своим API для обработки JSON.
Миф №5: «Пользователи сами виноваты, если используют недокументированное поведение»
Да, но нет. С технической точки зрения — да. С человеческой — нет. Если ваш код делает что-то определенное, люди будут на это полагаться, документировали вы это или нет. Это называется закон Хайрама: все наблюдаемое поведение вашей системы будет использоваться кем-нибудь. Даже внутри одной команды. Можно сколько угодно писать в README большими буквами «ЭТО ВНУТРЕННЯЯ РЕАЛИЗАЦИЯ, НЕ ТРОГАТЬ», но если это работает и решает чью-то проблему, оно будет использоваться². Винить пользователей за это — все равно что оставлять открытым люк посреди дороги и удивляться, что кто-то туда упал. Надо либо четко определять контракты и их границы, либо смириться с тем, что люди будут тащить в свой код всё, что плохо прибито.
¹ Вот как работает deprecation в одной из моих самых эзотерических библиотек на руби:

² Случай из жизни: в одной из моих библиотек мне нужно было парсить простенькие PlantUML/Mermaid диаграммки. Ради такого я не тащу в свои проекты монструозные зависимости, поэтому я быстренько набросал свой парсек в приватном пространстве и забыл. Спустя примерно год, я получил issue с претензией, что мой парсер не справляется с — не помню уже точно — типа, вложенными комментариями в стейтах.
Иными словами, чувак нашел мою библиотеку для правильной работы с конечными автоматами (!) и использовал её, чтобы недокументированными вспомогательными функциями парсить сложный PlantUML.
Так что выбор между всеми этими вашими SemVer, CalVer и прочие ShitVer — это споры о том, сколько чертей может уместиться на кончике ножа. Просто обеспечивайте обратную совместимость. Оставьте возможность вызвать первую версию API, даже, если сейчас мажор перевалил за двадцать.
Я делаю именно так — поэтому ни разу за взрослую карьеру мне не приходилось тратить бесценное время, калории и нервные клетки на раздумья о том, как правильно версионировать код.
Комментарии (4)

vkni
06.01.2026 16:33Вы, всё-таки, смешали в кучу коней и людей. Есть разные типы продуктов, разные типы экосистем.
И если "тут так заведено", то вы с попыткой держать обратную совместимость против толп не попрёте. Вот возьмите Питоновские библиотеки optparse и argparse - естественный вопрос, который возникае "АНАХУА?". Но там так заведено, и при попытке сделать что-то долгосрочное, вас опрокинут с какой-то из библиотек, что вы используете.
Есть коробочные продукты, которые используют Васи из Уренгоя. Тот же MS Word - это же ужас какой-то в плане обратной совместимости. Но это его хлеб. И там, конечно, сделаны адаптеры, XML и т.д. Но задача всё равно чертовски сложна. И Вася никакого сообщения об устаревании не увидит. А если будет видеть, то пользоваться Вордом станет невозможно.
Ну и т.д.
____________________________________________
Ещё есть момент такой: вот у Питона есть определённая репутация, так никто из разумных людей и не пытается делать на нём GUI или что-то долгосрочное и масштабное.
Хотя, конечно, понятно, в чей огород вы кидаете камни.

Roman_Cherkasov
06.01.2026 16:33Да, обратная совместимость — как та самая сволочь с кафедры прикладной казуистики, превращает любую техническую дискуссию в философский трактат о природе времени и неизбежности смерти.
Но вы ведь это и сделали.
В цитате которую вы привели выше - речь идет о том что некоторые изменения в коде - могут привести к последствиям, которые должны бы увеличить версию для того чтобы сказать - "Это новая реализация, предыдущее поведение - сломано".И по большому счету - это факт. Мы действительно, для какой-нибудь идеальной системы в вакууме, можем сказать - что мы сделали классную архитектуру, в которой изменения в одной части кода не приводят к изменению поведения другой части. Но настоящие продукты - это не всегда что-то идеальное. Сайд эффекты это не что-то редкое (и не всегда это плохо). И уж точно, называть позором, то что не идеальные системы существуют - моветон.
В предыдущей статье - речь о том как сигнализировать, о том что предыдущее поведение - не работает больше ожидаемым образом, а не о том как правильно поддерживать обратную совместимость. А вы говорите о том, что "Не делайте плохо, делайте хорошо и проблем не будет.". Нет - проблемы останутся, они будут безусловно реже и думать о них придется меньше. Но обратная совместимость - ломается. По вашему желанию или без него и не всегда это замечается во время. Только и всего.
Если что - не считаю что, изменение номера версии - нормальная история для того чтобы сказать о том что что-то изменено или сломано.

redfox0
06.01.2026 16:33версионируйте API так, чтобы v2 жил рядом с v1, не мешая ему гнить в покое
Несколько историй про ГИС:
в первой ГИС сразу заложили v1 и v2. Документация к v1 почти отсутствала, да этот и не нужно, ведь есть v2! Пока в один день разработчики не решили расширить объекты api, добавив новые обязательные поля. И при этом решив сохранить совместимость. Правильная реализация: создать v3 и поставить нужные валидаторы на входе, а v2 же недостающие поля заполнять каким-то значением по умолчанию или ничего не делать. Но разработчки пошли по своему пути: для v2 расширили количество полей, но сделать поля обязательными не смогли из-за нарушения обратной совместимости, поэтому полезность "нового" api стало стремиться к нулю, так как у разработчиков нет рычага давления на пользователей, чтобы те переходили на "новое" api;
в другой ГИС просто каждый год выходит новая версия с номером v1. Полностью не совместимая со старым api. На следующий год уже анонсировали, что уберут множество методов для api, единственная альтернатива - вносить данные руками через их веб-интерфейс;
и немного шедевральное, одна и та же функция, которая принимает ДВА разных типов объектов (часть полей совпадает). Внутри функция по "лишним" полям догадаывается, какой именно объект её передали, а потом конвертирует json в… excel. Ну а что, отлаженный парсер excel у разработчиков уже был (раньше система принимала только excel, потом быра расширена до json). Причём в json должны обязательно содержаться все ключи объекта, а если null, то его необходимо записать как пустую строку.
Wesha
Если Ваша библиотека включается в код какого-то вебсервера — они и не увидят никогда.