Переход от каскадной разработки к итеративнойPer Kroll, Director, Rational Unified Process, IBM
Оглавление
Из журнала Rational Edge: Модель совершенной методологии итеративной разработки во многом радикально отличается от совершенной модели каскадной разработки. Но на практике ни одна группа разработчиков не применяет эти подходы строго в соответствии с их моделями. В этой статье объясняется, почему группам может потребоваться плавный переход от каскадного к итеративному подходу; также указаны некоторые полезные шаги в этом направлении. Большинство групп разработчиков используют в своих проектах каскадный (waterfall - водопад, каскад) процесс. В чистом виде каскадный подход означат выполнение ряда фаз в строго определенном порядке: анализ требований, проектирование, выполнение/интеграция, тестирование. Тестирование откладывается до конца проекта, когда проблемы накапливаются настолько, что на их решение требуется много сил и времени; эти проблемы могут сорвать сроки выполнения проекта и надолго оставить ключевых членов группы без работы. На практике многие группы применяют модифицированный каскадный подход, разбивая проект на несколько частей, которые называются фазами или стадиями. Это помогает упростить интеграцию, позволяет раньше начать тестирование, раньше понять состояние проекта. При таком подходе код программ разбивается на разумные части, минимизируется код интеграции в виде необходимых для тестирования заглушек и драйверов. Кроме того, такой подход позволяет предварительно опробовать наиболее рискованные и трудные области, и на основе отзывов пользователей (обратной связи) изменять план проекта. Однако это не укладывается в рамки каскадного процесса в том смысле, что многие группы разработчиков могут принять изменение плана проекта после стадии 1 за крушение их первоначального проекта или неправильную постановку требований. И хотя модифицированный каскадный подход не исключает обратной связи, он также не поощряет ее. И наконец, желание минимизировать риск плохо сочетается с проектом, выполняемым по каскадной методологии. В данной статье рассматриваются преимущества итеративного подхода к процессу разработки программного обеспечения над традиционным каскадным подходом. Преимущества итеративного походаПри итеративном подходе, например, в принятом компанией IBM процессе Rational Unified Process (сокращенно RUP), выполняется последовательность шагов, которые называются итерациями. Каждая итерация включает в себя часть (иногда большую) стадий разработки (сбор требований, анализ, проектирование, выполнение и т. д.), показанных на рис. 1. Каждая итерация имеет четко определённый набор целей, а ее завершение обеспечивает частичную рабочую версию конечной системы. Каждая очередная итерация строится на основе предыдущих итераций, далее развивает, уточняет и совершенствует систему до завершения конечного продукта. На первых итерациях главное внимание уделяется требованиям к системе, а также анализу и проектированию; на завершающих итерациях главное внимание уделяется реализации и тестированию. Рис. 1. Итеративная разработка по методологии RUP. На каждой итерации выполняются: учет требования, анализ, проектирование, тестирование. Каждая итерация строится на основе предыдущих итераций; ее результатом является исполняемый файл, который на один шаг ближе к конечному продукту. Итеративный подход имеет преимущества над каскадным подходом по ряду следующих причин.
Некоторые руководители проектов не хотят применять итеративный подход, потому что считают его формой бесконечной и неуправляемой возни. Но в процессе RUP весь проект полностью управляем. Количество итераций, их длительность и цели - всё это тщательно планируется, задачи и ответственности участников четко определены. Кроме того, регистрируются объективные показатели прогресса. И хотя группа переделывает некоторые вещи от одной итерации к другой, эта работа тщательной контролируется. Четыре шага переходаВ большинстве каскадных проектов вся работа делится на фазы или стадии; мы также можем рассматривать это как первый шаг на пути к итеративному проектированию. Но затем, чтобы перейти к итеративному подходу, нам нужно применить другие принципы рабочего процесса, и достигается это в следующие четыре шага.
Рассмотрим эти шаги более подробно. Шаг 1. Создание функциональных прототипов на раннем этапеВ качестве первого шага на пути к итеративной разработке рассмотрим функциональные прототипы на фазах сбора требований и проектирования. Цели создания таких прототипов - уменьшить ключевые технические риски и лучше понять, что именно заказчик ожидает от создаваемой системы. Следует начать с трёх самых больших технических рисков и трёх самых крупных функциональных областей, которые нужно прояснить. Технические риски могут быть связаны с новой технологией, возможными технологическими решениями, которые значительно повлияют на всё решение в целом, а также с трудновыполнимыми техническими требованиями. Функциональные риски могут быть связаны с теми областями, в которых заказчики выдвинули нечёткие требования и критически важным функциям, а также с теми требованиями, которые имеют первостепенное значение для всей системы. Для каждого ключевого технического риска нужно спланировать прототип с целью уменьшить этот риск. Рассмотрим следующие примеры. Технический риск. В ходе выполнения проекта требуется перенести существующее приложение, чтобы оно могло работать поверх сервера IBM WebSphere Application Server. Пользователи уже жалуются на недостаточное быстродействие приложения, поэтому у вас есть подозрение, что вышеуказанный перенос может ещё более замедлить работу приложения. Прототип. Создайте архитектурный прототип, чтобы попробовать различные подходы к переносу приложения. Обратитесь за помощью к архитектору WebSphere. Оцените результаты, напишите архитектурные и проектные инструкции, чтобы группа разработчиков знала, что нужно и что нельзя делать. Это увеличит вероятность того, что быстродействие перенесенного приложения будет достаточно высоким, и исключит затраты на переделку на поздних этапах проекта. Технический риск. Вы создаёте новое приложение для планирования и оценки проектов по разработке программного обеспечения. Вам известно, что главным отличием этого приложения от уже имеющихся продуктов будет его способность хорошо поддерживать итеративное планирование. Но это также и одно из самых нечётких мест в технических требованиях. Прототип. Создайте функциональный прототип на основе предположений о том, какой именно должна быть поддержка итеративного планирования проектов. Продемонстрировав этот прототип различным представителям заказчика, вы обратите их внимание на планирование и узнаете от них, какие из ваших предположений оказались неправильными. Прототип поможет вам прояснить и уточнить требования к планированию; кроме того, вы получите от пользователей полезную информацию о том, насколько им полезно и удобно ваше приложение. Возможно даже, вы напишете код, который можно будет использовать не только в данном проекте. Шаг 2. Деление фаз подробного проектирования, выполнения и тестирования на итерацииМногие группы разработчиков испытывают затруднения с делением проекта на осмысленные итерации до получения более подробных сведений о проекте. Но если вы готовы вступить в фазу подробного проектирования, значит вы уже хорошо понимаете требования и представляете себе архитектуру. Значит, пришло время попробовать итеративную разработку! Можно использовать два основных подхода для определения того, что и на какой итерации нужно сделать. Обсудим достоинства и недостатки этих подходов. Подход 1. Разработка подсистем по одной или по несколько одновременно. Предположим, у вас есть девять подсистем, причем в каждой множество компонентов. Вы можете разделить фазы подробного проектирования, выполнения и тестирования на три итерации, каждая из которых нацелена на три из девяти подсистем. Это хорошо в том случае, если зависимости между подсистемами не слишком велики. Например, ваши девять подсистем должны предоставлять конечным пользователям четко определенный набор возможностей. На первой итерации можно разработать самые важные подсистемы, на второй итерации - менее важные, а на третьей - ещё менее важные. Такой подход имеет большое преимущество: если вы не успеете завершить проект к назначенному сроку, то хотя бы сделаете часть системы с наиболее важными функциями, причём эта часть будет действующей. Но такой подход не годится в случае многоуровневой архитектуры, когда подсистемы верхних уровней зависят от подсистем нижних уровней. Если строить подсистемы не одновременно, а последовательно одна за другой, то придётся начать с подсистем самого нижнего уровня, а затем последовательно переходить вверх от одного уровня к другому. Но для того чтобы правильно построить функции на нижних уровнях, обычно требуется проделать много работы по проектированию и разработке на верхних уровнях, поскольку они определяют то, что необходимо сделать на нижних уровнях. В результате создаётся парадоксальная ситуация, разрешить которую может второй подход. Подход 2. В первую очередь разрабатываются наиболее критически важные сценарии. При подходе 1 подсистемы разрабатываются последовательно по одной. А при подходе 2 главное внимание уделяется ключевым сценариям или, иначе говоря, ключевым способам использования системы, а затем добавляются остальные сценарии, менее важные. Насколько это отличается от подхода 1? Рассмотрим пример. Предположим, вы создаёте новое приложение, которое позволит заказчику вести работу с дефектами. Это многоуровневое приложение, которое будет работать поверх сервера WebSphere Application Server, а системой управления базами данных будет DB2. На первой итерации вы разрабатываете ряд сценариев, например, ввод простого дефекта без дополнительной информации. На второй итерации вы усложняете эти сценарии, например, дефект может влиять на последовательность производственных операций. На третьей итерации завершается создание набора функций ввода дефектов и обеспечивается полная поддержка нестандартных пользовательских записей, например, возможность сохранить частичную запись о дефекте, чтобы впоследствии вернуться к ней и продолжить работу с ней. При таком подходе вы работаете со всеми подсистемами на всех итерациях, но на первой итерации главное внимание уделяется самым важным вещам, а на последних итерациях внимание уделяется менее важным и менее трудным вещам. Подход 1 лучше при работе над системой с четко определенной архитектурой, например, при работе над расширением существующего приложения, при разработке нового приложения с простой архитектурой. В большинстве проектов со сложной архитектурой лучше применять подход 2, но итерации при этом нужно планировать так, чтобы на последних итерациях было не слишком много работы, иначе возможна задержка. Шаг 3. Создание базовой версии действующей архитектуры на раннем этапеЭтот шаг можно рассматривать как более формальный и организованный шаг 1: Создание функциональных прототипов на раннем этапе Что такое "действующая архитектура"? Действующая архитектура - это частичная реализация системы, созданная с целью продемонстрировать, что подобная архитектура способна поддерживать ключевые функции. Но более важно то, что при этом демонстрируется способность архитектуры удовлетворить требованиям по быстродействию, пропускной способности, объёму данных, надёжности, масштабируемости и т. д. Создание действующей архитектуры позволяет на следующих фазах уверенно строить на прочном фундаменте все функциональные возможности системы. Действующая архитектура - это эволюционный прототип, который в ходе своей эволюции будет сохранять проверенные функции и те функции, которые с высокой вероятностью удовлетворят требованиям к системе, когда архитектура будет завершена. Говоря другими словами, эти функции станут частью завершенной системы. В отличие от функционального прототипа, который создаётся на шаге 1, эволюционный прототип полностью охватывает все вопросы архитектуры. Создание эволюционного прототипа означает, что вы проектируете, реализуете и тестируете каркас, то есть архитектуру системы. На прикладном уровне функциональность системы будет неполной, но большинство интерфейсов между модулями системы будет реализовано, поэтому архитектуру можно компилировать и до некоторой степени тестировать. Выполните начальную загрузку и тесты на производительность. Такой прототип также показывает в действии ваши критически важные решения, в том числе выбор технологий, основных компонентов и интерфейсов между ними; прототип создан после того, как вы взвесили все за и против, спроектировали и реализовали архитектурные механизмы и шаблоны. Но как придумать архитектуру эволюционного прототипа? Главное - сконцентрироваться на самых важных вариантах использования, примерно от 20% до 30% всех услуг, которые системы должна предоставлять конечным пользователям. Далее приведены некоторые способы для определения самых важных вариантов использования.
Первому и последнему критериям из приведённого выше списка архитектор должен уделить больше внимания; руководитель проекта должен сосредоточиться в основном на первых двух критериях. Для каждого критически важного варианта использования определите самые важные сценарии, и используйте их для создания действующей архитектуры. Другими словами, спроектируйте, реализуйте и протестируйте эти сценарии. Шаг 4. Применение итеративного процесса с управлением на основе рисковЕсли вы выполнили описанные выше шаги 2 и 3, то очень близко подошли к модели "идеальной" итеративной разработки. Следующий шаг - объединить шаги 2 и 3, добавив управление разработкой на основе рисков и итеративную разработку. То есть описанный в RUP ряд итераций. RUP предлагает структурный подход к итеративной разработке, деля её на четыре фазы: обследование, проработка, построение системы, сдача её в эксплуатацию. Каждая фаза содержит итерации (иногда только одну итерацию), целью которых является создание технических результатов, необходимых для достижения целей данной фазы. Группа разработчиков выполняет столько итераций, сколько требуется для достижения целей фазы, но не более. Если после запланированного количества итераций не удаётся достичь поставленных целей, то необходима ещё одна итерация на этой же фазе, а значит и задержка срока завершения проекта. Чтобы избежать этого, уделяйте особое внимание тому, что требуется сделать на каждой фазе, каковы её цели. Например, на фазе обследования непродуктивно уделять слишком большое внимание требованиям. Ниже приведено краткое описание типичных целей фаз.
Множество способов сделать эти шагиВ этой статье мы описали постепенный переход в четыре шага от каскадного подхода к итеративному. Каждый шаг принесёт вам ощутимую пользу при минимуме затруднений. Некоторые группы разработчиков могут сделать сразу несколько шагов, другие - выполнить несколько проектов, сделав всего один шаг, и лишь после этого сделать следующий шаг. Какой бы способ движения этими шагами вы ни выбрали, они помогут вам сократить риски, связанные с изменениями процесса и организацией разработки. Примечания1 Подробное описание того, как разработка по методологии RUP осуществляется на практике, содержится в главах 5-8 книги The Rational Unified Process Made Easy (Пошаговое руководство по Rational Unified Process), авторы Per Kroll и Philippe Kruchten (Addison-Wesley, 2003). Дополнительная информация
|