В процессе разработки программных продуктов на платформе 1С:Предприятие часто возникает задача автоматизации управления версиями. Это может быть необходимо для ведения истории изменений в расширениях, версионирования внешних обработок или при организации процессов CI/CD. Казалось бы, задача тривиальна: нужно просто прибавить единицу к последнему числу в строке вида 1.0.3.11. Однако, как показывает практика и обсуждения профессиональных разработчиков, за этой простотой скрываются важные технические нюансы.
В этой статье мы подробно разберем несколько подходов к увеличению номера версии, проанализируем их преимущества и опасные стороны, а также выберем наиболее надежный метод, соответствующий современным стандартам разработки.
Рассмотрим подход, который часто называют «на смекалку». Его суть заключается в том, чтобы временно избавиться от разделителей (точек), превратить строку в число, увеличить его на единицу и вернуть точки на место. В самом упрощенном виде, который обсуждался на форуме, это выглядит так:
ТекущаяВерсия = "1.0.3.11";
НовоеЧисло = Число(СтрЗаменить(ТекущаяВерсия, ".", "")) + 1;
// Далее следует логика расстановки точек обратно
Проанализируем этот метод. На первый взгляд, он кажется изящным и коротким. Если мы имеем версию 1.0.3.11, убираем точки и получаем 10311. Прибавляем 1, получаем 10312. Если мы заранее знаем, что формат версии всегда строго фиксирован (например, по два знака на сегмент), мы можем легко вернуть точки.
Почему этот метод опасен в реальной разработке? Выясним причину: математический метод полностью игнорирует разрядность сегментов. Рассмотрим ситуацию, когда номер версии 1.0.0.9. При удалении точек мы получаем 1009, после инкремента — 1010. При попытке автоматического форматирования мы можем получить 1.0.1.0, хотя ожидалось 1.0.0.10. Если же количество цифр в сегментах разное (например, 1.2.10.5), математика и вовсе перестает работать корректно, так как «вес» разряда меняется непредсказуемо.
Разберем по шагам наиболее надежный и современный способ, который появился с развитием платформы 1С 8.3.6 и выше. Этот метод основан на использовании функций СтрРазделить и СтрСоединить. Он не зависит от длины каждого отдельного сегмента и гарантирует корректность результата.
Рассмотрим алгоритм действий:
Посмотрим на пример реализации этого алгоритма:
Функция УвеличитьВерсию(Знач ТекущаяВерсия)
ЧастиВерсии = СтрРазделить(ТекущаяВерсия, ".");
Если ЧастиВерсии.Количество() > 0 Тогда
// Индекс последнего элемента — это количество элементов минус 1
ИндексПоследнего = ЧастиВерсии.ВГраница();
ПоследнийНомер = Число(ЧастиВерсии[ИндексПоследнего]);
// Увеличиваем номер сборки
ЧастиВерсии[ИндексПоследнего] = Формат(ПоследнийНомер + 1, "ЧГ=0");
Возврат СтрСоединить(ЧастиВерсии, ".");
КонецЕсли;
Возврат ТекущаяВерсия;
КонецФункции
Преимущество этого подхода заключается в том, что он универсален. Неважно, сколько цифр в последнем сегменте — одна, две или десять. Мы работаем с конкретной частью версии, не затрагивая остальные. Этот метод также легко расширить. Например, если последний сегмент превышает 99, мы можем реализовать логику «переноса разряда» в предыдущий сегмент (Revision).
Иногда задача усложняется: нужно не просто прибавить 1, а соблюдать правила лимитов для каждого сегмента. Проанализируем ситуацию, когда версия имеет формат X.X.X.YY, где YY не может быть больше 99. Если текущая версия 1.0.3.99, следующей должна стать 1.0.4.0.
В этом случае нам потребуется цикл для обхода сегментов с конца в начало. Рассмотрим пример такой реализации:
Функция ИнкрементВерсииСПереносом(ВерсияСтрокой)
МассивВерсии = СтрРазделить(ВерсияСтрокой, ".");
Для Сч = -МассивВерсии.ВГраница() По 0 Цикл
Индекс = -Сч; // Обходим с конца
ТекущееЗначение = Число(МассивВерсии[Индекс]);
Если Индекс = МассивВерсии.ВГраница() И ТекущееЗначение < 99 Тогда
МассивВерсии[Индекс] = Формат(ТекущееЗначение + 1, "ЧГ=0");
Прервать;
ИначеЕсли Индекс = МассивВерсии.ВГраница() Тогда
МассивВерсии[Индекс] = "0";
// Цикл продолжится и увеличит следующий разряд
Иначе
МассивВерсии[Индекс] = Формат(ТекущееЗначение + 1, "ЧГ=0");
Прервать;
КонецЕсли;
КонецЦикла;
Возврат СтрСоединить(МассивВерсии, ".");
КонецФункции
Такой подход ближе к стандартам SemVer (семантического версионирования), где каждый сегмент имеет свой смысл: Major.Minor.Patch.Build. Хотя в 1С чаще используется четырехзначный формат платформы, логика инкремента может зависеть от внутренних правил компании.
Для тех, кто предпочитает лаконичность и работает в среде Windows, можно воспользоваться объектом VBScript.RegExp. Это позволяет решить задачу буквально в пару строк, используя поиск по шаблону. Мы можем найти последнюю группу цифр после точки и заменить её на увеличенное значение.
RegExp = Новый COMОбъект("VBScript.RegExp");
RegExp.Pattern = "(\d+)$"; // Ищем цифры в конце строки
Matches = RegExp.Execute(ТекущаяВерсия);
Если Matches.Count > 0 Тогда
СтарыйНомер = Matches.Item(0).Value;
НовыйНомер = Формат(Число(СтарыйНомер) + 1, "ЧГ=0");
НоваяВерсия = RegExp.Replace(ТекущаяВерсия, НовыйНомер);
КонецЕсли;
Этот метод очень мощный, так как позволяет работать даже со сложными строками версий, содержащими суффиксы (например, 1.0.3.11-beta). Регулярное выражение найдет именно цифровую часть и инкрементирует её.
Если вы работаете в современной конфигурации, построенной на базе Библиотеки стандартных подсистем (БСП), обязательно загляните в общий модуль ОбщегоНазначенияКлиентСервер. В нем часто содержатся вспомогательные методы для работы с версиями. Хотя функции инкремента там может не быть «из коробки», там есть функции СравнитьВерсии, которые помогут вам проверить корректность полученного результата. Использование стандартных библиотек — это признак хорошего тона в разработке на 1С.
Подведем итог нашему анализу:
СтрРазделить является «золотым стандартом». Он надежен, понятен и легко читается другими разработчиками.Выбирайте метод исходя из ваших задач, но всегда стремитесь к тому, чтобы код оставался понятным и устойчивым к изменению входных данных. Совместное использование СтрРазделить и СтрСоединить — лучший выбор для большинства задач в среде 1С.