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

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

3.3.3.2 Анализ влияния изменений требований

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

1) определить, как каждое предлагаемое изменение требований повлияет на проект;

2) на основе матрицы связей выявить другие требования, элементы архитектуры, исходный код и сценарии тестирования, которые, возможно, придется изменить;

3) определить, что необходимо для реализации изменений, и оценить затраты на реализацию.

3.3.3.3 Создание базовой версии и управление версиями требований

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

3.3.3.4 Ведение журнала изменений требований

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

3.3.3.5 Отслеживание состояния всех требований

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

3.3.3.6 Отслеживание проблем с требованиями

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

3.3.3.7 Создание матрицы связей (трассировки) требований

Всегда полезно, а иногда и обязательно, собирать наборы связей, которые соединяют отдельные функциональные требования с элементами архитектуры и кода, которые реализуют эти требования, а также с тестами для их проверки. Такая матрица связей требований помогает при проверке, все ли требования реализованы и проверены. Она также полезна на этапе обслуживания, когда требование нужно изменить. Матрица связей требований позволяет также сопоставить функциональные требования с требованиями более высоких уровней, на основе которых они созданы, и с другими родственными требованиями. Заполнять эту таблицу необходимо в ходе, а не в конце работы над проектом. Обязательно использовать для этих целей специальные программные средства. Возможные связи отслеживания требований приведены на рисунке 3.7.

Рисунок 3.7 – Возможные связи отслеживания требований (Карл Вигерс, 2014)

3.3.3.8 Использование средств для работы с требованиями

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

3.4 Итоги занятия

ü Одним из важнейших процессов программной инженерии является разработка и управление требованиями.

ü Данный процесс должен быть явно определен.

ü Существуют разные категории требований.

ü Ключевую роль в процессе разработки и управления требованиями играет бизнес-аналитик (данная роль всегда присутствует в проекте явно или неявно).

ü Управление требованиями не менее важный процесс, чем разработка требований.

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

ü Очень неплохим вложением в успех организации станет приобретение и развертывание специальной системы управления требованиями.

 

Если вас заинтересовала данная область знаний, рекомендую читать книгу Карла Вигерса «Разработка требований к ПО» 2е издание 2014.

 

Спасибо за внимание!

4. Проектирование

4 часа

«Есть два способа разработки проекта приложения: сделать его настолько простым, чтобы было очевидно, что в нем нет недостатков, или сделать его настолько сложным, чтобы в нем не было очевидных недостатков»

Хоар, Чарльз Энтони Ричард – английский учёный, специализирующийся в области информатики и вычислительной техники, лауреат премии Тьюринга, разработчик алгоритма быстрой сортировки т.д.

4.1 Основы проектирования

Проектирование ПО определяется как процесс определения архитектуры, компонентов, интерфейсов, и других характеристик системы или ее компонентов. Проект ПО (или дизайн) определяется как результат [этого] процесса.

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

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

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

Проектирование ПО как область знаний связано с разработкой требований, конструированием, моделированием ПО и качеством ПО.

 

4.1.1 Основные концепции проектирования ПО

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

4.1.2 Контекст проектирования

Для понимания роли проектирования ПО важно понимать контекст, в котором осуществляется проектирование и используются его результаты. В качестве такого контекста выступает жизненный цикл программной инженерии, а проектирование напрямую связано с результатами анализа требований, конструированием программных систем и их тестированием. Стандарты жизненного цикла, например, ГОСТ Р ИСО/МЭК 12207 уделяют специальное внимание вопросам проектирования и детализируют их, описывая контекст проектирования – от требований до тестов.

4.1.3 Процесс проектирования ПО

В стандартах, описывающих процессы жизненного цикла (таких как ГОСТ Р ИСО/МЭК 12207-2010) проектирование ПО состоит из двух видов деятельности, которые между анализом требований к ПО и конструированием ПО:

Высокоуровневое проектирование (или архитектурный дизайн или концептуальное проектирование) – декомпозиция структуры (статической) и организации (динамической) компонент;

Детальное проектирование – описывает специфическое поведение и характеристики отдельных компонент, а также интерфейсы между ними.

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

4.1.4 Принципы проектирования ПО

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

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

Абстракция (Abstraction)

Абстракция позволяет задействовать концепцию, игнорируя ее некоторые детали и работая с разными деталями на разных уровнях. Имея дело с составным объектом, вы имеете дело с абстракцией. Если вы рассматриваете объект как «дом», а не как комбинацию стекла, древесины и гвоздей, вы прибегаете к абстракции (рисунок 4.1). Если вы рассматриваете множество домов как «город», вы прибегаете к другой абстракции. Базовые классы представляют собой абстракции, позволяющие концентрироваться на общих атрибутах производных классов и игнорировать детали конкретных классов при работе с базовым классом. Удачный интерфейс класса – это абстракция, позволяющая сосредоточиться на интерфейсе, не беспокоясь о внутренних механизмах работы класса. Интерфейс грамотно спроектированного метода обеспечивает такую же выгоду на более низком уровне детальности, а интерфейс грамотно спроектированного пакета или подсистемы – на более высоком (Макконел, 2005).

Рисунок 4.1 – Абстракция – модель реального объекта, описанная
с некоторой точки зрения

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

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

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

 

Инкапсуляция и сокрытие информации (Encapsulation and information hiding)

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

Примечание: при этом, в качестве “пользователя” одного компонента может выступать другой компонент.

Сокрытие информации — один из основных принципов и структурного, и объектно-ориентированного проектирования. В первом случае сокрытие информации лежит в основе идеи «черных ящиков». Во втором оно дает начало концепциям инкапсуляции и модульности и связано с концепцией абстракции. Сокрытие ин формации – одна из самых конструктивных идей в мире разработки ПО, и сей- час мы рассмотрим ее подробнее.

Макконел рассуждает так: «Когда абстракция нас покидает, на помощь приходит инкапсуляция. Абстракция говорит: «Вы можете рассмотреть объект с общей точки зрения». Инкапсуляция добавляет: «Более того, вы не можете рассмотреть объект с иной точки зрения».

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

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

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

· секреты, которые скрывают источники изменений с целью локализации результатов возможных изменений.

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

Почаще задавайте себе вопрос «Что мне скрыть?», и вы удивитесь, сколько проблем проектирования растает на ваших глазах.
Сокрытие информации относится к тем немногим теоретическим подходам, польза которых уже долгое время неоспоримо подтверждается на практике (Boehm, 1987a). Было обнаружено, что крупные программы, использующие сокрытие информации, вчетверо легче модифицировать, чем программы, его не использующие (Korson and Vaishnavi, 1986).

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

 

Связанность (Coupling)

Связанность – определяет силу связи (часто, взаимного влияния) между модулями (Орлик, 2004).

Сопряжение характеризует силу связи подсистемы, класса или метода (компонента) с другими подсистемами, классами или методами (модулями). Наша цель (с точки зрения уменьшения сложности) – создать модули, имеющие немногочисленные, непосредственные, явные и гибкие отношения с другими модулями, что еще называют слабым сопряжением (loose coupling).

Старайтесь создавать модули, слабо зависящие от других модулей. Отношения модулей должны напоминать отношения деловых партнеров, а не сиамских близнецов . Скажем, метод sin() (синус) сопряжен слабо, так как нужную информацию он получает в форме одного значения — угла в градусах. Метод InitVars ( varl, var2, var3,..., varN ) сопряжен жестче, поскольку многие детали его работы становятся известными вызывающему модулю по передаваемым значениям. Два класса, зависящих от того, как каждый из них использует одну глобальную переменную, сопряжены еще жестче (Макконел, 2005).

 

