"Время — деньги. Создание команды разработчиков программного обеспечения" - читать интересную книгу автора (Салливан Эд)

Средства управления исходным кодом

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

О чём пойдёт речь

Продукты по управлению исходным кодом хранят файлы с кодом, отслеживают их версии, управляют файлами, составляющими проект, и предоставляют следующие функции.

Хранение файла и его прошлых, настоящих и будущих версий

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

Отслеживание истории изменений для каждого файла

При любых изменениях в файлах система управления исходным кодом внесёт нужные сведения в историю изменений: дату, время, пользователя и обычно небольшое примечание пользователя о природе изменения и его масштабе. Часто эти комментарии — единственное, чем вы располагаете. (Эта информация поможет новым разработчикам втянуться в проект.)

Группирование файлов

С ростом сложности проекта возникает необходимость группировать файлы: по назначению (например, по подпроектам или подсистемам) или по функциям (например, тестовые задания, спецификации и документация).

Маркировка файлов, связанных с конкретным выпуском программного продукта

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

Блокировка и разблокировка файлов

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

Что туда входит

Удобное расположение всех файлов и информации, связанной с проектом — это страшная (но излечимая) головная боль при разработке ПО. В NuMega не было времени создавать обширную инфраструктуру или сложные процессы для поддержки грамотного документооборота. Поэтому мы решили просто поместить все файлы и документы проекта в систему управления исходным кодом. Это были:

• исходные файлы;

• файлы заголовков;

• файлы библиотек;

• сценарии компоновки;

• результаты компиляции;

• результаты компоновки;

• инструменты и файлы для установки программ;

• инструменты и файлы для тестирования;

• спецификации проекта;

• планы проекта (ПО, документации и тестирования);

• пользовательская документация;

• тестовые задания и сценарии;

• тестовые модули разработчиков.

Из собственного опыта

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

Заметим, что в систему управления исходным кодом мы поместили всё, что можно было представить, а не только исходный код. Если что-то использовалось в проекте или относилось к проекту, мы помещали это в систему.

Зачем это нужно

При помещении всех файлов проекта в систему управления исходным кодом вы получаете большие преимущества. Во-первых, неважно, что это за файл и когда вы подключились к работе над проектом, — вы почти наверняка найдёте нужный файл в системе управления исходным кодом, а это весьма ценно. Разработчик сможет найти планы тестирования, технический писатель — функциональные спецификации, а новый сотрудник — нужную информацию без предварительного знакомства с историей создания проекта. Во-вторых, храня все файлы проекта в системе управления исходным кодом, вы сможете использовать функции маркировки и блокирования файлов, управления версиями и ведения истории.

Например, в NuMega была возможность отслеживать изменения в планах, тестовых сценариях и документации для всего проекта. К тому же мы могли помечать целые наборы тестовых сценариев и пользовательской документации для каждого внутреннего этапа и для каждого основного или неосновного выпуска. Мы могли с точностью до символа воссоздать все файлы (не только файлы исходного кода) любого выпуска в истории проекта.

Особо отмечу включение в систему NuMega средств сборки: компиляторов, компоновщиков, заголовков и т.д. Чёткое управление этими средствами критично для обслуживания сборочной среды проекта. Официальная сборочная среда была всегда доступна в системе управления исходным кодом. Все разработчики и машины, на которых собирался проект, должны были использовать один и тот же набор файлов. Без исключений.

Так как для сборки продукта мы не полагались на локальные файлы (не содержащиеся в системе управления версиями), мы задействовали идентичную сборочную среду во всём проекте. Этот простой подход сэкономил нам немало времени. До применения такой системы мы постоянно сталкивались с проблемами при сборке из-за несовместимости между компиляторами разработчиков или искали труднонаходимые ошибки во время выполнения, вызванные несоответствием библиотек или заголовков.

И последнее (но не менее ценное) преимущество — централизация файлов в системе управления исходным кодом обеспечивает простое резервное копирование всего проекта. Одной командой мы могли создать резервную копню или просто скопировать весь проект на другой диск или другую машину.

Каковы их технологические возможности

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

• управление разработкой нескольких редакций продукта;

• управление разработкой нескольких версий одной редакции;

• применение общих компонентов, как в рамках одного, так и нескольких проектов компании;

