Программная инженерия.Часть II. Учебное пособие
.pdf
ные шаблоны уровня класса используют наследование для составления композиций из интерфейсов и реализаций. В качестве простого примера можно привести использование множественного наследования для объединения нескольких классов в один. В результате получается класс, обладающий свойствами всех своих родителей. Вместо композиции интерфейсов или реализаций структурные шаблоны уровня объекта компонуют объекты для получения новой функциональности. Дополнительная гибкость в этом случае связана с возможностью изменять композицию объектов во время выполнения, что недопустимо при статической композиции классов.
Примером структурного шаблона уровня объектов является «Компоновщик». Он описывает построение иерархии классов для двух видов объектов: примитивных и составных. Последние позволяют создавать произвольно сложные структуры из примитивных и других составных объектов. В шаблоне «Заместитель» объект берет на себя функции другого объекта. У «заместителя» есть много применений. Он может действовать как локальный представитель объекта, находящегося в удаленном адресном пространстве, или представлять большой объект, загружаемый по требованию, или ограничивать доступ к критически важному объекту. «Заместитель» вводит дополнительный косвенный уровень доступа к отдельным свойствам объекта, поэтому он может ограничивать, расширять или изменять эти свойства. Шаблон «Приспособленец» определяет структуру для совместного использования объектов. Он акцентирует внимание на эффективности использования памяти. В приложениях, где участвует много объектов, должны снижаться накладные расходы на их хранение (примером может служить программа, которая реализует текстовый редактор, поддерживающий произвольное форматирование любых участков текста). Шаблон «Фасад» представляет набор объектов и выполняет свои функции, перенаправляя сообщения объектам, которые он представляет. Шаблон «Мост» отделяет абстракцию объекта от его реализации, так что их можно изменять независимо.
Шаблоны поведения связаны с алгоритмами и распределением обязанностей между объектами, предназначены больше для проектирования типичных способов взаимодействия между объектами и классами. Шаблоны поведения характеризуют сложный поток управления, который трудно проследить во время выполнения программы. Внимание акцентировано не на потоке управления как таковом, а на связях между объектами. В шаблонах поведения уровня класса используется наследование, чтобы распределить поведение между разными классами, например шаблон, описывающий абстрактное определение алгоритма, где алгоритм определяется пошагово. На каждом шаге вызывается либо
II Часть | пособие Учебное
71
ПРОГРАММНАЯ ИНЖЕНЕРИЯ
примитивная, либо абстрактная операция. Алгоритм усложняется, детализируется за счет подклассов, где определены абстрактные операции.
В качестве примера можно взять шаблон «Интерпретатор», который представляет грамматику произвольного языка в виде иерархии классов и реализует интерпретатор как последовательность операций над экземплярами этих классов. В шаблонах поведения уровня объектов используется не наследование, а композиция. Некоторые из них описывают, как с помощью кооперации множество равноправных объектов справляется с задачей, которая ни одному из них не под силу. Например, при максимальной степени связности каждому объекту пришлось бы иметь информацию обо всех остальных. Эту проблему решает шаблон «Посредник», находящийся между объектами-коллегами, обеспечивая косвенность ссылок, необходимую для разрыва лишних связей.
Пример 16.1. Рассмотрим пример реализации шаблона «Одиночка».
Название и классификация шаблона: Одиночка (Singleton) – шаблон, порождающий объекты.
Назначение. Гарантирует, что у класса есть только один экземпляр, и предоставляет глобальную точку доступа к нему.
Мотивация. Для некоторых классов важно, чтобы существовал только один экземпляр, например: в системе может быть много принтеров, но возможен лишь один диспетчер печати; должны быть только одна файловая система и единственный оконный менеджер; в цифровом фильтре может находиться только один аналого-цифровой преобразователь; в программе глобальные настройки должны храниться в едином хранилище.
Как гарантировать, что у класса есть единственный экземпляр и то, чтобы этот экземпляр был легко доступен? Глобальная переменная дает доступ к объекту, но не запрещает создавать несколько экземпляров класса. Более удачное решение – сам класс контролирует то, что у него есть только один экземпляр, и может запретить создание дополнительных экземпляров, перехватывая запросы на создание новых объектов, он же способен предоставить доступ к своему экземпляру. Это и есть назначение шаблона «Одиночка».
Применимость. Используйте паттерн «Одиночка», когда должен быть ровно один экземпляр некоторого класса, доступный всем клиентам, или единственный экземпляр должен расширяться путем порождения подклассов, и клиентам нужно иметь возможность работать с расширенным экземпляром без модификации своего кода. Структура паттерна «Синглетон» представлена на рис. 16.1.
72
Рис. 16.1. Структура шаблона «Одиночка»
Участники. «Singleton» – одиночка: определяет операцию Instance, которая позволяет клиентам получать доступ к единственному экземпляру (Instance – это статический метод класса); может нести ответственность за создание собственного уникального экземпляра.
Отношения. Клиенты получают доступ к экземпляру класса Singleton только через его операцию Instance.
Результаты. У шаблона «Одиночка» есть следующие достоинства.
–Контролируемый доступ к единственному экземпляру. Поскольку класс Singleton инкапсулирует свой единственный экземпляр, он полностью контролирует то, как и когда клиенты получают доступ к нему.
–Также следует отметить уменьшение числа имен. Шаблон позволяет избежать засорения пространства имен глобальными переменными,
вкоторых хранятся уникальные экземпляры.
–Кроме того, шаблон допускает уточнение операций и представления. От класса Singleton можно порождать подклассы, а приложение легко настроить экземпляром расширенного класса. Можно конкретизировать приложение экземпляром того класса, который необходим во время выполнения.
–Шаблон допускает переменное число экземпляров, т. е. позволяет легко изменить решение и разрешить появление более одного экземпляра класса Singleton. Можно применять один и тот же подход для управления числом экземпляров, используемых в приложении. Изменить нужно будет лишь операцию, дающую доступ к экземпляру класса Singleton. Реализация шаблона представлена листингом
Листинг 16.1. Пример реализации шаблона «Одиночка»
Class Singleton
{
// Статический экземпляр класса
private static Singleton _Instance = null;
II Часть | пособие Учебное
73
ПРОГРАММНАЯ ИНЖЕНЕРИЯ
//Конструктор private Singleton()
{
}
//Получение экземпляра класса public static Singleton Instance();
{
if (_Instance == null) _Instance = new Singleton (); return _Instance;
}
}
При использовании шаблона Singleton предусмотрено следующее. Гарантирована единственность экземпляра. Шаблон «Одиночка» устроен так, что больше одного экземпляра создать не удастся. Для этого прячут операцию, создающую экземпляры, за статической функцией-чле- ном или методом класса, которые гарантируют создание не более одного экземпляра. Данная операция имеет доступ к статическому полю класса, гдехранится уникальный экземпляр, и гарантирует инициализацию переменной этим экземпляром перед возвратом ее клиенту. При таком подходе «Одиночка» будет создан и инициализирован перед первым использованием.
Клиенты осуществляют доступ к «Одиночке» исключительно через
статический метод Instance. Переменная _Instance инициализируется пустым значением Null, а статический метод Instance возвращает ее зна-
чение, инициализируя ее уникальным экземпляром, если в текущий момент оно равно Null. Метод Instance использует отложенную инициали-
зацию: возвращаемое ей значение не создается и не хранится вплоть до момента первого обращения.
Необходимо отметить, что конструктор защищенный (private). Клиент, который попытается создать экземпляр класса Singleton непосредствен-
но получит ошибку на этапе компиляции. Это дает гарантию, что будет
создан только один экземпляр.
Поскольку переменная _Instance– указатель на объект класса Singleton, то функция – член Instance может присвоить этой переменной
указатель на любой подкласс данного класса.
16.4. Программные средства
При конструировании ПО обычно используют так называемые среды разработки, т. е. системы программных средств для разработки программного обеспечения.
74
Существуют и широко используются следующие интегрированные среды разработки, предназначенные для нескольких языков программирования.
Eclipse – cвободная интегрированная среда разработки модульных кросс-платформенных приложений, поддерживает разработку на языках Java, C/C++, Fortran, Perl, PHP, JAVASCRIPT, Python, Ruby;
NetBeans – интегрированная среда разработки приложений, поддерживает разработку на языках Java, JAVAFX, Python, PHP, JAVASCRIPT, C++, Ada.
Embarcadero RAD Studio – среда быстрой разработки приложений для Microsoft Windows фирмы Embarcadero Technologies. Текущая версия Embarcadero RAD Studio XE3 объединяет Delphi XE3 и C++ Builder XE3, Delphi Prism XE3 и HTML5 Builder в единую интегрированную среду разработки;
Qt Creator – свободная среда разработки для языков С, С++ и QML. Microsoft Visual Studio – интегрированная среда разработки компании
Microsoft, позволяет создавать приложения на языках C/C++, Visual Basic, C#, J#, F# и проекты для баз данных Microsoft SQL Server, включает в себя множество дополнительных инструментов, а также функционал для командной разработки и создания тестов.
Не менее популярны и среды разработки, предназначенные для одного определенного языка программирования.
Visual Basic – среда разработки на одноименном языке. Borland Delphi – среда разработки на языке Object Pascal. Borland C++ Builder – среда разработки на C++.
Dev-C++ – среда разработки на C++.
Вывод
Нами рассмотрено понятие шаблона проектирования с точки зрения эффективного способа решения характерных задач проектирования, которые проявляются как при проектировании, так и при конструировании.
Вопросы для самопроверки
1.Дайте определение шаблона проектирования.
2.Как в общем виде описываются шаблоны?
3.Опишите принципы работы с шаблонами.
4.Опишите типы шаблонов проектирования.
5.Чем они различаются и для чего служат?
Литература
1.Программная инженерия: учебник / В. А. Антипов и др.; под ред.
Б.Г. Трусова. М.: Академия, 2014. 282 с.
II Часть | пособие Учебное
75
ПРОГРАММНАЯ ИНЖЕНЕРИЯ
2.Соммервилл И. Инженерия программного обеспечения. 6-е изд. / пер. с англ. М.: Изд. дом «Вильямс», 2002. 624 с.
3.Кознов Д. Введение в программную инженерию: учебный курс. М.: Интуит, 2008.
Тема17.ТЕСТИРОВАНИЕПРОГРАММНОГООБЕСПЕЧЕНИЯ
План
17.1.Основы тестирования.
17.2.Виды тестирования.
17.3.Работа с ошибками.
17.4.Тестирование с использованием тест-комплектов.
17.5.Программные средства для тестирования программного обеспечения.
17.1. Основы тестирования
Тестирование является очень важным и нужным процессом в современном мире информационных технологий. Специалистам по тестированию следует быть не только грамотными в области информационных технологий (в том числе знать языки программирования), но и уметь «увидеть» продукт глазами пользователя, а кроме того, быть очень внимательными к деталям. Весь процесс тестирования направлен на поиск и устранение ошибок в разрабатываемой системе.
Процесс разработки ПП с позиции тестирования представлен на рис. 17.1. Отдел разработки бизнес-требований предоставляет группе тестирования и отделу разработки два документа: описание бизнес-логики выпускаемого продукта и описание функционального дизайна.
Бизнес-логика выпускаемого продукта описывает процессы, которые должен обрабатывать проектируемый продукт, с точки зрения конечного пользователя, а функциональный дизайн содержит информацию о функциях, которые должен выполнять проектируемый продукт, также может содержать описание интерфейса и требования пользователя к интерфейсу. После этого аналитики отдела разработки изучают данные документы и формируют документы технического дизайна (обычно они включают в себя описание архитектуры будущего продукта, технические задания). Данные документы отправляются обратно в отдел разработки бизнес-требований и группе тестирования. После его утверждения отделом разработки бизнес-требований группа тестирования приступает к написанию тест-плана, тест-сценариев и тест-кейсов.
76
Рис. 17.1. Схема процесса разработки ПП
Тест-план – документ, описывающий весь объем работ по тестированию, начиная с объекта, стратегии, расписания, критериев начала и окончания тестирования, до необходимого в процессе работы оборудования, специальных знаний, а также оценки рисков с вариантами их разрешения.
Тестовый сценарий содержит описание начальных условий, входных данных, действий пользователя и ожидаемого результата.
Тест-кейсы – описание совокупности шагов конкретных условий и параметров, необходимых для проверки реализации тестируемой функции или ее части.
Эти документы послужат основой для дальнейшего тестирования продукта. Одновременно с работой группы тестирования программисты пишут код. Когда код становится относительно стабильным, тестировщикам выдается версия программного продукта. В ходе выполнения тестов обнаруживаются дефекты, программисты их исправляют, выпускают новую версию продукта и выдают ее на тестирование. Так продолжается до тех пор, пока продукт не приобретает должный уровень качества или не подходит срок окончательного релиза.
II Часть | пособие Учебное
77
Процесс тестирования системы включает в себя выполнение следующих стадий.
– Изучение спецификации. Эта стадия самая важная, также ее называют «анализом дизайна и/или требований», иногда применяют название «тестирование спецификации». На данной стадии необходимо изучить документацию (спецификацию требований) по разрабатываемому приложению.
– Дымовое тестирование. На этой стадии необходимо проверить, работает ли система вообще (правильно ли работает, правильно ли обрабатывает ошибки и пр.). Это делается для того, чтобы понять, пригодно ли приложение для дальнейшего тестирования или оно изначально работает неправильно.
«Позитивное» тестирование». На этой стадии необходимо проверить результат работы приложения при получении им «правильных» входных данных.
«Негативное» тестирование. Это завершающая стадия начального тестирования. Необходимо посмотреть, как ведет себя приложение, подавая на вход «неправильные» данные. Если такой вариант описан в спецификации (а он должен быть описан), то необходимо сравнить ожидаемый результат с полученным.
Рассмотрим эти стадии более подробно.
На стадии изучения спецификации определяется, когда и как должно
|
работать само приложение, когда и как оно должно реагировать на ошиб- |
|
|
ки, т. е. как система или ее модули должны реагировать на неправиль- |
|
|
ные данные или неверное поведение пользователя. А также что должно |
|
|
быть в результате правильной обработки, при каких условиях и входных |
|
|
данных система должна работать корректно? Что должно быть в резуль- |
|
|
тате неправильной отработки тестируемого приложения, при каких ус- |
|
|
ловиях это может происходить? На все эти вопросы должен быть ответ |
|
|
в документации тестируемого приложения. Если ответа там нет, то доку- |
|
|
ментация неполная, что равняется, по сути, ошибке в документации. Эти |
|
|
первые дефекты (в спецификации, в требованиях), возникающие уже на |
|
ИНЖЕНЕРИЯ |
данной стадии являются для разрабатываемой системы не менее важны- |
|
ми, чем прочие. Поэтому тестирование требований это полноценный вид |
||
|
||
|
тестирования, которому зачастую незаслуженно уделяют мало внимания. |
|
|
Основными показателями успешного тестирования требований является |
|
ПРОГРАММНАЯ |
достижение критериев полноты и непротиворечивости требований. |
|
Документация дает возможность понять для себя основные этапы |
||
|
||
|
проверки приложения: где и как приложение должно корректно работать, |
|
|
как отрабатывать ошибочные ситуации: выдавать сообщения об ошибке, |
|
|
писать ошибку в файл протокола работы, прекращать выполнение и т. д. |
|
|
|
|
|
|
78
Далее осуществляется процесс тестирования, который можно опи- |
|
|
сать как следующую пошаговою процедуру: |
|
|
1) проверьте, как работает приложение, когда оно получает на вход |
|
|
корректные данные; |
|
|
2) если все работает правильно, как описано в спецификации, сле- |
|
|
дующим шагом является проверка граничных значений (минимальные и |
|
|
максимальные значения корректных данных); |
|
|
3) проверьте работу приложения при вводе данных, которые не вхо- |
|
|
дят в область допустимых значений (проверка обработки некорректных |
|
|
входных значений). |
|
|
В первых двух пунктах описан процесс, который называется «пози- |
|
|
тивным» тестированием. |
|
|
«Позитивное» тестирование – это тестирование на данных или |
|
|
сценариях, которые соответствуют нормальному (штатному, ожидаемо- |
|
|
му) поведению проверяемой системы. Основной целью «позитивного» |
|
|
тестирования является проверка того, можно ли при помощи системы |
|
|
делать то, для чего она создавалась. |
|
|
«Негативное» тестирование – это тестирование на данных или сце- |
|
|
нариях, которые соответствуют нештатному поведению тестируемой си- |
|
|
стемы, а также выдаче различных сообщений об ошибках исключитель- |
|
|
ным ситуациям, «запредельным» состояниям и т. п. |
|
|
Основной целью «негативного» тестирования является проверка |
|
|
устойчивости системы к воздействиям «негативного» рода: проверка не- |
|
|
верного набора данных, проверка обработки исключительных ситуаций |
|
|
(как в реализации самих программных алгоритмов, так и в логике биз- |
|
|
нес-правил) и т. п. |
|
|
Предшествовать «позитивному» и «негативному» тестированию |
|
|
должны работы по выполнению «дымового» тестирования, в ходе кото- |
|
|
рого осуществляется быстрое, неглубокое тестирование наиболее кри- |
|
|
тичной функциональности на простых, т. е. типичных сценариях с мини- |
|
|
мумом проверок («чтобы только дыма не было»). Может выполняться как |
|
|
на «позитивных», так и на «негативных» данных. |
|
|
Как нужно расставлять приоритеты при тестировании? «Позитивное» |
|
|
тестирование считается на порядок более важным, чем «негативное». |
Учебное |
|
Предположим, что система не слишком устойчива к «плохим» вводимым |
||
данным. Это страшно? Зачастую не слишком. Пользователи могут нау- |
||
читься обходить «подводные камни», не будут делать «опасные» или «не- |
|пособие |
|
нит, какие проблемы обычно возникают у пользователей, и будет давать |
||
разрешенные» действия, служба технической поддержки скоро запом- |
|
|
советы типа «ни в коем случае не оставляйте это поле пустым, а то…». |
Часть |
|
Но если система не выполняет своего основного предназначения, если |
||
II |
||
|
79
ПРОГРАММНАЯ ИНЖЕНЕРИЯ
пользователи (заказчики) не могут решить свои бизнес-задачи, если они все делают правильно, вводят хорошие данные, но не получают результата, то с такой системой никто работать не захочет. Поэтому «позитивное» тестирование гораздо важнее «негативного».
17.2. Виды тестирования
В настоящее время существует множество видов тестирования. Функциональное тестирование заключается в тестировании систе-
мы в целях проверки реализуемости функциональных требований, т. е. способности программы в определенных условиях решать задачи, нужные пользователям. Функциональные требования определяют, что именно делает программа и какие задачи она решает.
Нагрузочное тестирование. В общем случае производится моделирование ожидаемого использования приложения с помощью эмуляции работы нескольких пользователей одновременно. Подобное тестирование больше всего подходит для мультипользовательских систем и особенно для использующих клиент-серверную архитектуру (например, Web-серверов). Однако и другие типы систем (программ) могут быть протестированы подобным способом. Например, в текстовый или графический редактор можно загрузить очень большой документ, в финансовой системе сгенерировать отчет на основе данных за несколько лет.
В идеальном случае в качестве критериев успешности нагрузочного тестирования выступают требования к производительности системы, которые формулируются и документируются на стадии разработки функциональных требований до начала программирования основных архитектурных решений. Часто бывает так, что такие требования не были четко сформулированы или не были сформулированы вообще. В этом случае первое нагрузочное тестирование будет являться пробным и основываться на разумных предположениях об ожидаемой нагрузке и потреблении аппаратной части ресурсов. Одним из оптимальных подходов в использовании нагрузочного тестирования для измерений производительности системы является тестирование на стадии ранней разработки.
Стресс-тестирование – вид тестирования ПО, которое оценивает надежность и устойчивость системы в условиях превышения пределов нормального функционирования. Стресс-тестирование особенно необходимо для «критически важного» ПО. Стресс-тестирование обычно лучше обнаруживает такие качества, как устойчивость, доступность и способность к обработке исключений системой под большой нагрузкой, чем то, что считается признаком корректного поведения в нормальных условиях. В общем случае стресс-тестирование основано на снятии и анализе показателей производительности приложения при нагрузках,
80