Связность (Cohesion)

Связность – определяет как тот или иной элемент обеспечивает связь внутри модуля, внутреннюю связь.

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

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

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

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

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

 

Декомпозиция и модульность (Decomposition and Modularizаtion)

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

Иерархии помогают в достижении Главного Технического Императива Разработки ПО, позволяя сосредоточиться только на том уровне детальности, который заботит вас в конкретный момент. Иерархия не устраняет детали – она просто выталкивает их на другой уровень, чтобы вы могли думать о них, когда захотите, а не все время (Макконел, 2005).

Разделение интерфейса и реализации (Separation of interface and implementation)

Рисунок 4.2 – Интерфейс

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

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

 

Рисунок 4.3 – Хороший интерфейс класса напоминает айсберг – большая его часть скрыта от наблюдателя

Достаточность, полнота и простота (Sufficiency, completeness and primitiveness)

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

4.2 Ключевые проблемы проектирования

Как проводить декомпозицию? Как организовать и объединить компоненты в единую систему? Как обеспечить необходимую производительность? Наконец, как обеспечить приемлемое качество системы? Все это – фундаментальные вопросы и проблемы проектирования, вне зависимости от используемых при проектировании подходов.

Параллелизм (Concurrency)

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

Контроль и обработка событий (Control and Handling of Events)

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

Распределение компонентов (Distribution of Components)

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

Обработка ошибок и исключительных ситуаций и обеспечение отказоустойчивости (Errors and Exception Handling and Fault Tolerance )

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

Взаимодействие и представление (Interaction and Presentation)

Тема касается вопросов представления информации пользователям и взаимодействия пользователей с системой, с точки зрения реакции системы на действия пользователей. Речь в этой теме идет о реакции системы в ответ на действия пользователей и организации ее отклика с точки зрения внутренней организации взаимодействия, например, в рамках популярной концепции Модель–представление-контроллер (Model-View-Controller).

Примечание: в последних редакциях SWEBOK отдельным направлением области знаний «Проектирование» является «Проектирование пользовательского интерфейса» – мы в силу сжатости курса не будем его рассматривать.

Безопасность

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

4.3 Архитектура программного обеспечения

4.3.1 Что такое архитектура?

В строгом значении архитектура программного обеспечения (software architecture) – описание подсистем и компонент программной системы, а также связей между ними. Архитектура пытается определить внутреннюю структуру получаемой системы, задавая способ, которым система организована или конструируется.

4.3.2 Архитектурное представление

Любая система может рассматриваться с разных точек зрения (viepoints) – например, поведенческой (динамической), структурной (статической), логической (удовлетворение функциональным требованиям), физической (распределенность), реализации (как детали архитектуры представляются в коде) и т.п. В результате, мы получаем различные архитектурные представления (view). Архитектурное представление может быть определено, как частные аспекты программной архитектуры, рассматривающие специфические свойства программной системы. В свою очередь, проект системы – комплекс архитектурных представлений, достаточный для реализации системы и удовлетворения требований, предъявляемых к системе (Орлик, 2004).

4.3.3 Архитектурные стили

Архитектурный стиль, по своей сути, шаблон проектирования макро-архитектуры - на уровне модулей, "крупноблочного" взгляда. Например, архитектура распределенной сервисно-ориентированной системы может строиться в стиле обмена сообщениями через соответствующие очереди сообщений, может проектироваться на основе идеи взаимодействия между компонентами и приложениями через общую объектную шину, а может использовать концепцию брокера как единого узла пересылки запросов. В то же время, на более концептуальном уровне, мы можем говорить о выборе клиент-серверного стиля или распределенного стиля архитектуры системы. Таким образом, архитектурный стиль – набор ограничений, определяющих семейство архитектур, которые удовлетворяют этим ограничениям.

4.3.4 Шаблоны проектирования

Шаблоны проектирования (паттерны) — это готовые шаблоны, позволяющие решать частые проблемы разработки. Конечно, есть проблемы, требующие совершенно новых решений, но большинство уже встречалось разработчикам, поэтому их можно решить, применяя проверенные подходы, или шаблоны. Наиболее краткая формулировка того, что такое шаблон проектирования, может звучать так – “общее решение общей проблемы в заданном контексте”.

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

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

Самые простые и распространенные паттерны перечислены в таблице 4.1.

Таблица 4.1 – Простые и распространенные паттерны проектирования

Название Краткое описание
Абстрактная фабрика (Abstract Factory) Поддерживает создание наборов родственных объектов путем определения вида набора, но не вида каждого отдельного объекта.
Адаптер (Adapter) Преобразует интерфейс класса в другой интерфейс.
Компоновщик (Composite) Состоит из объекта, содержащего дополнительные объекты такого же типа, позволяя клиентскому коду взаимодействовать с объектом верхнего уровня и не заботиться о детальных объектах.
Декоратор (Decorator) Динамически назначает объекту новую функциональность без создания отдельных подклассов.
Фасад (Facade) Предоставляет унифицированный интерфейс к множеству интерфейсов в некоторой подсистеме. Определяет интерфейс более высокого уровня, облегчающий работу с подсистемой.
Фабричный метод (Factory Method) Определяет интерфейс для создания объектов, при этом выбранный класс инстанцируется подклассами.
Итератор (Iterator) Дает возможность последовательно обойти все элементы составного объекта, не раскрывая его внутреннего представления.
Наблюдатель (Observer) Определяет между объектами зависимость типа один ко многим, так что при изменении состояния одного объекта все зависящие от него получают извещение и автоматически обновляются.
Одиночка (Singleton) Предоставляет глобальный доступ к классу, который может иметь один и только один экземпляр.
Стратегия (Strategy) Определяет семейство алгоритмов, инкапсулируя их все и позволяя подставить один вместо другого. Можно менять алгоритм, независимо от клиента, который им пользуется.
Шаблонный метод (Template Method) Определяет структуру алгоритма, оставляя некоторые детали реализации подклассам.

 

Трудно найти объектно-ориентированную систему, в которой не используется хотя бы некоторые из указанных паттернов проектирования, а уж в больших системах встречаются чуть ли не все (Э. Гамма, 2010).

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

В общем, применение шаблонов проектирования – это эффективный инструмент управления сложностью (Макконел, 2005).

 

4.4 Анализ качества и оценка программного дизайна

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

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

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

Ø обзор дизайна (software design review); например, неформальный обзор архитектуры членами проектной команды;

Ø статический анализ (static analysis); например, трассировка с требованиями;

Ø симуляция и прототипирование (simulation and prototyping) – динамические техники проверки дизайна в целом или отдельных его атрибутов качества; например, для оценки производительности используемых архитектурных решений при симуляции нагрузки, близкой к прогнозируемым пиковым;

Ø измерения Могут быть использованы для количественной оценки ожиданий в отношении различных аспектов конкретного дизайна, например, размера <проекта>, структуры (ее сложности) или качества (например, в контексте требований, предъявляемых к производительности).

Макконел в своей книге «Совершенный код» приводит следующий контрольный список вопросов для оценки качества архитектуры ПО.

1. Ясно ли описана общая организация программы? Включает ли спецификация грамотный обзор архитектуры и ее обоснование?

2. Адекватно ли определены основные компоненты программы, их области ответственности и взаимодействие с другими компонентами?

3. Все ли функции, указанные в спецификации требований, реализуются разумным, не слишком большим и не слишком малым, числом компонентов?