• компоновка продукта на основе самого свежего набора файлов с исходным кодом (или на основе другого набора исходных файлов);

• поддержка локальных сборок для отдельных разработчиков.

Как ими управлять

Одна из главных задач в управлении проектом по разработке ПО — это контроль сложности проекта. Труднее всего справляться с исходным кодом и управлением конфигурацией. Хотя наше решение было не идеальным, оно все равно работало и помогло нам без особых проблем укладываться в сроки.

Мы использовали систему управления исходным кодом Visual Source Safe (VSS) компании Microsoft. Она предоставляет нужные нам основные функции, и у неё отличная цена — как раз для начинающего бизнеса. Хотя обсуждение VSS выходит за рамки этой книги, я расскажу о том, как мы приспособили этот продукт под наши нужды.

Основы структуры

Мы структурировали наши проекты по двум простым элементам: частям и продуктам. Часть — это компонент, используемый для компоновки программного продукта. Частями могут владеть разработчики, не являющиеся членами команды, работающей над проектом. Они могут обновлять свои части по собственному (однако согласуемому) графику, отличному от графика всего проекта. Продуктом являлся конечный пакет, продаваемый пользователям. Он складывался из уникальных для этого продукта частей и файлов. Храня в одном месте части и продукты, мы могли собирать различные редакции наших программ и одновременно поддерживать несколько параллельных направлений в разработке. Например, возможность выпускать исправления или пакеты обновлений, продолжая направлять все силы на разработку нового кода, была необходима и для поддержки, и для получения прибыли от следующих продуктов.

Структура и использование хранилища исходного кода

Все файлы, используемые при разработке наших продуктов, были рассортированы по трём папкам:

• Product Name — для файлов, относящихся к продукту;

• Environment — для файлов среды разработки;

• Imports — для сторонних файлов.

Папка Product Name содержала создаваемые нами файлы, необходимые для сборки, тестирования и написания документации к продукту (табл. 5-1). В ней были подкаталоги Branch для каждого варианта, над которым мы работали. В подкаталоге Parts хранились стандартные и совместно используемые компоненты, включаемые в продукт. И, наконец, для каждой редакции продукта имелся подкаталог Product. В каждой папке Product содержались необходимые для продукта части. Чтобы эта структура работала, нужно строго соблюдать соглашения об именах и не нарушать структуру. Координация изменений в частях и продуктах также была критичной.

Табл. 5-1. Примерная структура папки «Product Name».

$/Product_Name/ — Файлы, относящиеся к продукту

$/Product_Name/Branch/ — Различные направления в разработке

$/Product_Name/Parts/ — Совместно используемые файлы, входящие в продукт

$/Product_Name/Parts/Src/ — Исходный код для Parts (при необходимости совместно используется с/Products/Src)

$/Product_Name/Parts/Doc/ — Исходные файлы документации

$/Product_Name/Parts/Help/ — Исходные файлы справочной системы

$/Product_Name/Parts/Install/ — Исходный код программы установки

$/Product_Name/Parts/Patch/ — Исходный код вставок

$/Product_Name/Parts/Setup/ — Исходный код установщика

$/Product_Name/Parts/Samples/ — Исходный код с примерами

$/Product_Name/Parts/Tests/ — Исходный код тестов, тестовые задания и т.д.

$/Product_Name/Product/ — Редакции продукта Product Name (по одной папке на каждую редакцию)

$/Product_Name/Product/Output/ — Область для программ, созданных в других проектах

$/Product_Name/Product/Src/ — Исходный код продукта (при необходимости совместно используется с /Parts/Src)

$/Product_Name/Product/Doc/ — Файлы документации к продукту (совместно используется с /Parts/Doc)

$/Product_Name/Product/Help/ — Файлы справочной системы продукта (совместно используется с /Parts/Help)

$/Product_Name/Product/Imports/ — Импорт (совместно используется с /Imports)

$/Product_Name/Product/Install/ — Файлы для установки продукта (используется с /Parts/Install)

$/Product_Name/Product/Samples/ — Примеры для продукта (совместно используется с /Parts/Samples)

$/Product_Name/Product/Tests/ — Тестовые задания, тестовые сценарии (совместно используется с /Parts/Tests)

