Movatterモバイル変換


[0]ホーム

URL:


Семантическое Версионирование 2.0.0

Кратко

Учитывая номер версии МАЖОРНАЯ.МИНОРНАЯ.ПАТЧ, следует увеличивать:

  1. МАЖОРНУЮ версию, когда сделаны обратно несовместимые изменения API.
  2. МИНОРНУЮ версию, когда вы добавляете новую функциональность, не нарушая обратнойсовместимости.
  3. ПАТЧ-версию, когда вы делаете обратно совместимые исправления.

Дополнительные обозначения для предрелизных и билд-метаданных возможны какдополнения к МАЖОРНАЯ.МИНОРНАЯ.ПАТЧ формату.

Вступление

В мире управления процессом разработки есть понятие «ад зависимостей»(dependency hell). Чем больше растёт ваша система и чем больше библиотек выинтегрируете в ваш проект, тем больше вероятность оказаться в этой ситуации.

В системе с множественными зависимостями выпуск новой версии может быстропревратиться в кошмар. Если спецификации зависимости слишком жесткие, вынаходитесь в опасности блокирования выпуска новой версии (невозможностьобновить пакет без необходимости выпуска новой версии каждой зависимойбиблиотеки). Если спецификация зависимостей слишком свободна, вас неизбежнонастигнет версионное несоответствие (необоснованное предположение совместимостис будущими версиями).

В качестве решения данной проблемы я предлагаю простой набор правил итребований, которые определяют, как назначаются и увеличиваются номера версий.Для того чтобы эта система работала, вам необходимо определить публичный API.Он может быть описан в документации или определяться самим кодом. Главное,чтобы этот API был ясным и точным. Однажды определив публичный API, высообщаете об изменениях в нём особым увеличением номера версий. Рассмотримформат версий X.Y.Z (мажорная, минорная, патч). Баг-фиксы, не влияющие наAPI, увеличивают патч-версию, обратно совместимые добавления/изменения APIувеличивают минорную версию и обратно несовместимые изменения API увеличиваютмажорную версию.

Я называю эту систему «Семантическое Версионирование» (Semantic Versioning). Поэтой схеме номера версий и то, как они изменяются, передают смысл содержанияисходного кода и что было модифицировано от одной версии к другой.

Спецификация Семантического Версионирования (SemVer)