4. Приведено ли описание самых важных классов и их обоснование?

5. Приведено ли описание организации данных и ее обоснование?

6. Приведено ли описание организации и содержания БД?

7. Определены ли все важные бизнес-правила? Описано их влияние на систему?

8. Описана ли стратегия проектирования GUI?

9. Сделан ли GUI модульным, чтобы его изменения не влияли на оставшуюся часть программы?

10. Приведено ли описание стратегии ввода-вывода данных и ее обоснование?

11. Указаны ли оценки степени использования ограниченных ресурсов, таких как потоки, соединения с БД, дескрипторы, пропускная способность сети? Приведено ли описание стратегии управления такими ресурсами и ее обоснование?

12. Описаны ли требования к защищенности архитектуры?

13. Определяет ли архитектура требования к объему и быстродействию всех классов, подсистем и функциональных областей?

14. Описывает ли архитектура способ достижения масштабируемости системы?

15. Рассмотрены ли вопросы взаимодействия системы с другими системами?

16. Описана ли стратегия интернационализации/локализации?

17. Определена ли согласованная стратегия обработки ошибок?

18. Определен ли подход к отказоустойчивости системы (если это требуется)?

19. Подтверждена ли возможность технической реализации системы?

20. Определен ли подход к реализации избыточной функциональности?

21. Приняты ли необходимые решения относительно «покупки или создания» компонентов системы?

22. Описано ли в спецификации, как повторно используемый код будет адаптирован к другим аспектам архитектуры?

23. Сможет ли архитектура адаптироваться к вероятным изменениям?

24. Является ли какая-нибудь часть системы чрезмерно или недостаточно проработанной? Заданы ли явные ожидания по этому поводу?

25. Является ли вся архитектура концептуально целостной?

26. Независим ли высокоуровневый проект системы от платформы и языка, который будет использован для его реализации?

27. Указаны ли мотивы принятия всех основных решений?

4.5 Нотации проектирования (Software Design Notations)

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

4.5.1 Структурные описания, статический взгляд

Языки описания архитектуры (Architecture description language, ADL): текстовые языки, часто – формальные, используемые для описания программной архитектуры в терминах компонентов и коннекторов (специализированных компонентов, реализующих не функциональность, но обеспечивающих взаимосвязь функциональных компонентов между собой и с “внешним миром”);

Особую роль при проектировании ПО играют графические нотации или диаграммы – мощный эвристический инструмент. Все знают, что лучше один раз увидеть, чем сто раз услышать. Диаграммы позволяют представить проблему на более высоком уровне абстракции, и никакие описания их не заменят.
Диаграммы классов и объектов (Class and object diagrams): используются для представления набора классов и <статических> связей между ними (например, наследования) Пример диаграммы классов UML на рисунках 4.4-4.5;

Рисунок 4.4 – Диаграмма классов UML на примере сказки «Курочка ряба»

Рисунок 4.5 – Диаграмма классов UML на примере системы обработки заказов

 

Диаграммы компонентов или компонентные диаграммы (Component diagrams): в определенной степени аналогичны диаграммам классов, однако, в силу специфики концепции или понятия компонента*, обычно, представляются в другой визуальной форме (рисунок 4.6).

Рисунок 4.6 – Диаграмма компонентов UML

Карточки <функциональной> ответственности и связей класса (Class responsibility collaborator card, CRC): используются для обозначения имени класса, его ответственности (то есть, что он должен делать) и других сущностей (классов, компонентов, актѐров/ролей и т.п.), с которыми он связан; часто их называют карточками “класс-обязанность-кооперация” (рисунок 4.7);

Рисунок 4.7 – CRC-карточка класса «Заказ»

Диаграммы развѐртывания (Deployment diagrams): используется для представления (физических) узлов, связей между ними и моделирования других физических аспектов системы (рисунок 4.8);

Рисунок 4.8 – Диаграмма развертывания UML

Диаграммы сущность-связь (Entity-relationship diagram, ERD или ER): используется для представления концептуальной модели данных, сохраняемых в процессе работы информационной системы. Часто используются при проектировании БД (рисунок 4.9).

Рисунок 4.9 – Диаграмма «Сущность-связь» (ER-диаграмма)

Языки описания/определения интерфейса (Interface Description/definition Languages, IDL): языки, подобные языкам программирования, не включающие возможностей описания логики системы и предназначенные для определения интерфейсов программных компонентов (имѐн и типов экспортируемых или публикуемых операций).

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

Рисунок 4.10 – Структурная диаграмма Джексона

 

Структурные схемы (Structure charts): описывают структуру вызовов в программах (какой модуль вызывает, кем и как вызываем). Пример на рисунке 4.11.


Рисунок 4.11 – Структурная схема


4.5.2 Поведенческие описания, динамический взгляд

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

Диаграммы деятельности или операций (Activity diagrams): используются для описания потоков работ и управления;

Диаграммы сотрудничества (Collaboration diagrams): показывают динамическое взаимодействие, происходящее в группе объектов и уделяют особое внимание объектам, связям между ними и сообщениям, которыми обмениваются объекты посредством этих связей (рисунок 4.12).

Рисунок 4.12 – Диаграмма сотрудничества (кооперации) UML

 

Диаграммы потоков данных (Data flow diagrams, DFD): описывают потоки данных внутри набора процессов (не в терминах процессов операционной среды, но в понимании обмена информацией в бизнес-контексте);

Таблицы и диаграммы <принятия> решений (Decision tables and diagrams): используются для представления сложных комбинаций условий и действий (операций). Пример на рисунке 4.13;

Рисунок 4.13 – Диаграмма принятия решений

Блок-схемы и структурированные блок-схемы (Flowcharts and structured flowcharts) – применяются для представления потоков управления (контроля) и связанных операций. В качестве примера блок-схемы на рисунках 4.14-4.15 изображены диаграммы активности UML.

Рисунок 4.14 – Диаграмма активности UML (работа веб-сайта)

 

Рисунок 4.15 – Диаграмма активности UML (работа веб-сайта)

 

Диаграммы последовательности (Sequence diagrams): используются для показа взаимодействий внутри группы объектов с акцентом на временной последовательности сообщений/вызовов (рисунок 4.16).

Рисунок 4.16 – Диаграмма последовательности UML (приготовление яичницы)

 

Диаграммы перехода и карты состояний (State transition and statechart diagrams): применяются для описания потоков управления переходами между состояниями (рисунок 4.17).

Рисунок 4.17 – Диаграмма состояний UML

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

Псевдокод и программные языки проектирования (Pseudocode and program design languages, PDL): языки, используемые для описания поведения процедур и методов, в основном на стадии детального проектирования; подобны структурным языкам программирования.

 

4.6 Стратегии и методы проектирования ПО

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

Таким образом, методы в данном контексте это не просто некие “слабоформализованные” или просто частные практические подходы или техники. Методы здесь являются более общими понятиями, это - методологии, сконцентрированные на процессе (в частности, проектирования) и предполагающие следование определенным правилам и соглашениям, в том числе – по используемым выразительным средствам. Такие методы полезны как инструмент систематизации (иногда, формализации) и передачи знаний в виде комплексного набора понятий, подходов, техник и инструментов не только для отдельных специалистов, но для команд и проектных групп программных проектов.

4.6.1 Общие стратегии

Это обычно часто упоминаемые и общепринятые стратегии:

· “разделяй-и-властвуй” и пошаговое уточнение

· проектирование “сверху-вниз” и “снизу-вверх”

