Семантическое версионирование v2.0

Написано 21 Март, 2016 в категории Разработка ПО


Номер версии представляется как MAJOR.MINOR.PATCH, где увеличивается:
1. MAJOR версия, когда добавляется несовместимое с предыдущей версией api,
2. MINOR версия, когда ты добавляешь обратно-совместимую функциональность,
3. PATCH версия, когда ты добавляешь обратно-совместимое исправление ошибки.
Допускается добавление дополнительных меток для предварительного релиза и метаданных о сборке, как расширение формата MAJOR.MINOR.PATCH


Введение


В мире управления программным обеспечением есть внушающая ужас вещь, под названием "ад зависимостей" (dependency hell). Чем быстрее растет ваша система и чем больше зависимостей от сторонних библиотек она имеет, тем выше вероятность, что, в один прекрасный момент, вы попадете в эту яму отчаяния.
В системах с большим количество зависимостей выпуск новых версий может быстро превратиться в настоящий кошмар.
Для решения этой проблемы предлагается простой набор правил, определяющий, как должны назначаться номера версий. Эти правила основаны (но не ограничены) на, давно используемых, принципах нумерации проприетарного и свободного программного обеспечения. Для использования семантического версионирования необходимо определить публичный API (в виде документации или набора интерфейсов). Это очень важно, т.к. именно по характеру изменений этого API определяется, какую новую версию получит ваше программное обеспечение.


Правила Семантического Версионирования (СВ)

1. Программное обеспечение использующее СВ должно иметь публичный API (в виде документации или набора интерфейсов).

2. Стандартный номер версии должен иметь вид X.Y.Z - где X,Y и Z целые неотрицательные числа и не содержать ведущих нулей (т.е. не допускаются версии вида, например 1.01.0 - правильно 1.1.0). При внесении изменений в ПО должен изменяться один или несколько компонентов версии X, Y или Z.

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

4. В начале разработки MAJOR версия равно 0, версия имеет вид 0.Y.Z. Публичное API нестабильно. Все изменения API считаются обратно-совместимым, т.е при любом изменении API увеличивается Y компонент.

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

6. Z компонент версии (патч-номер версии) должен быть увеличен, только если внесены обратно-совместимые исправления ошибок. Исправление ошибки - это внутреннее изменение, исправляющее некорректное поведение без изменения публичного API. Также он МОЖЕТ увеличиваться при незначительных функциональных улучшениях кода без изменения публичного API.

7. Y компонент версии (минорный номер версии) должен быть увеличен, если добавлена новая обратно-совместимая функциональность в публичный API. Также Y должен быть увеличен если какие-либо функции публичного API помечены как устаревшие. Компонент Y МОЖЕТ увеличиваться, если внесены значительные функциональные улучшения кода без изменения публичного API, при этом Z компонент версии (патч-номер) должен быть сброшен в 0. Если одновременно с улучшениями производились исправления ошибок, то Z компонент версии можно не менять.

8. X компонент версии должен увеличиваться при внесении обратно-несовместимых изменений в публичный API. Если одновременно с этим были обратно-совместимые изменения API и исправление ошибок не меняющих API, то компоненты Y и Z можно не менять. При изменении X компонента, компоненты Y и Z должны быть сброшены в 0.

9. Предрелизные версии могут быть обозначены путем добавления дефиса и идентификаторов, разделенных точкой, сразу после версии патча. Идентификаторы могут содержать только символы из набора [0-9A-Za-z]. Числовые идентификаторы не должны содержать ведущий ноль. Предрелизная версия указывает на то, что соответствующая версия публичного API еще не стабильна. Примеры нумерации: 1.0.0-alpha, 1.0.0-alpha.1, 1.0.0-0.3.7, 1.0.0-x.7.z.92

10. Метаданные сборки могут быть добавлены в конец релизной или предрелизной версии после знака "+". Метаданные сборки - это один или несколько непустых идентификаторов разделенных точкой. Идентификаторы могут содержать только символы из набора [0-9A-Za-z]. При определении старшинства версии метаданные сборки не учитываются, т.е. если 2 версии отличаются только метаданными сборки - эти версии имеют одинаковый приоритет. Пример: 1.0.0-alpha+001, 1.0.0+20130313144700, 1.0.0-beta+exp.sha.5114f85.

11. Старшинство версий должно рассчитываться путем сравнения X, Y, Z. При определении очередности слева направо сравниваются соответствующие компоненты версий. Например: 1.0.0 < 2.0.0 < 2.1.0 < 2.1.1. Когда X, Y и Z версий соответственно равны - смотрим какая из версий является предрелизной, релизная версия всегда старше. Например: 1.0.0-alpha < 1.0.0. Сравнение предрелизных версий производится слева направо, числовые идентификаторы сравниваются как число, а символьные - лексически. Числовые идентификаторы имеют меньший приоритет, чем лексические. Набор из большего количества идентификаторов имеет больший приоритет, чем набор из меньшего количества идентификаторов, при условии что все идентификаторы меньшего набора расположены в том же порядке, что и большего. Например: 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.


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

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

Рассмотрим пример в котором есть приложение "Пожарная машина", которое зависит от библиотеки "Лестница". Библиотека "Лестница" использует семантическое версионирование. Приложение "Пожарная машина" использует библиотеку "Лестница" версии 3.1.0, т.к именно в этой версии были добавлены необходимые приложению функции. Это означает, что мы можем указать для приложения "Пожарная машина" диапазон совместимых версий библиотеки "Лестница" [3.1.0, 4.0.0). Это означает, что если в системе будет библиотека "Лестница" версии 3.1.1 или 3.2.5, то приложение "Пожарная машина" будет работать так же хорошо как и с версией 3.1.0
Однако с версией 4.0.0 и выше приложение может быть уже несовместимо.

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

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

FAQ

→ Как менять версии формата 0.Y.Z на стадии разработки?
↑Самое простое - это начать с версии 0.1.0, а затем увеличивать Y при каждом новом выпуске, т.е. использовать 0.Y.0 (если вам не принципиально что вошло в новую версию, улучшения или исправления ошибок).

→ Как определить что пора выпускать версию 1.0.0?
↑Как только от Вашего ПО начинает зависеть стороннее ПО или пользователи - смело ставьте версию 1.0.0

→ Если даже при малейшем изменении обратной совместимости в публичном API надо увеличивать X компонент версии, не получится ли так что он быстро вырастет до больших значений, например, 42.0.0?
↑Это вопрос планирования и предвидения развития Вашего ПО. При изменении публичного API следует помнить, что это влечет изменение зависимого ПО, что может быть очень затратно с экономической точки зрения.

→ Как удалять из публичного API устаревшие части?
↑Устаревание кода является неотъемлемой частью разработки ПО и часто необходимо для успешного развития. Когда вы помечаете часть публичного ПО, как устаревшее, вам необходимо выпустить минимум один минорный релиз, чтобы переход на новый код был плавным, и подробно описать в документации произведенные изменения.

→ Есть ли ограничение на длину строки версии?
↑Данная спецификация не накладывает никаких ограничений. Просто используйте здравый смысл.

Вольный перевод с дополнениями для Оригинал