к библиотеке   к курсу Жоголева   к оглавлению   к высокоуровн. языкам - 3GL   к визуальным средам - 4GL

Brian Wilson Kernighan
Брайан Уилсон Керниган

Brian Wilson Kernighan - род. 1942, Торонто, Онтарио, Канада - соавтор знаменитого руководства "Язык программирования Си" совместно с автором языка Деннисом Ритчи. Соавтор языка AWK (Alfred Aho, Peter Weinberger, Brian Kernighan). В соавторстве с Робом Пайком написал также известные книги "Практика программирования" и "UNIX. Программное окружение". Последнюю часто называют своего рода "Библией для UNIX-программистов".

Технологии программирования (Software Engineering)

Основные технологические подходы

5.1. Ранние технологические подходы

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

5.1.1. Подход "кодирование и исправление"

Подход "кодирование-исправление" (code and fix) упрощенно может быть описан следующим образом. Разработчик начинает кодирование системы с самого первого дня, не занимаясь сколь-либо серьезным проектированием.

Все ошибки обнаруживаются, как правило, к концу кодирования и требуют исправления через повторное кодирование.

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

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

5.2. Каскадные технологические подходы

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

5.2.1. Каскадный подход

Каскадный подход (pure waterfall) считается "дедушкой" технологических подходов к ведению жизненного цикла. Фактически, его можно рассматривать как отправную точку для огромного количества других подходов. Сформировался каскадный подход в период с 1970 по 1985 годы. Специфика "чистого" каскадного подхода такова, что переход к следующему процессу осуществляется только после того, как завершена работа с текущим процессом (см. рис. 3.1). Возвраты к уже пройденным процессам не предусмотрены.

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

5.2.2. Каскадно-возвратный подход

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

5.2.3. Каскадно-итерационный подход

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

5.2.4. Каскадный подход с перекрывающимися процессами

Классический каскадный подход позволяет выполнять каждый процесс отдельной команде. Достаточно разумным является использование команды на том же самом процессе в следующей разработке. Каскадный подход с перекрывающимися процессами (waterfall with overlapping) предполагает наличие таких специализированных команд, позволяющих до определенной степени сократить передаваемую документацию. Следующий процесс начинается до завершения текущего (рис. 3.8). Более того, несколько процессов могут выполняться параллельно.

5.2.5. Каскадный подход с подпроцессами

Каскадный подход с подпроцессами (waterfall with subprocesses) очень близок подходу с перекрывающимися процессами. Особенность его в том, что с архитектурной точки зрения проект достаточно часто может быть разделен на подпроекты, которые могут разрабатываться индивидуально (рис. 3.9). В данном подходе требуется дополнительная фаза тестирования подсистем до объединения их в единую систему. Следует особое внимание обращать на грамотное деление проекта на подпроекты, которое должно учесть все возможные зависимости между подсистемами.

5.2.6. Спиральная модель

Спиральная модель (spiral model) была предложена Барри Боэмом (Barry Воет) в середине 80-х годов XX века с целью сократить возможный риск разработки. Фактически, это была первая реакция на устаревание каскадной модели. Спиральная модель использует понятие прототипа - программы, реализующей частичную функциональность создаваемого программного продукта. Создание прототипов осуществляется за несколько витков спирали, каждый из которых состоит из "анализа риска", "некоторого процесса" и "верификации" (рис. 3.10). Обращение к каждому процессу предваряет "анализ риска", причем, если риск превышения сроков и стоимости проекта оказывается существенным, то разработка заканчивается. Это позволяет предотвратить более крупные денежные потери в будущем.

Особенность спиральной модели - в разработке итерациями. Причем каждый следующий итерационный прототип будет обладать большей функциональностью.

5.3. Каркасные технологические подходы

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

5.3.1. Рациональный унифицированный процесс

Рациональный унифицированный процесс (rational unified process) [Фаулер, Скотт 1999] [Буч, Рамбо, Джекобсон 2000] вобрал в себя лучшее из технологических подходов каскадной группы. В нем выделяются четыре основные фазы, рассмотренные ранее в разд. 3.4.1.