· абстракция данных и сокрытие информации

· итеративный и инкрементальный подход

· и другие...

 

4.6.2 Функционально-ориентированное или структурное проектирование

Это один из классических методов проектирования, в котором декомпозиция сфокусирована на идентификации основных программных функций и, затем, детальной разработке и уточнении этих функций “сверху-вниз”. Структурное проектирование, обычно, используется после проведения структурного анализа (рисунок 4.18) с применением диаграмм потоков данных и связанным описанием процессов. Исследователи предлагают различные стратегии и метафоры или подходы для трансформации DFD в программную архитектуру, представляемую в форме структурных схем. Например, сравнивая управление и поведение с получаемым эффектом.

 

Рисунок 4.18 – Методология структурного анализа (Idef0)

 

 

Рисунок 4.19 – Диаграмма потоков данных

 

4.6.3 Объектно-ориентированное проектирование

Представляет собой множество методов проектирования, базирующихся на концепции объектов. Данная область активно эволюционирует с середины 80-х годов, основываясь на понятиях объекта (сущности), метода (действия) и атрибута (характеристики). Здесь главную роль играют полиморфизм и инкапсуляция, в то время, как в компонентно-ориентированном подходе большее значение придается мета-информации, например, с применением технологии отражения (reflection). Хотя корни объектно-ориентированного проектирования лежат в абстракции данных (к которым добавлены поведенческие характеристики), так называемый responsibility-driven design или проектирование на основе <функциональной> ответственности по SWEBOK* может рассматриваться как альтернатива объектно-ориентированному проектированию (хотя функциональная ответственность столь же близка принципам современного объектно-ориентированного проектирования, сколь и абстракция данных) (Орлик, 2004).

4.6.4 Проектирование на основе структур данных

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

 

4.6.5 Компонентное проектирование

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

 

4.6.6 Сервисно-ориентированный подход

Компонентно-ориентированное проектирование является одной из наиболее динамично развивающихся концепций проектирования и может рассматриваться как предвестник и основа сервисно-ориентированного подхода (Service-Oriented Architecture, SOA). Сервисно-ориентированный подход – модульный подход к разработке ПО, основанный на использовании распределённых, слабо связанных (англ. loose coupling) заменяемых компонентов, оснащённых стандартизированными интерфейсами для взаимодействия по стандартизированным протоколам. Программные комплексы, разработанные в соответствии с сервис-ориентированной архитектурой, обычно реализуются как набор веб-служб.

 

Существуют и другие методы…

 

4.7 Итоги занятия

ü Проектирование – это процесс, трансформирующий требования в структуру ПО, пригодную для конструирования.

ü Проектирование ПО условно разделено на архитектурное проектирование и детальное проектирование.

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

ü Наиболее общими подходами к описанию системы являются статический и динамические точки зрения.

ü Удобным средством описания проекта (дизайна) системы являются графические нотации.

ü Существует большое количество подходов к проектированию (функционально-ориентированный, объектно-ориентированный, компонентно-ориентированный, сервисно-ориентированный и другие).

5. Конструирование

2 часа

Программа должна следовать “Закону наименьшего удивления”. Что это за закон? Он гласит, что программа должна всегда отвечать пользователю так, чтобы вызывать у него наименьшее удивление.

 

5.1 Связь с другими областями знаний

Термин конструирование программного обеспечения (software construction) описывает детальное создание рабочей программной системы посредством комбинации кодирования, верификации (проверки), модульного тестирования (unit testing), интеграционного тестирования и отладки.

 

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

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

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

В процессе конструирования обычно создается большая часть активов программного проекта - конфигурационных элементов (configuration items). Поэтому в реальных проектах просто невозможно рассматривать деятельность по конструированию в отрыве от области знаний “Конфигурационного управления” (Software Configuration Management) (Орлик, 2004).

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

Так как конструирование невозможно без использования соответствующего инструментария и, вероятно, данная деятельность является наиболее инструментально-насыщенной, важную роль в конструировании играет область знаний “Инструменты и методы программной инженерии” (Software Engineering Tools and Methods).

Из связанных дисциплин программной инженерии (Related Disciplines of Software Engineering) наиболее тесная и естественная связь данной области знаний существует с компьютерными науками (computer scince). Именно в них, обычно, рассматриваются вопросы построения и использования алгоритмов и практик кодирования. Наконец, конструирование касается и управления проектами (project management), причем, в той степени, насколько деятельность по управлению конструированием важна для достижения результатов конструирования.

5.2 Цель и результаты конструирования

С точки зрения ГОСТ Р 12207-2010 цель процесса конструирования программных средств заключается в создании исполняемых программных блоков, которые должным образом отражают проектирование программных средств.

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

1) определяются критерии верификации для всех программных блоков относительно требований;

2) изготавливаются программные блоки, определенные проектом;

3) устанавливается совместимость и прослеживаемость между программными блоками, требованиями и проектом;

4) завершается верификация программных блоков относительно требований и проекта.

5.3 Основы конструирования

Фундаментальные основы конструирования программного обеспечения включают:

1) минимизация сложности.

2) ожидание изменений.

3) конструирование с возможностью проверки.

4) стандарты в конструировании.

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

5.3.1 Минимизация сложности

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

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

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

5.3.2 Ожидание изменений

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

Ожидание изменений поддерживается рядом техник, представленных в теме 5.5.2 “Кодирование”.

 

5.3.3 Конструирование с возможностью проверки

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

Среди техник, направленных на достижение такого результата конструирования:

- обзор, оценка кода (code review);

- модульное тестирование (unit-testing);

- структурирование кода для и совместно с применениям автоматизированных средств тестирования (automated testing);

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

5.3.4 Стандарты в конструировании

Стандарты, которые напрямую применяются при конструировании, включают:

- коммуникационные методы (например, стандарты форматов документов и <оформления> содержания)

- языки программирования и соответствующие стили кодирования (например, Java Language Specification, являющийся частью стандартной документации JDK – Java Development Kit и Java Style Guide, предлагающий общий стиль кодирования для языка программирования Java)

- платформы (например, стандарты программных интерфейсов для вызовов функций операционной среды, такие как прикладные программные интерфейсы платформы Windows - Win32 API, Qt или .NET Framework SDK);

- инструменты (не в терминах сред разработки, но возможных средств конструирования – например, UML как один из стандартов для определения нотаций для диаграмм, представляющих структура кода и его элементов или некоторых аспектов поведения кода)

Использование внешних стандартов. Конструирование зависит от внешних стандартов, связанных с языками программирования, используемым инструментальным обеспечением, техническими интерфейсами и взаимным влиянием Конструирования программного обеспечения и других областей знаний программной инженерии (в том числе, связанных дисциплин, например, управления проектами). Стандарты создаются разными источниками, например, консорциумом OMG – Object Management Group (в частности. Стандарты CORBA, UML, MDA, …), международными организациями по стандартизации такими, как ISO/IEC, IEEE, TMF, …, производителями платформ, операционных сред и т.д. (например, Microsoft, Sun Microsystems, CISCO, NOKIA, …), производителями инструментов, систем управления базами данных ит.п. (Borland, IBM, Microsoft, Sun, Oracle, ...). Понимание этого факта позволяет определить достаточный и полный набор стандартов, применяемых в проектной команде или организации в целом.

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

 

5.4 Управление конструированием

5.4.1 Модели конструирования

