Программные продукты: от разработки к производству

№ 3 (27) 2010

Д. А. Тимофеев

Программные продукты: от разработки к производству

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

На протяжении всей истории создания программных продуктов предпринимался целый ряд попыток формулирования единого набора правил и методик создания программного обеспечения. Создателями самых известных процессов являются крупные компании — производители ПО. Например: MSF (Microsoft Solution Framework [3]) от компании Microsoft или RUP (Rational Unified Process) от компании Rational Software Corp. Но та же Microsoft использует для разработки собственных продуктов смесь MSF и Agile methodology, признавая, что полностью описанный, унифицированный фреймворк MSF несколько далек от практики. Многие успешные компании-разработчики программного обеспечения используют в качестве процесса производства компиляцию общепризнанных подходов и методик. В данной статье сделана попытка выделить те самые общие моменты, которые объединяют большинство существующих методологий, и рассмотреть их с практической точки зрения: что, когда и зачем применять. Пройдя через все этапы производства программного продукта, познакомимся с важными элементами этого процесса и их влиянием на конечный результат. Наличие или отсутствие тех или иных шагов и элементов в процессе производства программного продукта позволит сделать вывод о промышленном качестве или о любительской разработке. Что отличает эти два процесса? В первую очередь,

промышленная разработка предсказуема. Если команда разработчиков работает над разными задачами, но в рамках единого промышленного процесса производства ПО, можно с высокой вероятностью ожидать на выходе продукты одного качества. Это же относится и к планированию. Точность планирования очень важна при формировании бюджета и ресурсов. Промышленные процессы производства программного обеспечения позволяют планировать работу над задачами с одинаковой точностью от проекта к проекту. Главная задача команды разработчиков — высокое качество ПО и удовлетворенность заказчиков. Эти составляющие взаимосвязаны и непосредственно вытекают из процессов производста ПО и их качества. В случае формального подхода к работе в рамках унифицированного процесса качество продуктов будет находиться на низком уровне. И это является сигналом о необходимости улучшать существующие процессы: выявлять слабые места, изучать существующие процессы и best practices и применять лучшие из них на практике.

Полный цикл разработки программного продукта состоит из следующих основных стадий:

• анализ требований;

• разработка архитектуры;

• разработка продукта;

• тестирование;

• установка клиенту;

• поддержка.

№ 3 (27) 2010

В зависимости от используемых процес- время как другие процессы могут приме-

сов те или иные стадии циклически повторя- няться от этапа к этапу, на всем протяжении

ются в рамках релизов или отдельных под- жизненного цикла разработки программно-

задач. Упрощенная модель цикла разработ- го комплекса. Тем не менее, отталкиваясь от

ки представлена на рис. 1. этапов, можно более детально проанализи-

Есть процессы, свойственные только ровать многие процессы. Далее будут упо-

определенным этапам разработки ПО, в то мянуты этапы, имеющие прямое отношение

-ч ПРИКЛАДНАЯ ИНФОРМАТИКА

№ 3 (27) 2010 ' -

к самым важным процессам производства ПО, которые хотелось бы отметить в данной статье.

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

О том, что надо писать спецификации, знают все. Но часто не относятся всерьез к этому процессу и составляют их «для галочки». Спецификация позволяет разбить задачу любой величины на подзадачи, выявить проблемные области на ранних этапах, увидеть риски. Также она дает возможность оценить, правильно ли понял задание исполнитель. Качественно написанная спецификация — важный этап в процессе <| планирования и работы над проектом в це-§ лом.

§ При работе над спецификацией могут ^ быть выявлены некие проблемные зоны, ко-| торые должны быть учтены при составлении плана проекта. Как правило, такими зонами являются неизвестные разделы предметной ¡^ области, нехватка ресурсов и времени, про-

5 тиворечивость требований и др. И тут в игру вступает процесс управления рисками.

§ Каждый риск (проблемная зона) имеет ряд ¡Ц характеристик:

! • вероятность того, что это событие на-| ступит;

6 • критичность для бюджета, сроков или § функциональности проекта;

• ресурсоемкость выхода из данной ситуации (деньги, время, функционал) и т. д.

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

