Добавил:
Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:

Основы разработки программного обеспечения на примере языка С. Учебное пособие для СПО

.pdf
Скачиваний:
0
Добавлен:
07.09.2026
Размер:
2 Мб
Скачать
☆
Объектный подход к проектированию
Эти типы не абстрактны, они столь же реальны, как int и float.
Дуг Макилрой
При разработке программного обеспечения выделяют два принципиальных подхода к проектированию: структурный (или функциональный) и объектный.
Структурный (функциональный) подход заключается в выделении основных функций или действий и базируется на нисходящем проектировании, основанном на структурах и алгоритмах управления. Основное понятие этого подхода - алгоритмы.
В объектном или объектно-ориентированном подходе в первую очередь выделяется множество основных объектов системы и впоследствии определяется множество операций над объектами. Такой подход базируется на абстрактных типах, и решение задачи выражается в терминах выделенных объектов.
6.1. Выделение объектов
Для обоих подходов первый шаг проектирования заключается в постановке задачи. При объектно-ориентированном подходе удобно строить таблицу, в которую заносятся все объекты и операции. Такая таблица помогает структурировать описание и показывает основные взаимосвязи между объектами.
Рассмотрим задачу реализации электронного каталога и системы учета для библиотеки. Читатель приходит в библиотеку, ищет в электронном каталоге нужные книги, выбирает их, берет на прочтение (эта операция связывает читателя и книгу, отметка ставится в формуляр читателя). При возвращении книги делаются соответствующие записи как в формуляре читателя, так и в данных о книге.
Основными объектами программы будут:
Основы разработки программного обеспечения на примере языка СС.В. Синицын, О.И. Хлытчиев
161
книга; формуляр; читатель.
Основные операции - найти книгу, взять книгу и вернуть книгу.
Таблица объектов
будет выглядеть следующим образом:
Таблица 6.1. Объекты системы
Объект Операции Примечания
Книга
Взять книгу на прочтение
Проверить соответствие критерию поиска
Используется для поиска нужной книги по критериям
Получить полную информацию о книге
Обновить информацию о книге
Изменить информацию об имеющейся книге
Завести новую книгу
При появлении новой книги в библиотеке
Вернуть книгу после прочтения
Формуляр
Взять книгу на прочтение
Вернуть книгу после прочтения
Снять книгу с читателя
Совмещается с возвратом книги в библиотеку или в случае утери книги
Завести новый формуляр
Читатель
Взять книгу на прочтение
Вернуть книгу после прочтения
Основы разработки программного обеспечения на примере языка СС.В. Синицын, О.И. Хлытчиев
162
Снять книгу с читателя
Завести нового читателя
Показать информацию о читателе
Обновить информацию о читателе
6.2. Состав операций
Как видно из табл. 6.1
, возможны случаи, когда одна операция вы­полняется сразу над несколькими объектами. Например, операция "Взять книгу на прочтение" выполняется сразу над тремя объектами ­"Читатель", "Формуляр" и "Книга", так как эта операция связывает объекты "Читатель" и "Книга" через объект "Формуляр". В данной задаче понятие "Формуляра" является связью между "Читателем" и "Книгой". Но это не равнозначная связь, так как с одним читателем может быть связано несколько книг, но не наоборот.
Из табл. 6.1
видно, что для каждого объекта предусмотрена операция создания (конструктор). Эта операция позволяет заводить новые книги и новых читателей с установкой для них первоначальных значений всех свойств.
Таблица объектов выявляет наиболее значимые объекты, для которых определено наибольшее количество операций. В нашем случае основные объекты - это "Читатель" и "Книга", что не противоречит восприятию реальной библиотеки.
В таблицу объектов можно добавить объект "Операция" или объект, отвечающий за получение команды пользователя электронной системой.
Теперь, когда определены все основные объекты, можно рассматривать
Основы разработки программного обеспечения на примере языка СС.В. Синицын, О.И. Хлытчиев
163
алгоритм, основываясь на выделенных операциях. Следующий шаг объектно-ориентированного подхода к проектированию заключается в детальной проработке каждой операции. Предварительно должны быть рассмотрены все форматы ввода/вывода и интерфейсы.
Первый шаг - построение таблицы объектов и операций рассмат-ривает абстракции и не накладывает ограничений на реализацию. Второй шаг, наоборот, фиксирует структуры данных, детализирует представление каждого объекта, структурирует алгоритмы. Если операция или объект достаточно сложны, то к ним в отдельности может снова применяться объектно-ориентированный подход.
Как объектный, так и структурный подходы имеют свои достоинства и недостатки. Объектный подход удобен в случаях, когда алгоритм для решения задачи представляется не очень сложным и главная проблема заключается в представлении данных. Выделение основных объектов упрощает описание задачи реального мира. Однако когда алгоритм представляется достаточно сложным, объектный подход не позволяет его упростить. В этом случае удобен структурный подход, который позволяет двигаться сверху вниз, постепенно упрощая алгоритм, но при этом общая картина решения задачи постоянно остается целостной.
Объектный подход упрощает декомпозицию программы на модули, естественно выделяя каждый объект в отдельный модуль. Структурный подход слабо поддерживает декомпозицию на модули, а это порой является довольно сложной самостоятельной задачей.
Объектно-ориентированный подход упрощает последующую модификацию, так как все операции логически выделены в отдельные процедуры.
В силу того, что объектный и структурный подходы являются независимыми, их стоит объединять вместе для использования преимуществ каждого.
Объекты и операции удобно выбирать, используя объектный подход, а реализацию удобнее проводить при помощи структурного подхода.
Внимание!
Основы разработки программного обеспечения на примере языка СС.В. Синицын, О.И. Хлытчиев
164
Объектно-ориентированный подход помогает выделить объекты программы. Если описать алгоритм становится сложно, следует использовать структурный подход, если же основная проблема в структуре данных, то стоит обратиться к объектному подходу. При проектировании следует придерживаться максимального уровня абстракции. Каждую операцию и каждый объект стоит рассматривать как отдельную задачу. Сочетание объектного и структурного подхода дает наибольший эффект.
6.3. Пример проектирования (продолжение примера раздела 2)
Напомним, что для преобразования строки по правилу 2-3-1 мы пришли в нашем случае к последовательности действий программы:
1. ввести входную строку;
2. если входная строка пустая, то закончить работу;
3. преобразовать входную строку;
4. вывести преобразованную строку;
5. ввести очередную входную строку и вернуться к действию (2).
Простейший анализ этого описания действий позволил нам выделить основной объект - входную строку и список действий:
ввести, преобразовать, проверить состояние "входная строка - пуста".
Далее можно выделить объект - "сообщение" и соответствующую ему операцию - "вывести".
Конкретный способ реализации объекта выбирается программистом в результате оценки нескольких вариантов, например способ представления объекта строка - список в связном представлении или массив символов; вид параметра процедуры вывода сообщения - текст сообщения или его номер в таблице сообщений и т.п.
Основы разработки программного обеспечения на примере языка СС.В. Синицын, О.И. Хлытчиев
165
Выводы
В данном примере целесообразно принять решение о представлении объекта "строка" (входная и преобразованная) в виде массива символов. Этот массив представляет собой основной информационный объект и может быть реализован в отдельном модуле str. Над ним должны быть определены следующие операции (процедуры).
Ввести входную строку (readString). Проверить входную строку на корректность (testString). Проверить входную строку на пустоту (isEmpty). Преобразовать строку (processString). Вывести строку (printString).
На процедуру testString естественно возложить контроль алфавита, длины входной строки и нарушение структуры входной строки (ведущие символы не пробелы).
Для вывода сообщений можно разработать отдельный модуль msg, в котором будет реализована единственная процедура msgWrite, ее параметром является значение перечислимого типа (INPUT_MSG,
END_MSG, ERROR_MSG), определяющее вывод сообщений 2.2.1.1,
2.2.1.2 и 2.2.1.3 соответственно.
При этом логика программы головного модуля может быть представлена так:
msgWrite(INPUT_MSG); readString(str); while(!isEmpty(str)) { if (!testString(str)) { msgWrite(ERROR_MSG); } else { processString(str); printString(str); }
Основы разработки программного обеспечения на примере языка СС.В. Синицын, О.И. Хлытчиев
166
msgWrite(INPUT_MSG); readString(str); } msgWrite(END_MSG);
Предполагается, что процедура ввода строки обращается к модулю msg для вывода приглашения к вводу msgWrite (INPUT_MSG).
Далее кодирование и отладка головного модуля и модулей str и msg могут быть произведены на языке программирования.
Вопросы и задачи для самостоятельного решения
Какие подходы к проектированию кроме объектного вам известны? Какие основные шаги необходимо выполнять при объектно­ориентированном подходе к проектированию? В чем основные преимущества объектного подхода, и когда его следует использовать? Что такое объект? Определите основные объекты для задачи учета штрафов за нарушения правил дорожного движения, в рамках которой сотрудники ГИБДД выписывают штрафы водителям, заносят данные: о водителе, о нарушении, его месте, времени и транспортном средстве.
Основы разработки программного обеспечения на примере языка СС.В. Синицын, О.И. Хлытчиев
167
Тестирование программного обеспечения
Тестирование может показать лишь наличие ошибок, но не их отсутствие.
Эдсгер Дейкстра
Любая программа может содержать в себе ошибки. Компилятор способен выявлять только синтаксические ошибки, но не способен отслеживать семантику. Большинство ошибок проявляется в ходе работы программы, при этом они могут возникать не всегда, а лишь при определенных условиях. Таким образом, успешная компиляция программы и выполнение этой программы в одних и тех же условиях не гарантируют отсутствие ошибок.
Для выявления ошибок в программах ЖЦ разработки ПО предусматривает процесс тестирования, который является достаточно трудоемким и занимает больше времени, чем кодирование. (Г. Майерс дает оценку 1/3 для тестирования, при том, что кодирование занимает примерно 1/6 [6
].) Тестируемое ПО обычно называют SUT - Software Under Test. Цель тестирования - не убедиться в безошибочной работоспособности программы, а наоборот - найти ошибки. Поэтому в первую очередь возникает вопрос: а что есть ошибка в программе?
Заметим, что к этому моменту программа уже представляет собой выполнимый процессором набор команд, т.е. с точки зрения процессора она корректна. Даже если при каких-то условиях программа аварийно завершает свое выполнение или "портит" другие процессы, сразу нельзя сказать, что это ошибка в программе - возможно, так было задумано. Таким образом, ошибки необходимо рассматривать с точки зрения пользователя, основываясь на дополнительной информации, т.е. неком описании того, что должна делать программа (это же описание может включать в себя требование о том, чтобы программа никогда не завершалась аварийно и др.).
Основы разработки программного обеспечения на примере языка СС.В. Синицын, О.И. Хлытчиев
168
Рис. 7.1. V-образная модель жизненного цикла разработки ПО
При рассмотрении вопросов анализа программного кода порой удобнее применять ранее рассмотренную в разделе 1 модель жизненного цикла. Ее часто называют V-образной из-за расположения блоков на рисунке (рис. 7.1
).
Нисходящая левая ветвь модели отражает поэтапную последовательность преобразования одних программных документов в другие: SYS - системных требований в SRD - требования к программному обеспечению, проектированию и формированию DDD ­описания архитектуры системы и, наконец, разработке CODE - кода программ. Восходящая правая ветвь отражает процесс верификации разработанного программного обеспечения.
На первом этапе путем тестирования производится модульная верификация (MV), при которой поведение исполняемого программного кода проверяется на соответствие его DDD-описанию. Это наиболее трудоемкая и скрупулезная часть исследования. Она часто требует написания драйверов - моделей модулей, вызывающих процедуры тестируемого модуля, и заглушек - моделей процедур других модулей, вызываемых из тестируемого. Часто в MV отдельно выделяют процесс тестирования межмодульных связей, описанных в DDD.
На втором этапе производится комплексная верификация (CV) реализованного программного обеспечения по отношению к требованиям. Наконец, производится комплексная интеграция (CI) и
Основы разработки программного обеспечения на примере языка СС.В. Синицын, О.И. Хлытчиев
169
проверка всей системы: пользователь, аппаратура и программное обеспечение. При грамотном процессе разработки уже на этапах нисходящей ветви для каждого требования определяется, на каком уровне верификации должна будет проводиться проверка его соблюдения.
При этом следует исходить из предположения, что ошибки всегда есть. Тестирование можно считать успешным, если найдены ошибки, а не наоборот. В достаточно сложном ПО все ошибки могут не обнаруживаться даже после длительного тестирования, однако чем тщательнее ведется тестирование, тем меньше ошибок остается и тем менее вероятно возникновение невыявленных ошибок [6
].
7.1. Тестовый план
Тестирование обычно проводится снизу вверх, т.е. сначала тести­руются отдельные функции, затем целые модули и далее проводится комплексное тестирование всей программы или комплекса программ. Для проведения тестирования разрабатывается тест-план (test-plan) ­совокупность тестовых наборов {примеров} (test-case). В каждом тестовом примере производится выполнение тестируемого программного элемента SUT при заданных Input - условиях и входных данных и проверяются все Output - выходные данные на соответствия заданным значениям.
Тестовый пример (набор) должен включать в себя как минимум:
входы (конкретные значения всех выходных параметров, все необходимые свойства и установки окружения); действия (что надо выполнить и в какой последовательности); ожидаемый выход (конкретные величины всех возвращаемых значений, все выводы в потоки, сигналы, все изменяемые свойства и установки окружения).
Кроме указанных данных удобно, если каждый тестовый пример имеет дополнительно:
номер (уникальный номер каждого тестового примера, чтобы на
Основы разработки программного обеспечения на примере языка СС.В. Синицын, О.И. Хлытчиев
170
Соседние файлы в предмете [НЕСОРТИРОВАННОЕ]