Модели конструирования определяют комплекс операций, включающих последовательность, результаты (например, исходный код и соответствующие unit-тесты) и другие аспекты, связанные с общим жизненным циклом разработки. В большинстве случаев, модели конструирования определяются используемым стандартом жизненного цикла, применяемыми методологиями и практиками. Некоторые стандарты жизненного цикла, по своей природе, являются ориентированными на конструирование – например, экстремальное программирование (XP- eXtreme Programming). Некоторые рассматривают конструирование в неразрывной связи с проектированием (в части моделирования), например, RUP (Rational Unified Process) (Орлик, 2004).

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

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

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

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

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

Выбор метода (методологии) конструирования является ключевым аспектом для планирования конструкторской деятельности. Такой выбор значим для всей конструкторской деятельности, а также необходимых условий еѐ осуществления, определяя порядок соответствующих операций и уровень выполнения заданных условий перед тем как начнется конструирование или составляющие его действия. Например, модульное тестирование в ряде методов является частью работ, после написания соответствующего функционального кода, в то время, как ряд гибких (agile) практик, например, XP (кстати, первыми начавшие использовать такие методы верификации кода), требуют написания Unit-тестов до того, как пишется соответствующий код, требующий тестирования (Орлик, 2004).

Используемый подход к конструированию влияет на возможность уменьшения (в идеале - минимизации) сложности, готовности к изменениям и конструировании с возможностью проверки.

 

5.4.2 Планирование конструирования

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

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

 

5.4.3 Измерения в конструировании

О каком планировании может идти речь, если мы не способны предсказать (например, на основе оценки результатов предыдущих проектов) ни длительность работ, ни стоимость отдельных задач, ни вероятность возникновения дефектов против заданных параметров приемлемого качества? (Орлик, 2004)
Большая часть результатов, да и самой деятельности по конструированию программного обеспечения, может быть измерена, в том числе - количественно. Это и исходный разработанный код, и модифицированный объем кода, и степень повторного использования, и многие другие характеристики. Эти измерения, или как их еще принято называть – результаты аудита кода и метрики кода, несут большую пользу как для оценки рисков и качества (приводящих к соответствующим операциям по снижению рисков и повышению качества), а также, для управления конструированием и программными проектами, в целом.

Код является одним из наиболее четко детерминированных активов проекта (постепенно такими становятся и модели, строящиеся на основе структур метаданных, и тесно связанные с кодом - например, UML). Код является и самим носителям требуемой функциональности. Соответственно, применение измерений в отношении кода становится тем инструментом, который влияет и на управление и на сам код (Орлик, 2004).

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

 

5.5 Практические соображения

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

5.5.1 Проектирование в конструировании

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

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

Детали деятельности по проектированию на стадии конструирования в основном те же самые, что и описанные в области знаний “Проектирование программного обеспечения” (Software Design). Отличие заключается в большем внимании деталям.

5.5.2 Кодирование

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

- техники создания легко понимаемого исходного кода на основе использования соглашений об именовании, форматирования и структурирования кода;

- использование классов, перечисляемых типов, переменных, именованных констант и других выразительных сущностей;

- организация исходного текста (в выражения, шаблоны, классы, пакеты/модули и другие структуры)

- использование структур управления;

- обработка ошибочных условий и исключительных ситуаций;

- предотвращение возможных брешей в безопасности (например, переполнение буфера или выход за пределы индекса в массиве);

- документирование кода;

- тонкая “настройка” кода;

- рефакторинг.

 

5.5.3 Тестирование в конструировании

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

- модульное тестирование (unit testing);

- интеграционное тестирование (integration testing).

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

Тестировании в конструировании обычно включает подмножество видов тестирования, описанных в области знаний “Тестирование программного обеспечения” (Software Testing). Например, тестирование в конструировании обычно не включает системного тестирования, нагрузочного тестирования, usability-тестирования (оценки прозрачности использования) и других видов тестовой деятельности.

IEEE опубликовал два стандарта, посвященных данной теме:

- IEEE Std 829TM-2008: «IEEE Standard for Software Test Documentation»;

- IEEE Std 1008-1987 (R2003): «IEEE Standard for Software Unit Testing».

 

5.5.4 Повторное использование

Во введении в стандарт IEEE Std. 1517-99 “IEEE Standard for Information Technology – Software Lifecycle Process – Reuse Processes” даётся следующее понимание повторному использованию в программном обеспечении: “Реализация повторного использования программного обеспечения подразумевает и влечѐт за собой нечто большее, чем просто создание и использование библиотек активов. Оно требует формализации практики повторного использования на основе интеграции процессов и деятельности по повторному использованию в сам жизненный цикл программного обеспечения.” В то же время, повторное использование достаточно важно и непосредственно при конструировании программных систем, что подчеркивается включением этой темы в обсуждаемую область знаний конструирования ПО.

Задачи, связанные с повторным использованием в процессе конструирования и тестирования, включают:

- выбор единиц (units), баз данных тестовых процедур, данных <полученных в результате> тестов и самих тестов, подлежащих повторному использованию;

- оценку потенциала повторного использования кода и тестов;

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

5.5.5 Качество конструирования

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

- модульное (unit) и интеграционное (integration) тестирование;

- разработка с первичностью тестов (test-first development - тесты пишутся до конструирования кода);

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

- использование процедур утверждений (assertion);

- отладка (в привычном понимании - debugging);

- технические обзоры и оценки (review);

- статический анализ.

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

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

5.5.6 Интеграция

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

К обсуждаемым интеграционным вопросам конструирования относятся:

- планирование последовательности, в которой интегрируются компоненты;

- обеспечение поддержки создания промежуточных версий программного обеспечения;

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

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

 

 

Дополнить новыми разделами SWEEBOK («Технологии конструирования» и «Инструменты и методы конструирования»)

6. Тестирование

2 часа

Тестирование (software testing) – деятельность, выполняемая для оценки и улучшения качества программного обеспечения. Эта деятельность, в общем случае, базируется на обнаружении дефектов и проблем в программных системах.

Тестирование программных систем состоит из динамической верификации поведения программ на конечном (ограниченном) наборе тестов (set of test cases), выбранных соответствующим образом из обычно выполняемых действий прикладной области и обеспечивающих проверку соответствия ожидаемому поведению системы.

В данном определении тестирования выделены слова, определяющие основные вопросы, которым адресуется данная область знаний:

· Динамичность (dynamic): этот термин подразумевает тестирование всегда предполагает выполнение тестируемой программы с заданными входными данными. При этом, величины, задаваемые на вход тестируемому программному обеспечению, не всегда достаточны для определения теста. Сложность и недетерминированность систем приводит к тому, что система может по разному реагировать на одни и те же входные параметры, в зависимости от состояния системы. В данной области знаний термин “вход” (input) будет использоваться в рамках соглашения о том, что вход может также специфицировать состояние системы, в тех случаях, когда это необходимо. Кроме динамических техник проверки качества, то есть тестирования, существуют также и статические техники, рассматриваемые в области знаний “Software Quality”.

· Конечность (ограниченность, finite): даже для простых программ теоретически возможно столь большое количество тестовых сценариев, что исчерпывающее тестирование может занять многие месяцы и даже годы. Именно поэтому, с практической точки зрения, всестороннее тестирование считается бесконечным. Тестирование всегда предполагает компромисс между ограниченными ресурсами и заданными сроками, с одной стороны, и практически неограниченными требованиями по тестированию, с другой. То есть мы снова говорим об определении характеристик “приемлемого” качества, на основе которых планируем необходимый объем тестирования.

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