Планирование. Считается, что планированием должны заниматься менеджеры или руководители команд. На самом деле, в нем участвует каждый работник внутри проектной команды [2]. На этапе написания спецификаций весь проект разбивается на подзадачи. Часто бывает, что этого разбиения не достаточно для точного планирования. В таком случае исполнитель должен писать спецификацию более низкого уровня, разбивая задачу на более мелкие части, каждую из которых можно оценить с большей точностью. Более того, многие задачи содержат ряд типовых подзадач, на выполнение которых всегда требуется примерно одинаковое время, либо оно прямо пропорционально времени разработки. Это могут быть такие подзадачи, как написание спецификации, тестирование, cross code review, написание unit-тестов, развертывание на тестовых или рабочих серверах. Данные подзадачи можно оценить либо напрямую во временных единицах, либо в зависимости от времени разработки. В случае, когда все типовые подзадачи описаны и «взвешены», исполнителю остается только оценить объем работ и подставить это время в формулу, которая учтет весь набор подзадач и даст на выходе полное время работы над задачей. Данная формула индивидуальна для каждой команды разработчиков, т. к. она сильно связана с внутренними процессами, а также с типом решаемых задач. Приведем пример такой формулы:

№ 3 (27) 2010

Тзадача Т'кодирование + Танализ + Тюнит-тесты + + Т'тестирование + Тразвертывание.

Здесь Тзадача — суммарное время на работу команды над задачей;

Ткодирование — время, которое планирует затратить разработчик на написание исходного кода модуля, решающего поставленную задачу;

Танализ — время анализа. Обычно составляет 10-15% от Ткодирование. В зависимости от типа решаемых задач может быть как очень небольшим значением (типовые, многократно решенные в прошлом задачи), так и значением, во много раз превышающим время на разработку (ранее никем не решаемые задачи);

Тюнит-тесты — время написания модулей для автоматического тестирования исходного кода

приложения. Обычно 5°-7°% от Жирование. Также возможна обратная зависимость, так как unit tests пишутся до модуля, который они будут тестировать;

Ттестирование — время ручного тестирования, 20-40% от Ткодирование. На этот коэффициент влияет тип задачи;

Тразвертывание — Фемя развертывания прил°-

жения на тестовых или рабочих серверах. Как правило, данная процедура происходит автоматически и включает в себя единора-зовую подготовку скриптов для автоматической заливки приложения.

В силу указанной выше зависимости некоторых временных интервалов от времени кодирования имеем:

Танализ = Ткодирование Канализ , Тюнит-тесты = Ткодирование Кюнит-тесты , Ттестирование = Ткодирование Kтестирование ,

где K — соответствующие коэффициенты.

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

держивающими процессы производства ПО, и многое другое.

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

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

<u

J!

1

ч:

2 LQ

Время

Рис. 2. Изменения плана

57

-ч ПРИКЛАДНАЯ ИНФОРМАТИКА

№ 3 (27) 2010 ' -

то случаются потери изменений при заливке проекта с одного сервера на другой. Как эффективно работать над задачей распределенной команде?

Для успешной работы команды разработчиков над программным продуктом существует целый ряд техник и инструментов.

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

Хранилище исходного кода. Оно должно обладать целым рядом свойств: поддержка одновременного доступа к файлам, история изменений с возможностью возврата к предыдущим версиям, авторизация и <| идентификация пользователя. Хранилище | исходного кода позволяет хранить все ис-§ ходные коды проекта в одном месте, вес-^ ти лог всех изменений с указанием номера | версии, даты, имени программиста и описания изменений. Программ, которые реализуют функции хранилища, много. Возмож-¡^ но, самая популярная из бесплатных про-5 грамм — SVN1.

При работе с хранилищем надо строго § придерживаться правил и процедур. В дан-¡Ц ной статье приведем только некоторые ос! новные моменты, а более подробно о ра-| боте с SVN можно прочитать в материа-

о

^ 1

С ' http://tortoisesvn.tigris.org/

