Александр Фридман
Нет нужды говорить о необходимости использования систем управления исходными текстами (CMS) при разработке программного обеспечения. В данной статье мы покажем, как эти системы позволяют поддерживать полный цикл разработки ПО, в особенности для больших систем. Методы, описываемые здесь, применимы к большинству современных CMS, но прежде всего описание ориентировано на системы CVS (проект GNU) и PVCS (продукт компании Intersolv).
Самое первое (и простое) применение систем управления исходными текстами- это поддержка стадии разработки. Каждая из имеющихся на рынке систем позволяет хранить историю всех изменений файлов с исходными текстами, возвращаться при необходимости к предыдущим версиям и т. п. Изменения файла, помещенные в систему управления исходными текстами, называются версиями. Каждая версия имеет номер, обычно состоящий из двух чисел, разделенных точкой, например: 1.2, 2.0 и т. д.
При работе над проектом коллектива разработчиков эти системы обеспечивают целостность изменений. Для того чтобы внести изменения в текст программы, предварительно надо заблокировать соответствующий файл в CMS. Блокировка, во-первых, разрешает разработчику, заблокировавшему файл, вносить в него изменения, а во-вторых, запрещает блокировку всем остальным разработчикам. По завершении изменений они помещаются в CMS и файл разблокируется.
Таким образом, отдельный файл может изменять в один момент времени только один разработчик. Тем самым достигается непротиворечивость изменений.
В системе CVS по умолчанию блокировка отсутствует. Вместо этого, если файл одновременно модифицировался несколькими программистами, при каждом помещении изменений в систему управления исходными текстами проверяется, не затрагивают ли эти изменения одни и те же участки файла. Такой же режим можно установить и в PVCS.
В целом на стадии разработки использование систем управления исходными текстами достаточно просто и легко осваивается.
С переходом к следующим стадиям жизненного цикла программ- тестирование, эксплуатация, модификация - использование систем управления исходными текстами усложняется, но, с другой стороны, и потребность в подобных средствах увеличивается.
Первая проблема- составление версии большой программы, состоящей из многих файлов. Предположим, что наша программа состоит всего из двух файлов: main.cpp и main.h. Начальная версия системы была образована из версий обоих файлов с номерами 1.1. В следующей версии был изменен интерфейс системы, описанный в файле main.h. Эти изменения были записаны в CMS под номером версии 1.2. Файл main.cpp с соответствующими изменениями также получил номер версии 1.2. Однако в ходе тестирования были исправлены найденные ошибки и исправленный файл main.cpp получил номер 1.3. Таким образом, новая версия системы должна состоять из двух файлов: main.cpp версии 1.3 и main.h версии 1.2.
Составление версии системы из версии 1.2 файла main.cpp- это ошибка. Поэтому информацию о версиях всех файлов, составляющих систему, необходимо каким-либо образом запоминать. Простейшее решение состоит в использовании механизма меток. Каждой версии исходных файлов в системе управления текстами может быть присвоена символическая метка. Историю системы лучше отслеживать по меткам (табл. 1).
Таблица 1. Символические метки позволяют отследить историю системы
Обратите внимание, что версия 1.2 файла main.cpp никак не помечена. Эта версия отражает историю разработки, но не историю выпусков системы. Для того чтобы восстановить версию 1 системы, нужно извлечь все файлы, помеченные меткой Ver 1.1.
Полный цикл
Полные циклы разработки программ требуют более сложных манипуляций с системой управления исходными текстами. Для начала опишем гипотетическую (но вполне реальную) организацию проекта. В каждый момент времени над программным продуктом работают три группы. Первая- группа эксплуатации. Она либо использует готовый продукт внутри компании (для внутренних проектов), либо осуществляет поддержку пользователей этого продукта вне компании. В обязанности этой группы входит распространение новых версий программы по мере их готовности. Вторая группа- группа тестирования. По результатам тестирования она или возвращает систему на доработку, или “дает добро” на передачу очередной версии в эксплуатацию. Третья группа состоит из разработчиков, которые, собственно, и модифицируют код, разрабатывая новую версию системы либо исправляя ошибки.
При такой организации одновременно существуют по меньшей мере три версии системы: рабочая, эксплуатирующаяся версия, тестируемая версия и новая, разрабатываемая версия. Имеются три типичных сценария смены версий системы.
1. Идеальный. Тестовая группа не находит никаких проблем в тестируемой версии программы и передает ее в эксплуатацию, немедленно начиная тестировать следующую версию, которую передали ей разработчики.
2. Плановый. Тестовая группа находит ошибку в тестируемой версии и возвращает ее на доработку. После исправления ошибки тестирование продолжается.
3. Аварийный. Обнаруживается критическая ошибка в рабочей версии, требующая немедленного исправления. Разработчики делают исправления, тестовая группа должна прервать тестирование очередной версии, протестировать аварийные исправления, передать их в эксплуатацию и вернуться к плановому тестированию.
Первый сценарий не вызывает особых затруднений при отображении в системе управления исходными текстами. У каждого файла есть по крайней мере три метки, соответствующие трем упомянутым версиям. Поскольку передача версии в эксплуатацию не связана ни с какими изменениями исходного текста, изменения в метках не нужны.
Рассмотрим действия при реализации второго сценария (табл. 2).
Таблица 2. Ситуация до изменений версии
Если для версий используются “плавающие” метки, то ситуация после изменений выглядит так, как показано в табл. 3.
Таблица 3. Ситуация после внесения изменений
Опасность заключается в том, что информация о предыдущем варианте версии 1 утеряна и возврат к ней, равно как и сравнение с нею с целью определить, в чем же состояли изменения, крайне неудобен (нигде не зафиксирован тот факт, что версия 1.3 файла main.cpp была в предыдущем варианте версии 1). Исправить подобный недостаток можно, используя одновременно два типа меток: “плавающие” и “фиксированные”, отмечающие каждый вариант построения. Тогда ситуация в системе управления исходными текстами будет выглядеть так, как показано в табл. 4.
Таблица 4. Использование двух типов меток
Здесь каждому построению системы соответствует своя метка- Build 1, Build 2 и Build 3; эти метки никогда не перемещаются. Метки Ver 1.x перемещаются и отражают текущее состояние версий. Как можно видеть из табл. 4, версия 1.2 файла main.h участвовала в двух построениях, поэтому у нее две метки Build.
Такая система меток позволяет полностью сохранить историю разработки в системе управления исходными текстами и реализовать третий сценарий изменений- аварийное исправление работающей версии, после чего можно вернуться к тестированию версии 1. Пример состояния исходных текстов приведен в табл. 5.
Таблица 5. Аварийное исправление работающей версии
Не следует преувеличивать сложность структуры исходных текстов. Ответвления, получившиеся в результате исправления ошибок (версии 1.1.1 и 1.3.1 файла main.cpp), скорее всего, временные. Необходимые исправления будут внесены в новую версию системы, которая в настоящее время находится в разработке, и ветви не будут продолжаться. Наглядно процесс изменений файла main.cpp изображен на рис. 1.
Рис. 1. Процесс изменений файла main.cpp
Тем не менее система меток не совсем удобна. Основное неудобство заключается в том, что за все изменения меток ответственны разработчики. В частности, перед ними стоит задача определения каждого варианта построения, которая чаще возлагается на тестовиков. При наличии десятков, а то и сотен файлов в реальных системах и десятков разработчиков необходим более простой механизм определения варианта построения.
Для этого в системах управления исходными текстами существует механизм групп готовности (promotion group). Если в системе CVS существует только три группы: экспериментальная (Exp), стабильная (Stab) и работающая (Rel), то в системе PVCS количество, названия и структура групп настраиваются.
Прежде чем пояснить, как можно использовать группы готовности, отвлечемся на то, каким образом осуществляется построение систем. Широко распространены два метода такого построения. Первый заключается в регулярной перестройке системы- иногда ежедневной, иногда еженедельной. Такая практика применяется, например, в компании Microsoft. Каждую неделю строится новая версия системы, используемая для дальнейшей разработки и тестирования. Благодаря этому постоянно имеется свежая, относительно работоспособная версия продукта, которая в определенный момент времени может быть передана для “официального” тестирования.
Второй метод предусматривает значительно более редкий выпуск новых версий- может быть, несколько раз в год, а чаще просто в связи с готовностью новых функций или по окончании исправления ошибок.
Версии файлов, которые находятся в разработке, входят в экспериментальную группу. Перевод из экспериментальной в стабильную группу осуществляется разработчиками после завершения предварительного тестирования и означает необходимость включения в следующее построение системы этой версии файла. Для разработчиков гораздо проще работать с небольшим количеством групп готовности, чем со многими десятками меток. Наличие групп готовности не отменяет необходимости меток, которые служат для фиксирования истории разработки, и ответственность за их установку лежит на группе тестирования.
При работе с PVCS можно определить большее количество групп. Например, ввести группы Development (для версий файлов, находящихся в разработке), Unit-test (для версий, прошедших индивидуальное тестирование и предназначенных для интеграции), System-test (для версий, передаваемых на тестирование в тестовую группу), Production (для эксплуатируемых версий). Для групп System-test и Production вводятся дополнительные группы System-test-fix и Production-fix для плановых и аварийных исправлений. Движение одной версии файла представлено на рис. 2.
Рис. 2. Движение одной версии файла
Стандартно изменение происходит по вертикали. Первоначально новая версия файла заносится в группу Development. Если предварительное тестирование проходит успешно, эту же версию файла относят к группе Unit-test. Если и интеграционное тестирование проходит успешно, версию относят к группе System-test, и за дальнейшее изменение групп ответственной становится группа тестирования. Исправления ошибок для тестируемой версии помещаются в группу System-test-fix, откуда переводятся в группу System-test группой тестирования при очередном построении системы. Аналогично обрабатываются аварийные изменения работающей версии.
Разумеется, приведенная структура групп готовности- лишь пример, иллюстрирующий их возможное применение. В каждом конкретном случае стратегия использования систем управления исходными текстами программ своя. Эта стратегия должна быть определена исходя из специфики проекта и организации разработки. Главное здесь- обеспечить удобную и эффективную реализацию необходимых задач поддержки системы в соответствии с приоритетами конкретной задачи. Формулирование этих приоритетов, задач поддержки, стратегии построения системы и способов работы с системой управления исходными текстами- необходимые шаги в планировании любого реального проекта.
С Александром Фридманом можно связаться по адресу: afridman@glasnet.ru.