· Ожидаемое поведение (expected behaviour): Хотя это не всегда легко, все же необходимо решить, какое наблюдаемое поведение программы будет приемлемо, а какое – нет. В противном случае, усилия по тестированию – бесполезны. Наблюдаемое поведение может рассматриваться в контексте пользовательских ожиданий (подразумевая “тестирования для валидации” - testing for validation), спецификации (“тестирование для верификации” - testing for verification) или, наконец, в контексте предсказанного поведения на основе неявных требований или обоснованных ожиданий.

 

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

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

В области знаний «Качество программного обеспечения» (Software Quality) техники управления качеством четко разделены на статические (без выполнения кода) и динамические (с выполнением кода). Обе эти категории важны. Данная область знаний – “Тестирование” – касается динамических техник.

Как уже отмечалось ранее, тестирование тесно связано с областью знаний «Конструирование» (Software Construction). Более того, модульное (unit-) и интеграционное тестирование все чаще рассматривают как неотъемлемый элемент деятельности по конструированию.

6.1 Основы тестирования (Software Testing Fundamentals)

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

6.1.1 Недостатки и сбои (Faults vs. Failures)

Важно четко разделять причину нарушения работы прикладных систем, обычно описываемую терминами недостаток или дефект, и наблюдаемый нежелательный эффект, вызываемый этими причинами – сбой. Термин ошибка, в зависимости от контекста, может описывать и как причину сбоя, и сам сбой. Тестирование позволяет обнаружить дефекты, приводящие к сбоям.

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

6.1.2 Ключевые вопросы (Key Issues)

Критерии отбора тестов/критерии адекватности тестов, правила прекращения тестирования
(Test selection criteria/test adequacy criteria, or stopping rules)

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

Эффективность тестирования/Цели тестирования
(Test effectiveness/Objectives for testing)

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

Тестирование для идентификации дефектов
(Testing for defect identification)

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

Проблема оракула (The oracle problem)

“Оракул”, в данном контексте, любой агент (человек или программа), оценивающий поведение программы, формулируя вердикт - тест пройден (“pass”) или нет (“fail”).

Теоретические и практические ограничения тестирования (Theoretical and practical limitation of testing)

Теория тестирования выступает против необоснованного уровня доверия к серии успешно пройденных тестов. К сожалению, большинство установленных результатов теории тестирования – негативны, означая, по словам Дейкстры (Dijkstra), то, что “тестирование программы может использоваться для демонстрации наличия дефектов, но никогда не покажет их отсутствие”. Основная причина этого в том, что полное (всеобъемлющее) тестирование недостижимо для реального программного обеспечения. Из-за этого современные методики говорят, что тестирование должно определяться на основе анализа рисков и может рассматриваться в качестве стратегии управления рисками.

Тестируемость (Testability)

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

6.1.3 Связь тестирования с другой деятельностью
(Relationships of testing with other activities)

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

6.2 Уровни тестирования

 

Рисунок 6.1 – V-модель разработки и тестирования ПО

6.2.1 Над чем производятся тесты

Тестирование обычно производится на протяжении всей разработки и сопровождения на разных уровнях. Уровень тестирования определяет “над чем” производятся тесты: над отдельным модулем, группой модулей или системой, в целом. При этом ни один из уровней тестирования не может считаться приоритетным. Важны все уровни тестирования, вне зависимости от используемых моделей и методологий.

Модульное тестирование (Unit testing)

Этот уровень тестирования позволяет проверить функционирование отдельно взятого элемента системы. Что считать элементом – модулем системы определяется контекстом. Наиболее полно данный вид тестов описан в стандарте IEEE Std 1008-1987 (R2003)“Standard for Software Unit Testing”, задающем интегрированную концепцию систематического и документированного подхода к модульному тестированию.

Интеграционное тестирование (Integration testing)

Данный уровень тестирования является процессом проверки взаимодействия между программными компонентами/модулями.

Классические стратегии интеграционного тестирования – “сверху-вниз” и “снизу-вверх” – используются для традиционных, иерархически структурированных систем и их сложно применять, например, к тестированию слабосвязанных систем, построенных в сервисно-ориентированных архитектурах (SOA).

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

Интеграционное тестирование – постоянно проводимая деятельность, предполагающая работу на достаточно высоком уровне абстракции. Наиболее успешная практика интеграционного тестирования базируется на инкрементальном подходе, позволяющем избежать проблем проведения разовых тестов, связанных с тестированием результатов очередного длительного этапа работ, когда количество выявленных дефектов приводит к серьезной переработке кода (традиционно, негативный опыт выпуска и тестирования только крупных релизов называют “big bang testing.”).

Системное тестирование (System testing)

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

На этом уровне также тестируются интерфейсы к внешним приложениям, аппаратному обеспечению, операционной среде и т.д.

6.2.2 Цели тестирования

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

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

Можно выделить следующие, наиболее распространенные и обоснованные цели (а, соответственно, виды) тестирования:

Приёмочное тестирование (Acceptance/qualification testing)

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

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

Установочное тестирование (Installation testing)

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

Альфа- и бета-тестирование (Alpha and beta testing)

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

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

Функциональные тесты/тесты соответствия
(Conformance testing/Functional testing/Correctness testing)

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

Достижение и оценка надежности
(Reliability achievement and evaluation)

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

Регрессионное тестирование (Regression testing)

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

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

Тестирование производительности (Performance testing)

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

Нагрузочное тестирование (Stress testing)

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

Сравнительное тестирование (Back-to-back testing)

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

Восстановительные тесты (Recovery testing)

Цель – проверка возможностей рестарта системы в случае непредусмотренной катастрофы (disaster), влияющей на функционирование операционной среды, в которой выполняется система.

Конфигурационное тестирование (Configuration testing)

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

Тестирование удобства и простоты использования (Usability testing)

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

6.3 Техники тестирования (Test Techniques)

6.3.1 Техники, базирующиеся на интуиции и опыте инженера
(Based on the software engineer’s intuition and experience)

Специализированное тестирование (Ad hoc testing)

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

Исследовательское тестирование (Exploratory testing)

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

6.3.2 Техники, базирующиеся на спецификации

Эквивалентное разделение <приложения>
(Equivalence partitioning)

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

Анализ граничных значений (Boundary-value analysis)

Тесты строятся с ориентацией на использование тех величин, которые определяют предельные характеристики тестируемой системы. Расширением этой техники являются тесты оценки живучести (robustness testing) системы, проводимые с величинами, выходящими за рамки специфицированных пределов значений.

Таблицы принятия решений (Decision table)

Такие таблицы представляют логические связи между условиями (могут рассматриваться в качестве “входов”) и действиями (могут рассматриваться как “выходы”). Набор тестов строится последовательным рассмотрением всех возможных кросс-связей в такой таблице.

Тесты на основе конечного автомата (Finite-state machine-based)

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

Тестирование на основе формальной спецификации (Testing from formal specification)

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

Случайное тестирование (Random testing)

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

6.3.3 Техники, ориентированные на код (Code-based techniques)

Тесты, базирующиеся на блок-схеме (Control-flow-based criteria)

Набор тестов строится исходя из покрытия всех условий и решений блок-схемы. В какой-то степени напоминает тесты на основе конечного автомата. Отличие – в источнике набора тестов.

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

Тесты на основе потоков данных (Data-flow-based criteria)

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

6.3.4 Тестирование, ориентированное на дефекты (Fault-based techniques)

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

Предположение ошибок (Error guessing)

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

Тестирование мутаций (Mutation testing)

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