А вот в период прохождения этих фаз и функционируют процессы (например, анализ и проектирование), которые к тому же состоят из ряда последовательных итераций (рис. 3.11).

Основные особенности данного подхода таковы:

5.4. Генетические технологические подходы

Название этой группы подходов дано под впечатлением от статьи Поттосина [Поттосин 1997], в которой термин "генетический" связывается с происхождением программы и дисциплиной ее создания.

5.4.1. Синтезирующее программирование

Синтезирующее программирование предполагает синтез программы по ее спецификации. В отличие от программы, которая написана на алгоритмическом языке и предназначена для исполнения на вычислительной машине после трансляции в исполняемый код, документ на языке спецификаций является лишь базисом для последующей реализации. Для получения этой реализации необходимо решить перечисленные ниже основные задачи (http://case.ispras.ru/PublicScripts/cgi-bin/lib.cgi/code_generation/autoreferat.html).

Автоматическая генерация программ по спецификациям возможна для многих языков спецификаций, среди которых особо выделим SDL, ASN.1, LOTOS, Estelle, UML.

5.4.2. Сборочное (расширяемое) программирование

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

Сборка может осуществляться вручную или быть задана на некотором языке сборки, или извлечена полуавтоматическим образом из спецификации задачи. В статье [Цейтин 1990] изложены основные направления для создания техники сборочного программирования.

Сборочное программирование тесно связано с методом повторного использования кода, причем как исходного, так и бинарного. Выделяют несколько разновидностей технологических подходов сборочного программирования, которые в значительной степени определяются базисной методологией.

5.4.3. Конкретизирующее программирование

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

Наиболее известная технология конкретизирующего программирования - это подход с применением паттернов проектирования [Гамма, Хелм, Джонсон, Влиссидес 2001]. Паттерн (шаблон) проектирования (design pattern) - описание взаимодействия объектов и классов, адаптированных для решения общей задачи проектирования в конкретном контексте. Проектировщик, знакомый с паттернами, может сразу применять их к решению новой задачи, конкретизируя их. Паттерны проектирования упрощают повторное использование удачных проектных и архитектурных решений.

Паттерн состоит из четырех основных элементов:

Дополнительно к паттернам существуют каркасы (framework) - наборы взаимодействующих классов, составляющих повторно используемый дизайн для конкретного класса программ. Каркас диктует определенную архитектуру приложения, в нем аккумулированы проектные решения, общие для проектной области. Например, существуют каркасы, которые используются для разработки компиляторов.

5.5. Подходы на основе формальных преобразований

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

5.5.1. Технология стерильного цеха

Основные идеи технологии стерильного цеха (cleanroom process model) были предложены Харланом Миллзом в середине 80-х годов XX века. Технология складывается из следующих частей (рис. 3.13) [Linger 1994]:

Процесс проектирования связан с представлением программы как функции, в виде так называемых "ящиков":

Замечание о методе ящиков
Обратим внимание на то, что понятия "черный" и "прозрачный" ящик уже встречались нами при рассмотрении тестирования программных продуктов. Метод ящиков удобен, когда нам надо работать с функциями либо с закрытой, либо с открытой реализацией.

Использование ящиков определяют следующие три принципа:

Черный ящик представляет собой точную спецификацию внешнего, видимого с пользовательской точки зрения поведения. Ящик получает стимулы s от пользователя и выдает ответ R. Каждый ответ черного ящика определяется его текущей историей стимулов SH как следующая функция:

(S, SH) -> (R)

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

Если следующим стимулом будет число 1, то на основании первой истории калькулятор выдаст ответ 3141, а на основании второй - 1. Определять поведение черных ящиков очень удобно с помощью табличных спецификаций.

Ящик с состояниями получаем из черного ящика выделением элементов истории стимулов, которые сохраняют состояние (инварианты состояний) в процессе выполнения действий в черном ящике. Функция преобразования ящика с состояниями выглядит так:

(S, OS) -> (R, NS)

Здесь OS - старое состояние, a NS - новое. Хотя с пользовательской точки зрения поведение черного ящика и ящика с состоянием выглядит одинаково, истории стимулов заменяются ссылками на старое состояние и новое состояние, требуемое преобразованием.

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

(S, OS) -> (R, NS) by procedure

Проектирование процедуры прозрачного ящика выглядит как последовательное определение функций назначения и преобразование их в структуру управления и новые функции назначения. Пример проектирования процедуры прозрачного ящика [Linger 1994] приведен на рис. 3.14.

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

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

5.5.2. Формальные генетические подходы

Сложились методы программирования, обладающие свойством доказательности и не теряющие это точное, накопленное знание [Поттосин 1997]. Три таких метода соответствуют уже исследованным генетическим подходам, но с учетом формальных, математических спецификаций.

Одной из наиболее интересных современных работ в области формальных генетических подходов является В-технология [Abrial 1996]. На ее основе была осуществлена разработка системы управления парижским метрополитеном "METEOR".

5.6. Группа ранних подходов быстрой разработки

Развитием и одновременно альтернативой каскадных подходов является группа подходов быстрой разработки. Все эти подходы объединяют следующие основные черты:

5.6.1. Эволюционное прототипирование

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

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

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

5.6.2. Итеративная разработка

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

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

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

5.6.3. Постадийная разработка

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

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

5.7. Адаптивные технологические подходы

Адаптивные технологические подходы были задуманы как подходы, поддерживающие изменения. Они только выигрывают от изменений, даже когда изменения происходят в них самих. Данные подходы ориентированы на человека, а не на процесс. В них необходимо учитывать в работе природные качества человеческой натуры, а не действовать им наперекор (http://www.martinfowler.com).

5.7.1. Экстремальное программирование

Наиболее концентрированно идеи быстрой разработки программ оказались выражены в подходе экстремального программирования (extreme programming) (http://www.extremeprogramming.org). Две основные черты, присущие быстрым разработкам, являются базовыми и в этом подходе. Методы, объединенные в данном подходе, не являются принципиально новыми. Однако именно их рациональное объединение и совокупное использование дает существенные результаты и успешно выполненные проекты [Бек 2000]. Наибольшую пользу подход экстремального программирования может принести в разработке небольших систем, требования к которым четко не определены и вполне могут измениться.

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

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

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

Уверенность в нормальной работе каждого отдельного теста постепенно формирует у разработчиков уверенность в нормальной работе системы в целом.

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

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

Для того чтобы выполнить задачу, ответственный за нее программист должен найти себе партнера (рис. 3.20). Окончательный код всегда пишется двумя программистами на одной рабочей станции.

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

5.7.2. Адаптивная разработка

В основу подхода адаптивной разработки (Adaptive Software Development - ASD) положены три нелинейные перекрывающие друг друга фазы - обдумывание, сотрудничество и обучение. Автор данного подхода Джим Хайсмит (Jim Highsmith) обращает особое внимание на использование идей из области сложных адаптивных систем.

Результаты планирования (которое само здесь является парадоксальным) в адаптивной разработке всегда будут непредсказуемыми. При обычном планировании отклонение от плана является ошибкой, которую исправляют. При данном подходе отклонения ведут к правильным решениям.

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

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

5.8. Подходы исследовательского программирования

Исследовательское программирование имеет следующие особенности (http://www.osp.ru/pcworld/2001/01/062.htm):

В основе исследовательского программирования в большей степени, чем в других подходах, лежит искусство.

5.8.1. Компьютерный дарвинизм

Название данного подхода было предложено Кеном Томпсоном (Ken Thompson). Подход основан на принципе восходящей разработки, когда система строится вокруг ключевых компонентов и программ, которые создаются на ранних стадиях проекта, а затем постоянно модифицируются. Все более крупные блоки собираются из ранее созданных мелких блоков.

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

Подход состоит из трех основных процессов:

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

к библиотеке   к курсу Жоголева   к оглавлению   к высокоуровн. языкам - 3GL   к визуальным средам - 4GL

Знаете ли Вы, что модификаторы - это операции, которые модифицируют объекты соответствующего им типа. Например, операция push для стека.

Bourabai Research Institution home page

Bourabai Research - Технологии XXI века Bourabai Research Institution