ле «Управление версиями в Subversion»2. В папке проекта должны быть три основные папки: trunk, branch и tag. Папка trunk содержит самую последнюю полную разра-ботческую версию проекта. В папке branch содержатся текущие незаконченные задачи разработчиков. В папке tag содержатся версии проекта, снимки релизов, различных версий рабочих серверов. Как правило, программист при получении новой задачи заводит отдельную папку в brunch, куда помещает последнюю версию из trunk. При работе над задачей все изменения идут в эту персональную папку и не затрагивают trunk. Периодически программист должен заливать себе в branch последнюю версию из trunk, чтобы быть уверенным, что его изменения не конфликтуют с основным проектом. По завершению работы над задачей программист еще раз заливает в branch последнюю версию из trunk, проверяет работоспособность и переносит свои изменения в trunk. Когда подходит срок релиза, в папке tag создается папка релиза, куда помещается код определенной версии из trunk. Вся дальнейшая работа с релизом происходит из этой папки. Любые изменения будут попадать в нее, а только потом в trunk. В какой-то момент все ошибки релиза будут исправлены, папка в tag будет переименована: к имени релиза прибавится пометка stable. Существует большое количество деталей и тонкостей, но основной процесс работы с хранилищем именно такой.

Еще одним очень важным инструментом является общее хранилище всех задач: ошибок, изменений, улучшений системы. Оно должно обладать следующими свойствами:

• к нему должны иметь доступ все члены команды разработчиков;

• необходимо иметь уникальный идентификатор для всех задач;

• каждая задача в любой конкретный момент времени должна находиться в определенной заранее известной стадии процесса работы над задачами данного типа;

2 http://svnbook.red-bean.com/

ПРИКЛАДНАЯ ИНФОРМАТИКА /-

' № 3 (27) 2010

• каждая задача на текущий момент времени должна быть поручена только одному вполне конкретному исполнителю;

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

Хранилище задач позволяет вести учет всех изменений системы, распределять те или иные задачи между релизами, служит единым местом постановки задач всем членам проектной команды. Примерами подобных систем являются FogBugz3 и Jiro4.

Юнит-тесты. Многие команды программистов вообще не используют юнит-тесты. Они просто пишут код и отдают его тестерам, задача которых убедиться, что все работает верно. И если с пользовательским интерфейсом такой вариант возможен, то с бизнес-логикой приложения могут быть проблемы. Предположим, один программист разрабатывает классы и методы DAL и BLL (Data Access Layer — уровень работы с данными, Business Logic Layer — уровень бизнес-логики), а другой программист разрабатывает пользовательский интерфейс. Тестеры смогут протестировать работу первого разработчика только после того, как второй закончит свою работу, и все модули будут объединены. Часто промежуток времени между окончанием работы первого программиста и началом работы тестера достаточно большой. Это не позволяет разработчику исправлять свои ошибки по «горячим следам», пока не забыты все особенности кода [1]. Юнит-тесты — это программные модули, которые тестируют внешние методы и свойства данного класса. Чаще всего юнит-тесты используются для тестирования классов бизнес-логики приложения, но иногда они пишутся и для DAL методов. Причем, юнит-тесты нужно писать до того, как написан код. Это позволяет программисту лучше понять суть задачи и обдумать детали до кодирования. Существует мнение, что можно экономить время и не писать юнит-

3 http://www.fogcreek.com/FogBugz/

4 http://www.atlassian.com/software/jira/

тесты. Но это прямой путь к продуктам низ- 8 кого качества с большим количеством труд- "g но исправимых ошибок. Поговорка «скупой S платит дважды» очень хорошо подходит для ^ данной ситуации — время, затраченное на продумывание структуры классов и написание юнит-тестов, будет многократно перекрыто временем переписывания плохо продуманных частей кода, выискиванием и исправлением ошибок.

Итак, команда использует хранилище, пишет юнит-тесты, применяет стандарт кодирования. Но типовые ошибки все равно возникают: при заливке кода на рабочие сервера забыли изменить настройки или запустить скрипт, программист не запустил юнит-тесты, и в хранилище попал нерабочий код, и т. д. Данные ошибки происходят, потому что типовые операции надо производить автоматически, а не вручную. Подумайте, сколько операций вам приходится делать каждый раз, когда вы хотите откомпилировать код, запустить юнит-тест, сделать сборку проекта, загрузить исходный код программы в хранилище, развернуть проект на тестовом или рабочем сервере. Сколько нажатий кнопок приходится делать? Правильный ответ — 1.

Заливка кода в branch автоматически запускает компилятор проекта, потом инициируется программа запуска юнит-тестов, потом собирается проект и разворачивается на разработческом тестовом сервере. И все это происходит автоматически. Результат приходит в виде отчета на почту. Такой процесс называется Continuous Integration (система постоянной интеграции). Для поддержки данной системы существует множество различных инструментов, от самых обычных «bat» скриптов до сложных систем с множеством настроек и параметров. Главное — желание автоматизировать любую последовательность шагов, которую вы выполняли уже несколько раз и которую вам еще не раз придется выполнить.