SWEBOK фокусируется на возможности, с помощью тестов, определять отличия между мутантами и исходным вариантом кода. Если такое отличие установлено, мутанта “убивают”, а тест считается успешным.

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

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

6.3.5 Техники, базирующиеся на условиях использования

Операционный профиль (Operational profile)

Базируется на условиях использования системы.

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

Тестирование, базирующееся на надежности инженерного процесса (Software Reliability Engineered Testing)

Базируется на условиях разработки системы.

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

6.3.6 Техники, базирующиеся на природе приложения

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

· Объектно-ориентированное тестирование.

· Компонентно-ориентированное тестирование.

· Web-ориентированное тестирование.

· Тестирование на соответствие протоколам.

· Тестирование систем реального времени.

 

6.3.7 Выбор и комбинация различных техник

Функциональное и структурное (Functional and structural)

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

Определенное или случайное (Deterministic vs. random)

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

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

 

6.4 Измерение результатов тестирования

Часто техники тестирования путают с целями тестирования. Степень покрытия тестами - не то же самое, что высокое качество тестируемой системы. Однако, эти вопросы связаны. Чем выше степень покрытия, чем больше вероятность обнаружения скрытых дефектов. Когда мы говорим о результатах тестирования, мы должны подходить к их оценке, как оценке самой тестируемой системы. Именно количественные оценки результатов тестирования (но не самих тестов, например, покрытия ими возможных сценариев работы системы) освещаются ниже. В свою очередь, метрики самих тестов или процесса тестирования, как такового – вопросы, рассматриваемые в областях знаний “Процессы программной инженерии” (Software Engineering Process) и “Управление инженерной деятельностью” (Software Engineering Management).

Измерения являются инструментом анализа качества. Измерение результатов тестирования касается оценки качества получаемого продукта – программной системы. История измерений демонстрирует прогресс достижения приемлемого качества. Такая история является инструментом менеджмента качества.

6.4.1 Оценка программ в процессе тестирования (Evaluation of the program under test)

Измерения программ как часть планирования и разработки тестов (Program measurements to aid in planning and design testing)

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

Типы дефектов, их классификация и статистика возникновения (Fault types, classification and statistics)

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

Стандарт IEEE 1044-93 классифицирует возможные программные “аномалии”.

Плотность дефектов (Fault density)

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

Жизненный цикл тестов, оценка надежности (Life test, reliability evaluation)

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

Модели роста надежности (Reliability growth models)

Данные модели обеспечивают возможности прогнозирования надежности системы, базируясь на обнаруженных сбоях. Модели такого рода разбиваются на две группы – по количеству сбоев (failure-count) и времени между сбоями (time-between-failure).

 

6.4.2 Оценка выполненных тестов

Метрики покрытия/глубины тестирования (Coverage/thoroughness measures)

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

Введение искусственных дефектов (Fault seeding)

“Своими руками?! Никогда! ...” – такова, обычно, первая реакция на идею искусственного внесения дефектов, например, в программный код. На практике, этот подход помогает классифицировать возможные ошибки и следующие за ними сбои, применяя в дальнейшем полученные результаты для моделирования (пусть, часто, и интуитивного) возможных причин реальных сбоев, обнаруженных в процессе тестирования.

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

Оценка мутаций (Mutation score)

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

Сравнение и относительная эффективность различных техник тестирования (Comparison and relative effectiveness of different techniques)

Различные исследования в области тестирования связаны с попытками сравнения (с точки зрения достигаемого качества продукта) разных подходов к тестированию. Когда мы говорим об “эффективности” тестирования надо чѐтко договориться, что именно мы подразумеваем под эффективностью, желательно, в количественном выражении. Возможные варианты интерпретации этого понятия – число тестов (данной техники), необходимых для обнаружения первого дефекта; отношение количества всех обнаруженных дефектов к дефектам, найденным с применением заданного подхода и т.п. Только обладая такого рода данными можно говорить о корректности сравнения и оценки эффективности.

6.5 Процесс тестирования

Концепции, стратегии, техники и измерения тестирования должны быть объединены в единый процесс тестирования как деятельности по обеспечению качества. Процесс тестирования поддерживает работы по тестированию и определяет “правила игры” для членов команды тестирования – от планирования тестов до оценки их результатов. Хотя, в большинстве современных методов разработки, в частности, гибких (agile) подходов, тестирование выходит на передний план и является одной из базовых практик, многостороннее тестирование и, тем более, прогнозирование на основе полученных результатов, часто подменяется отдельными работами в этой области, не позволяющими добиться необходимых параметров качества. Только в том случае, если тестирование рассматривать как один из важных процессов всей деятельности по созданию и поддержке программного обеспечения, можно добиться оценки стоимости соответствующих работ и, в конце концов, соблюсти те ограничения, которые определены для проекта (Орлик, 2004).

6.5.1 Практические соображения

Программирование без персоналий (Attitudes / Egoless Programming)

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

Руководства по тестированию (Test guides)

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

Управление процессом тестирования (Test process management)

Работы по тестированию, ведущиеся на разных уровнях (см. выше 6.2 «Уровни тестирования»), должны быть организованы в единый (однозначно интерпретируемый) процесс, на основе учета 4-х элементов и связанных с ними факторов:

1) людей (в том числе, в контексте организационной структуры и культуры),

2) инструментов,

3) регламентов,

4) количественных оценок (измерений).

Документирование тестов и рабочего продукта (Test documentation and work products)

Документация – составная часть формализации процесса тестирования. Существует стандарт IEEE 829-98 «Standard for Software Test Documentation», предоставляющий прекрасное описание тестовых документов, их связей между собой и с процессом тестирования. Среди таких документов могут быть:

· план тестирования;

· спецификация процедуры тестирования;

· спецификация тестов;

· лог тестов;

· и др.

Документирование тестов, в случае его формального ведения, должно быть актуальным. В противном случае, как и любые другие документы, документация по тестированию ляжет “мертвым грузом”. В то же время, деятельность по тестированию, в случае отсутствия соответствующих регламентов и результатов (в том числе, исторических, для разных проектов), сложно поддается оценке для прогнозирования и, тем более, улучшению - в общем контексте улучшения процессов. Если компания-разработчик не ведет соответствующей документации по тестированию, говорить о сертификации или оценке по тем или иным моделям или стандартам (CMMI, ISO, SixSigma и т.п.) – просто не представляется возможным. А это уже вопрос доверия заказчиков, не имевших опыта работы с конкретной компанией-разработчиком.

Внутренние и независимые команды тестирования (Internal vs. independent test team)

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

Оценка стоимости и усилий, а также другие измерения процесса (Cost/effort estimation and other process measures)

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

Окончание тестирования (Termination)

Очень важным аспектом тестирования является решение о том, в каком объеме тестирование достаточно и когда необходимо завершить процесс тестирования. Тщательные измерения, такие как достигнутое покрытие кода тестами или охват функциональности, безусловно, очень полезны. Однако, сами по себе они не могут определить критериев достаточности тестирования. Приятие решения об окончании тестирования также включает рассмотрение стоимости и рисков, связанных с потенциальными сбоями и нарушениями надѐжности функционирования тестируемой программной системы. В то же время, стоимость самого тестирования также является одним из ограничений, на основе которых принимается решение о продолжении тех или иных связанных с проектом работ (с частности, тестирования) или об их прекращении. Cм. также подпункт «Критерии отбора тестов/критерии адекватности тестов, правила прекращения тестирования», описанный в п 6.1.2 «Ключевые вопросы (Key Issues)».

Повторное использование и шаблоны тестов (Test reuse and test patterns)

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

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