Из собственного опыта

Когда я пришёл в NuMega, для одного из продуктов было создано три каталога по именам разработчиков: Frank, Bill и Matt. Так как каждый работал над своим собственным кодом, они могли вносить изменения, не повреждая чужих файлов. Однако там было мало общего кода (одна большая структура данных для основных подсистем). Но это работало! Дальше нам нужно было увеличить команду разработчиков, и мы уже не могли обойтись без системы управления исходным кодом. Такая система позволила усложнить проект, удерживая его под контролем. Без неё я просто не могу представить ПО для разработчиков.

В папке Environment ($/Env) хранятся файлы, используемые командой разработчиков, но не являющиеся частью конечного продукта. Это все, начиная с инструментов и утилит и заканчивая стандартами создания кода и шаблонами для проекта. Папка Environment содержит файлы среды, описывающие среду с точки зрения разработчика, а также с точки зрения тестирования и документации. В NuMega мы хотели создать общую среду для команд разработчиков, и потому для этой цели мы создали специальный раздел в хранилище исходного кода. Вот примерный список подкаталогов, которые могут быть в этом разделе хранилища исходного кода (табл. 5-2):

Табл. 5-2. Примерная структура папки Environment.

$/Env/Dev/ ПО среды разработки и инструментальных средств

$/Env/Dev/Bin Исполняемые модули (подкаталог для каждого инструмента)

$/Env/Dev/Src Исходный код для этих инструментов (подкаталог для каждого)

$/Env/Dev/Doc Документация для этих инструментов (подкаталог для каждого)

$/Env/Dev/Etc Прочие файлы

$/Env/Test/ Инструментальные средства и файлы для тестирования

$/Env/Test/Bin Исполняемые модули

$/Env/Test/Src Исходный код и документация для этих инструментов

$/Env/Test/Doc Документация по среде тестирования

$/Env/Test/Etc Прочие файлы

$/Env/Documentation/ Документация по среде проекта

$/Env/Documentation/Templates Шаблоны проекта, шаблоны документации и справочники по стилям

$/Env/Documentation/Plans Планы и спецификации проекта, тестовых заданий и документации

$/Env/Documentation/Process Технологические документы проекта

$/Env/Etc Прочие файлы, не вошедшие в предыдущие категории

В папке Imports ($/Imports) хранились файлы или наборы инструментов из сторонних продуктов (табл. 5-3). Сами сторонние продукты в этой папке не содержались, там были только библиотеки и заголовки. В результате в разделе Imports проводилось совсем немного изменений. Однако так как эта область использовалась для хранения различных версий сторонних продуктов, было очень важно не вносить никаких изменений без чёткого осмысления, полного тестирования и учёта связей с элементами, на которые эти изменения могли бы подействовать.

Табл. 5-3. Примерная структура папки Imports.

$/Imports/RogueWave Библиотеки и заголовки RogueWave

$/Imports/ObjectSpace Библиотеки и заголовки ObjectSpace

$/Imports/Visual С Результаты компиляции, библиотеки и заголовки Visual С

$/Imports/Install Shield Библиотеки и заголовки Install Shield

$/Imports/Прочие Папки для каждого инструмента или библиотеки сторонних производителей

Компоновочная система

В NuMega мы писали сценарий сборки продукта на выделенной «компоновочной машине». Сценарий должен был выбирать нужные для сборки продукта файлы из системы управления исходным кодом. Эта информация включала как сами средства компоновки, так и исходные файлы, библиотеки, заголовки и другие необходимые компоненты. Для ведения процесса компиляции мы выбрали Nmake — популярное средство управления компоновкой. Nmake сначала собирает все части продукта, а затей компонует окончательные исполняемые файлы продукта.

Сценарий компоновки в качестве входных данных принимал метку сборки, позволяло нам создать определённые версии продукта. Так как мы маркировали и отбирали и средства сборки, и файлы продукта, то таким образом мы гарантировали надёжность сборочной среды. Сценарии компоновки также использовали стандартные переменные окружения и макросы, так что мы собирали все части и продукты посредством одного вызова. То, что наша компоновочная машина и разработчики использовали одни и те же сценарии компоновки, позволяло собирать файлы проекта просто и без ошибок.

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