Слова «ДОЛЖЕН» (MUST), «НЕ ДОЛЖЕН» (MUST NOT), «ОБЯЗАТЕЛЬНО» (REQUIRED),«СЛЕДУЕТ» (SHOULD), «НЕ СЛЕДУЕТ» (SHOULD NOT), «РЕКОМЕНДОВАННЫЙ» (RECOMMENDED),«МОЖЕТ» (MAY) и «НЕОБЯЗАТЕЛЬНЫЙ» (OPTIONAL) в этом документе должны бытьинтерпретированы в соответствии сRFC 2119.

  1. ПО, использующее Семантическое Версионирование, должно объявить публичныйAPI. Этот API может быть объявлен самим кодом или существовать строго вдокументации. Как бы ни было это сделано, он должен быть точным иисчерпывающим.

  2. Обычный номер версии ДОЛЖЕН иметь формат X.Y.Z, где X, Y и Z — неотрицательныецелые числа и НЕ ДОЛЖНЫ начинаться с нуля. X — мажорная версия, Y — минорнаяверсия и Z — патч-версия. Каждый элемент ДОЛЖЕН увеличиваться численно.Например: 1.9.0 ->1.10.0 -> 1.11.0.

  3. После релиза новой версии пакета содержание этой версии НЕ ДОЛЖНО бытьмодифицировано. Любые изменения ДОЛЖНЫ быть выпущены как новая версия.

  4. Мажорная версия ноль (0.y.z) предназначена для начальной разработки. Всёможет измениться в любой момент. Публичный API не должен рассматриваться какстабильный.

  5. Версия 1.0.0 определяет публичный API. После этого релиза номера версийувеличиваются в зависимости от того, как изменяется публичный API.

  6. Патч-версия Z (x.y.Z | x > 0) ДОЛЖНА быть увеличена только если содержитобратно совместимые баг-фиксы. Определение баг-фикс означает внутренниеизменения, которые исправляют некорректное поведение.

  7. Минорная версия (x.Y.z | x > 0) ДОЛЖНА быть увеличена, если в публичном APIпредставлена новая обратно совместимая функциональность. Версия ДОЛЖНА быть увеличена,если какая-либо функциональность публичного API помечена как устаревшая (deprecated).Версия МОЖЕТ быть увеличена в случае реализации новой функциональности илисущественного усовершенствования в приватном коде. Версия МОЖЕТ включать в себяизменения, характерные для патчей. Патч-версия ДОЛЖНА быть обнулена, когдаувеличивается минорная версия.

  8. Мажорная версия X (X.y.z | X > 0) ДОЛЖНА быть увеличена, если в публичном APIпредставлены какие-либо обратно несовместимые изменения. Она МОЖЕТ включать всебя изменения, характерные для уровня минорных версий и патчей. Когдаувеличивается мажорная версия, минорная и патч-версия ДОЛЖНЫ быть обнулены.

  9. Предрелизная версия МОЖЕТ быть обозначена добавлением дефиса и сериейразделённых точкой идентификаторов, следующих сразу за патч-версией.Идентификаторы ДОЛЖНЫ содержать только ASCII буквенно-цифровые символы и дефис[0-9A-Za-z-]. Идентификаторы НЕ ДОЛЖНЫ быть пустыми. Числовые идентификаторыНЕ ДОЛЖНЫ начинаться с нуля. Предрелизные версии имеют более низкий приоритет,чем соответствующая релизная версия. Предрелизная версия указывает на то, чтоэта версия не стабильна и может не удовлетворять требованиям совместимости,обозначенными соответствующей нормальной версией. Примеры: 1.0.0-alpha,1.0.0-alpha.1, 1.0.0-0.3.7, 1.0.0-x.7.z.92.

  10. Сборочные метаданные МОГУТ быть обозначены добавлением знака плюс и рядаразделённых точкой идентификаторов, следующих сразу за патчем или предрелизнойверсией. Идентификаторы ДОЛЖНЫ содержать только ASCII буквенно-цифровые символыи дефис [0-9A-Za-z-]. Идентификаторы НЕ ДОЛЖНЫ быть пустыми. Сборочныеметаданные СЛЕДУЕТ игнорировать, когда определяется старшинство версий. Поэтомудва пакета с одинаковой версией, но разными сборочными метаданными,рассматриваются как одна и та же версия. Примеры: 1.0.0-alpha+001,1.0.0+20130313144700, 1.0.0-beta+exp.sha.5114f85.

  11. Приоритет определяет, как версии соотносятся друг с другом, когдаупорядочиваются. Приоритет версий ДОЛЖЕН рассчитываться путём разделения номеровверсий на мажорную, минорную, патч и предрелизные идентификаторы. Именно втакой последовательности (сборочные метаданные не фигурируют в расчёте).Приоритет определяется по первому отличию при сравнении каждого из этихидентификаторов слева направо: Мажорная, минорная и патч-версия всегдасравниваются численно. Пример: 1.0.0 < 2.0.0 < 2.1.0 < 2.1.1. Когда мажорная,минорная и патч-версия равны, предрелизная версия имеет более низкий приоритет,чем нормальная версия. Пример: 1.0.0-alpha < 1.0.0. Приоритет двух предрелизныхверсий с одинаковыми мажорной, минорной и патч-версией ДОЛЖНЫ быть определенысравнением каждого разделённого точкой идентификатора слева направо до тех пор,пока различие не будет найдено следующим образом: идентификаторы, состоящиетолько из цифр, сравниваются численно; буквенные идентификаторы или дефисысравниваются лексически в ASCII-порядке. Численные идентификаторы всегда имеютнизший приоритет, чем символьные. Больший набор предрелизных символов имеетбольший приоритет, чем меньший набор, если сравниваемые идентификаторы равны.Пример: 1.0.0-alpha < 1.0.0-alpha.1 < 1.0.0-alpha.beta < 1.0.0-beta <1.0.0-beta.2 < 1.0.0-beta.11 < 1.0.0-rc.1 < 1.0.0.

Зачем использовать семантическое версионирование?

Это не новая или революционная идея. Вероятно, вы уже используете что-топодобное. Проблема в том, что «подобное» — не достаточно хорошо. Безсоответствия формальной спецификации, номера версий практически бесполезны дляуправления зависимостями. Ясно определив и сформулировав идею версионирования,становится легче сообщать о намерениях пользователям вашего ПО. Когда этинамерения ясны, гибки (но не слишком), спецификации зависимостей наконец могутбыть созданы.

Простой пример демонстрирует, как Семантическое Версионирование может сделать«ад зависимостей» вещью из прошлого. Представим библиотеку, названную«Firetruck». Она требует Семантически Версионированный пакет под названием«Ladder». Когда Firetruck был создан, Ladder был 3.1.0 версии. Так как Firetruckиспользует функциональность версии 3.1.0, вы спокойно можете объявить зависимость отLadder версии 3.1.0, но менее чем 4.0.0. Теперь, когда доступен Ladder 3.1.1 и3.2.0 версии, вы можете интегрировать его в вашу систему и знать, что он будетсовместим с текущей функциональностью.