Иногда говорят о таком стиле разработки как о самостоятельной методологии – TDD. Насколько это верно, зависит от того, что именно понимать под методологией разработки. Скорее, с точки зрения автора, это техника, практика или стиль организации работы, чем самостоятельная методология.
Разработка, управляемая тестированием (Test-driven development)

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

 

6.5.2 Тестовые работы (Test Activities)

Данная тема дает краткий обзор работ по тестированию. При этом подразумевается, что успешное управление тестовыми работами сильно зависит от процессов конфигурационного управления (Software Configuration Management), рассматриваемых позднее как самостоятельная область знаний.

Планирование (Planning)

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

1) координацию персонала;

2) управление оборудованием и другими средствами, необходимыми для организации тестирования;

3) планирование обработки нежелательных результатов (т.е. является управлением определенными видами рисков).

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

Генерация сценариев тестирования (Test-case generation)

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

Разработка тестового окружения (Test environment development)

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

Выполнение тестов (Execution)

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

· должны фиксироваться все работы и результаты процесса тестирования;

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

· тестирование должно проводиться в соответствии с заданными и документированными процедурами;

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

 

Ряд вопросов выполнения тестов и других работ по тестированию освещен в стандартеIEEE Std 1008-1987 (R2003): «IEEE Standard for Software Unit Testing».

 

Анализ результатов тестирования (Test results evaluation)

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

Отчёты о проблемах/журнал тестирования (Problem reporting/Test log)

Во многих случаях, в процессе тестовой деятельности ведѐтся журнал тестирования, фиксирующий информацию о соответствующих работах: когда проводится тест, какой тест, кем проводится, для какой конфигурации программной системы (в терминах параметров и в терминах идентифицируемой версии контекста конфигурационного управления) и т.п. Неожиданные или некорректные результаты тестов могут записываться в специальной подсистеме ведения отчетности по сбоям (problem-reporting system, обеспечивая формирование базы данных, используемой для отладки, устранения проблем и дальнейшего тестирования. Кроме того, аномалии (помехи), которые нельзя идентифицировать как сбои, также могут фиксироваться в журнале и/или системе ведения отчетности по сбоям. В любом случае, документирование таких аномалий снижает риски процесса тестирования и помогает решать вопросы повышения надежности самой тестируемой системы. Отчёты по тестам могут являться входом для процесса управления изменениями и генерации запросов на изменения (change request) в рамках процессов конфигурационного управления (см. далее соответствующую область знаний «Конфигурационное управление»).

Отслеживание дефектов (Defect tracking)

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

7. Сопровождение

2 часа

Данная лекция:

1) включает концепции и терминологию, формирующие основы понимания роли и содержания работ по сопровождению программных систем;

2) описывают, почему именно существует потребность в сопровождении;

3) представляет некоторые технические и управленческие вопросы, связанные с сопровождением программных систем;

4) освещает вопросы организации процесса сопровождения;

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

7.1 Основы сопровождения ПО (Software Maintenance Fundamentals)

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

 

Если проблема 2000 года, в свое время, оказала особое влияние на изменение отношения к сопровождению на Западе, то расширение применения продуктов Open Source во всем мире и связанная с ним волна надежд на получение дешевого решения существующих задач привела к тому, что вопросы сопровождения вышли для многих организаций на первый план. Ситуация во многих ИТ-подразделениях показывает, что такие надежды оправдались только частично. Использование продуктов Open Source не стало дешевой альтернативой и, в ряде случаев, привело даже к большим проектным затратам именно в силу недостаточно проработанной политики эксплуатации и сопровождения построенных на их основе прикладных решений. Это ни в коем случае не значит, что волна Open Source “захлебнулась”. Это означает только, что игнорирование оценки стоимости сопровождения привело к превышению бюджетов, недостатку ресурсов и, в конце концов, частому провалу инициатив по использованию таких продуктов в корпоративной среде. Неготовность рассматривать жизненный цикл во времени как продолжающийся и после передачи системы в эксплуатацию, непроработанность соответствующих процедур корректировки продукта после его выпуска – основная беда и в бизнесе-среде, для которой программное обеспечение лишь инструмент, и в компаниях-интеграторах, “забывающих” о необходимости развития успеха после внедрения системы у заказчика, и у независимых поставщиков программных продуктов, которые, выпуская новую версию лучшего в своем классе продукта, начинают работать над новой версией, уделяя недостаточное внимание поддержке и обновлению уже существующих версий.
Фаза сопровождения в жизненном цикле, обычно, начинается сразу после приемки/передачи продукта и действует в течение периода гарантии или, чаще, технической поддержки. Однако, сама деятельность, связанная с сопровождением, начинается намного раньше.

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

7.1.1 Определения и терминология

Стандарт жизненного цикла 12207 (IEEE, ISO/IEC, ГОСТ Р ИСО/МЭК) позиционирует сопровождение как один из главных процессов жизненного цикла. Этот стандарт описывает сопровождение как процесс модификации программного продукта в части его кода и документации для решения возникающих проблем <при эксплуатации> или реализации потребностей в улучшениях <тех или иных характеристик продукта>. Задача состоит в модификации продукта при условии сохранения его целостности. Международный стандарт ISO/IEC 14764 (Standard for Software Engineering - Software Maintenance) определяет сопровождение программного обеспечения в тех же терминах, что и стандарт 12207, придавая особое значение работам по подготовке к деятельности по сопровождению до передачи системы в реальную эксплуатацию, например, вопросам планирования регламентов и операций по сопровождению.

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

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

7.1.2 Природа сопровождения (Nature of Maintenance)

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

7.1.3 Потребность в сопровождении (Need for Maintenance)

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

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

· устранение сбоев;

· улучшение дизайна;

· реализация расширений функциональных возможностей;

· создание интерфейсов взаимодействия с другими (внешними) системами;

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

· миграции унаследованного (legacy) программного обеспечения;

· вывода программного обеспечения из эксплуатации;

 

Деятельность персонала сопровождения включает четыре ключевых аспекта:

· поддержка контроля (управляемости) программного обеспечения в течение всего цикла эксплуатации;

· поддержка модификаций программных систем;

· совершенствование существующих процессов сопровождения;

· предотвращение падения производительности программной системы до неприемлемого уровня.

7.1.4 Приоритет стоимости сопровождения
(Majority of Maintenance Costs)

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

7.1.5 Эволюция программного обеспечения (Evolution of Software)

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

7.1.6 Категории сопровождения (Categories of Maintenance)

Сегодня говорят о четырех категориях работ по сопровождению:

Корректирующее сопровождение (corrective maintenance): “реактивная” модификация программного продукта, выполняемая уже после передачи в эксплуатацию для устранения сбоев;

Адаптирующее сопровождение (adaptive maintenance): модификация программного продукта на этапе эксплуатации для обеспечения продолжения его использования с заданной эффективностью (с точки зрения удовлетворения потребностей пользователей) в изменившемся или находящемся в процессе изменения окружении; в первую очередь, подразумевается изменение бизнес-окружения, порождающее новые требования к системе;

Совершенствующее сопровождение (perfective maintenance): модификация программного продукта на этапе эксплуатации для повышения характеристик производительности и удобства сопровождения;

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

 

7.2 Ключевые вопросы сопровождения ПО
(Key Issues in Software Maintenance)

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

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

· технические вопросы;

· управленческие вопросы;

· оценка стоимости;

· измерения.

 

7.2.1 Технические вопросы (Technical Issues)














Дата: 2019-02-19, просмотров: 452.