Тестирование. Данный процесс незаслуженно считается работой второго сорта. На самом деле, грамотный тестер играет не менее важную роль в проекте, чем ведущий

v 59

№ 3 (27) 2010

разработчик. При формировании требований тестер обязательно должен присутствовать и внимательно слушать представителей заказчика. Его задача — создать тест-план проекта — документ, описывающий стратегию и тактику будущего тестирования. При тестировании конкретной задачи тестер пишет тест-план задачи: набор шагов, которые необходимо выполнить с целью получения одного из двух возможных вариантов ответа: да или нет. Да — функционал работает, кнопка нажимается, символы появляются, рамка в нужном месте. Нет — не работает, не появляется, не там и не так. Третьего не дано. Также тестировщики используют инструменты автоматического тестирования интерфейсов. Как правило, такие инструменты используются для выполнения regression test — общего теста всей системы в целом для определения работоспособности ее основного функционала. Такой тест отвечает на вопрос, работает ли система в принципе. Как правило, основной функционал системы меняется редко, поэтому regression test — набор типовых шагов, которые требуется выполнять многократно на разных серверах при выходе нового релиза либо каких-либо внеочередных критических изменений. Правильней всего один раз написать скрипт для программы автоматического тестирования, а потом лишь вносить в него небольшие изменения по мере развития системы. и Процесс анализа всех проблемных § зон проекта после его завершения (Post § Project Review). Организатором данно-^ го процесса служит менеджер проекта. Он | сводит все проблемы воедино и формирует список участников обсуждения. Как правило, участие принимают все, кто работал над про-¡^ ектом. В ходе обсуждения рассматриваются 2 все проблемы по очереди и по каждой принимается решение. Как правило, проблемы бы-§ вают трех основных видов: случайные, ошиб-¡Ц ки исполнителей, недостатки процесса. ! Случайные проблемы — это все то, что | невозможно предугадать заранее и к чему & нельзя быть готовым: природные катаклиз-§ мы, экономический кризис, человеческий

фактор. И для таких ситуаций не существует типовых решений.

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

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

№ 3 (27) 2010

Таблица 1

Тест зрелости команды

Номер Вопрос Ответ

1 Используется ли хранилище исходного кода?

2 Используется ли хранилище задач/изменений системы?

3 Осуществляется ли билдинг ваших проектов в один шаг?

4 Создаются ли спецификации?

5 Планируются ли работы по проекту?

6 Тестируются ли работы по проекту?

7 Пишутся ли юнит-тесты?

8 Используется ли стандарт кодирования?

9 Проводятся ли процедуры Quality Assurance?

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

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

Джоэль Спольски5, основатель и владелец компании Fog Creek Software, один из создателей Excel в компании Microsoft, придумал тест «The Joel Test: 12 Steps to Better Code»6 («Тест Джоэля: 12 шагов к лучшему коду»). По материалам данной работы тест был несколько изменен и приведен в табл. 1.

Нужно ответить на 9 вопросов и подсчитать количество положительных ответов.

5 http://www.joelonsoftware.com/AboutMe.html

6 http://www.joelonsoftware.com/articles/fog0000000043. html

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

Результат 8 — неплохо. Но надо стремиться к максимальному результату. Нужно тщательно пересмотреть используемые инструменты, ресурсы и процессы и внести необходимые дополнения.

Результат 7 и ниже — плохо. Проблемы с планированием, качеством и объемами выполняемых работ, неудовлетворенность заказчиков. Чтобы претендовать на промышленный уровень разработки, необходимо пересмотреть текущие подходы и заняться внедрением процессов промышленного производства ПО. Не забывайте, что такие компании, как Microsoft, работают с результатом 9 каждый день.

Список литературы

1. Kent Beck. Test Driven Development: By Example. Addison-Wesley Professional, 2002.

2. Kent Beck, Martin Fowler. Planning Extreme Programming. Addison-Wesley Professional, 2000.

3. Michael S. V. Turner. Microsoft Solutions Framework Essentials. Microsoft, 2006.

4..... 61