Как ответственный разработчик, вы, конечно, хотите быть уверены, что всеобновления функционируют как заявлено. В реальном мире полный бардак и ничегонельзя с этим поделать. Что вы можете сделать — это дать СемантическомуВерсионированию предоставить способ выпуска релизов без выпуска новых версийзависимых пакетов и сохранить вам время и нервы.

Если это звучит соблазнительно, всё что вам нужно — это начать использоватьСемантическое Версионирование, объявить, что вы его используете, и следоватьправилам. Добавьте ссылку на этот сайт в вашем README, тогда пользователи будутзнать правила и извлекать из этого пользу.

FAQ

Что я должен делать с ревизиями в 0.y.z на начальной стадии разработки?

Самое простое — начать разработку с 0.1.0 и затем увеличивать минорную версиюдля каждого последующего релиза.

Как я узнаю, когда пора делать релиз 1.0.0?

Если ваше ПО используется на продакшене, оно, вероятно, уже должно быть версии1.0.0. Если у вас стабильный API, от которого зависят пользователи, версиядолжна быть 1.0.0. Если вы беспокоитесь за обратную совместимость, вероятно,версия вашего ПО уже 1.0.0.

Не препятствует ли это быстрой разработке и коротким итерациям?

Мажорная версия 0 как раз и означает быструю разработку. Если вы изменяете APIкаждый день, вы должны быть на версии 0.y.z или на отдельной ветке разработкиработать над следующей главной версией.

Даже если малейшие обратно несовместимые изменения в публичном API требуют выпуска новой главной версии, не закончится ли это тем, что очень скоро версия станет 42.0.0?

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

Документирование всего API — слишком много работы!

Это ваша ответственность, как профессионального разработчика, правильнодокументировать ПО, предназначенное для широкого использования. Управлениесложностью ПО очень важная часть поддержки высокой эффективности проекта. Этотяжело сделать, если никто не знает, как использовать ваше ПО или какой методможно вызывать безопасно. В долгосрочной перспективе СемантическоеВерсионирование и настойчивость в качественном документировании публичного APIпоможет всем и всему работать слаженно.

Что мне делать, если я случайно зарелизил обратно несовместимые изменения как минорную версию?

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

Что я должен делать, если я обновляю свои собственные зависимости без изменения публичного API?

Это можно рассматривать как совместимые изменения, так как они не влияют напубличный API. ПО, которое явно зависит от тех же зависимостей что и ваш пакет,должно иметь собственные спецификации зависимостей и автор будет уведомлен овозможных конфликтах. Являются ли данные изменения уровня патча илиминорного уровня, зависит от того, обновили ли вы свои зависимости чтобыисправить баг или реализовать новую функциональность. В последнем случае, как правило,добавляется некоторое количество дополнительного кода и как следствие,увеличивается минорная версия.

Что если я нечаянно изменил публичный API в несоответствии с изменением номера версии (т.е. код содержит обратно несовместимые изменения в патч-релизе)?

На ваше усмотрение. Если у вас огромная аудитория, которая будет поставленаперед фактом возвращения прежнего поведения API, то лучше выпустить новый релизс увеличением главной версии, даже несмотря на то, что фикс содержит исправленияуровня патча. Запомните, в Семантическом Версионировании номера версийизменяются строго следуя спецификации. Если эти изменения важны для вашихпользователей, используйте номер версии, чтобы информировать их.

Что делать с устаревшей функциональностью?

Объявление функциональности устаревшей — это обычное дело в ходе разработки и частонеобходимо для продвижения вперёд. Когда вы объявляете устаревшим частьпубличного API, вы должны сделать две вещи: (1) обновить вашу документацию,чтобы дать пользователям узнать об этом изменении; (2) выпустить новый релиз сувеличением минорной версии. Прежде чем вы полностью удалите устаревшуюфункциональность в релизе с увеличением главной версии, должен быть как минимум одинминорный релиз, содержащий объявление функциональности устаревшей, чтобыпользователи могли плавно перейти на новый API.

Есть ли в SemVer лимиты на длину строки версии?

Нет, но руководствуйтесь здравым смыслом. 255 символов в строке версии, пожалуй,перебор. Кроме того, определенные системы могут предъявлять своисобственные ограничения на размер строки.

Об авторе

Авторство спецификаций Семантического Версионирования принадлежитТому Престон-Вернеру, основателю Gravatars исоучредителю GitHub.

Если вы хотите оставить отзыв, пожалуйста,создайте запрос наGitHub.

Лицензия

Creative Commons — CC BY 3.0


[8]ページ先頭

©2009-2025 Movatter.jp