Некоммерческое акционерное общество
АЛМАТИНСКИЙ ИНСТИТУТ ЭНЕРГЕТИКИ И СВЯЗИ
Кафедра инженерной кибернетики
ТЕХНОЛОГИИ ПРОГРАММИРОВАНИЯ
Конспект лекций
для студентов всех форм обучения специальностей
050702 – Автоматизация и управление, 050703 – Информационные системы
СОСТАВИТЕЛИ: Н.В. Сябина. Технологии программирования. Конспект лекций для студентов всех форм обучения специальностей 050702 – Автоматизация и управление, 050703 – Информационные системы. - Алматы: АИЭС, 2006.- 74 с.
Настоящий конспект лекций составлен на основании типовой рабочей программы в помощь первокурсникам при изучении теоретического материала по технологиям программирования и включает семнадцать тем. В конце каждой темы приведены ссылки на дополнительную литературу для более глубокого освоения предмета. В приложениях содержится необходимый справочный и иллюстративный материал.
Конспект лекций предназначен для студентов всех форм обучения специальностей 050702 – Автоматизация и управление, 050703 – Информационные системы.
Содержание
1 Лекция № 1. Программные средства автоматизации персонального компьютера. Технология программирования. Основные понятия и
подходы
2 Лекция № 2. Разработка сложных программных систем
3 Лекция № 3. Жизненный цикл программного обеспечения
4 Лекция № 4. Быстрая разработка приложений. Технологичность программного обеспечения
5 Лекция № 5. Приемы обеспечения технологичности программных продуктов
6 Лекция № 6. Структурное и «неструктурное» программирование
7 Лекция № 7. Определение требований к программному обеспечению и исходных данных для его проектирования
8 Лекция № 8. Принципиальные решения начальных этапов
проектирования
9 Лекция № 9. Алгоритмические языки и предъявляемые к ним
требования
10 Лекция № 10. Структурный подход. Анализ требований, определение спецификаций
11 Лекция № 11. Структурный подход. Проектирование программного обеспечения
12 Лекция № 12. Объектный подход. Проектирование программного обеспечения
13 Лекция № 13. Пользовательские интерфейсы
14 Лекция № 14. Особенности разработки пользовательских интерфейсов
15 Лекция № 15. Компоненты пользовательских интерфейсов.
Технология Drag&Drop
16 Лекция № 16. Тестирование и отладка программных продуктов
17 Лекция № 17. Составление программной документации......................... 65
Приложение А
Приложение Б
Приложение В
Приложение Г
Список литературы
1 Лекция №1. Программные средства автоматизации персонального компьютера. Технология программирования. Основные понятия и подходы
Содержание лекции: понятие о программном обеспечении компьютера; технология программирования; основные этапы развития.
Цель лекции: получить представление о современном состоянии программного обеспечения; изучить основные понятия и подходы технологии программирования; получить представление о структурном, модульном, объектном и визуальном программировании.
Программным обеспечением называют совокупность программ, позволяющих осуществить на компьютере автоматизированную обработку информации. Согласно современным тенденциям программное обеспечение классифицируется как системное (общее) и прикладное (специальное). Создание программной системы – задача весьма трудоемкая, особенно когда обычный объем программ превышает сотни тысяч операторов. Специалист в области разработки программного обеспечения должен иметь представление о методах анализа, проектирования, реализации и тестирования программных систем, а также ориентироваться в существующих подходах и технологиях.
Технологией программирования называют совокупность методов и средств, используемых в процессе разработки программного обеспечения. Она представляет собой набор технологических инструкций, включающих: указание последовательности выполнения технологических операций; перечисление условий, при которых выполняются операции; описания самих операций с определением исходных данных, результатов, инструкций, нормативов, стандартов, критериев и методов оценки. Кроме того, технология определяет способ описания проектируемой системы (модели), используемой на конкретном этапе разработки. Различают технологии, используемые на конкретных этапах разработки (в основе лежит ограниченно применимый метод) и технологии, охватывающие несколько этапов разработки (в основе лежит базовый метод или методология). Среди основных этапов развития технологий программирования выделяют «стихийное» программирование, структурный, объектный и компонентный подходы к программированию [1].
На этапе «стихийного» программирования (период от момента появления первых ЭВМ до середины 60-х годов XX века) практически отсутствовали сформулированные технологии, а программирование было искусством. Первые программы имели простейшую структуру: программа на машинном языке и обрабатываемые данные. Сложность программ в машинных кодах ограничивалась способностью программиста одновременно мысленно отслеживать последовательность выполняемых операций и местонахождение данных при программировании. В результате появления ассемблеров вместо двоичных кодов стали использовать символические имена данных и мнемоники кодов операций, а программы стали более «читаемыми». Создание языков программирования высокого уровня (FORTRAN, ALGOL) существенно упростило программирование вычислений, снизив уровень детализации операций, что позволило увеличить сложность программ.
В результате появления средств, позволяющих оперировать подпрограммами, были созданы огромные библиотеки расчетных и служебных подпрограмм. Типичная программа состояла из основной программы, области глобальных данных и набора подпрограмм, однако при увеличении количества подпрограмм возрастала вероятность искажения части глобальных данных какой-либо подпрограммой, поэтому было предложено размещать в них локальные данные (рисунок 1.1), а появление новых средств поддержки подпрограмм позволило разрабатывать программное обеспечение нескольким программистам параллельно.
Рисунок 1.1 - Архитектура программы: а) с глобальной областью данных; б) использующей подпрограммы с локальными данными
В начале 60-х годов XX века разразился «кризис программирования»: разработчики сложного программного обеспечения срывали все сроки завершения проектов: проект устаревал раньше, чем был готов к внедрению, его стоимость увеличивалась, в результате многие проекты так никогда и не были завершены. Все это было вызвано несовершенством технологии программирования. Прежде всего, использовалась разработка «снизу-вверх». В отсутствии четких моделей описания подпрограмм и методов проектирования, создание подпрограмм превращалось в непростую задачу. Интерфейсы подпрограмм получались сложными, и при сборке программного продукта выявлялось большое количество ошибок согласования, исправление которых требовало серьезного изменения уже разработанных подпрограмм, при этом в программу часто вносились новые ошибки. В итоге процесс тестирования и отладки программ занимал более 80% времени разработки, если вообще когда-нибудь заканчивался. Анализ причин возникновения ошибок позволил сформулировать новый подход к программированию - структурный.
Структурный подход к программированию, который развивался на втором этапе развития технологий в 60-70 годы XX века, представляет собой совокупность рекомендуемых технологических приемов, охватывающих выполнение всех этапов разработки программного обеспечения. В его основе лежит декомпозиция сложных систем с целью последующей реализации в виде отдельных небольших (до 40-50 операторов) подпрограмм, позже названная процедурной декомпозицией. Структурный подход требовал представления задачи в виде иерархии подзадач простейшей структуры, а проектирование осуществлялось «сверху-вниз» и подразумевало реализацию общей идеи. Были введены ограничения на конструкции алгоритмов, рекомендованы формальные модели их описания, а также специальный метод проектирования алгоритмов - метод пошаговой детализации. Принципы структурного программирования были заложены в основу процедурных языков программирования, которые включали основные «структурные» операторы передачи управления, поддерживали вложение подпрограмм, локализацию и ограничение области «видимости» данных (PL/1, ALGOL-68, Pascal, С). Дальнейший рост сложности и размеров разрабатываемого программного обеспечения потребовал развития структурирования данных, в языках появляется возможность определения пользовательских типов данных [2].
Стремление разграничить доступ к глобальным данным программы дало толчок к появлению и развитию технологии модульного программирования (рисунок А.1), что предполагало выделение групп подпрограмм, использующих одни и те же глобальные данные в отдельно компилируемые модули (библиотеки). Связи между модулями осуществлялись через специальный интерфейс, в то время как доступ к реализации модуля (телам подпрограмм и некоторым «внутренним» переменным) был запрещен. Эту технологию поддерживают современные версии Pascal, С, C++, Ада и Modula. Разработка программ несколькими программистами существенно упростилась: модули разрабатывались независимо друг от друга и могли использоваться без изменений в других разработках, а их взаимодействие обеспечивалось через специально оговоренные межмодульные интерфейсы. Структурный подход в сочетании с модульным программированием позволяет получать надежные программы, размером не более 100 000 операторов. Недостаток: ошибка в интерфейсе при вызове подпрограммы выявляется только при выполнении программы (из-за раздельной компиляции модулей), а при увеличении размера программы возрастает сложность межмодульных интерфейсов, поэтому предусмотреть взаимовлияние отдельных частей программы становится практически невозможно. Для разработки программного обеспечения большого объема было предложено использовать объектный подход.
На третьем этапе (80-е - 90-е годы XX века) был сформирован объектный подход к программированию. Технология создания сложного программного обеспечения, основанная на представлении программы в виде совокупности взаимодействующих путем передачи сообщений программных объектов, каждый из которых является экземпляром определенного класса, а классы образуют иерархию с наследованием свойств, была названа объектно-ориентированным программированием (рисунок А.2). Объектная структура программы впервые была использована в языке имитационного моделирова-ния сложных систем Simula, а затем использована в новых версиях универсальных языков программирования, таких как Pascal, C++, Modula, Java. Достоинством объектно-ориентированного программирования является «естественная» декомпозиция программного обеспечения, существенно облегчающая разработку. Это приводит к более полной локализации данных и интегрированию их с подпрограммами обработки, что позволяет вести практически независимую разработку отдельных объектов программы. Кроме того, объектный подход предлагает новые способы организации программ, основанные на механизмах наследования, полиморфизма, композиции, наполнения, позволяющих конструировать из простых объектов сложные. В результате существенно увеличивается показатель повторного использования кодов и появляется возможность создания библиотек классов. На основе объектного подхода были созданы среды, поддерживающие визуальное программирование (Delphi, C++ Builder, Visual C++), при использовании которого некоторая часть будущего продукта проектируется с применением визуальных средств добавления и настройки специальных библиотечных компонентов. В результате появляется заготовка будущей программы, в которую уже внесены коды. Использование объектного подхода имеет много преимуществ, однако его конкретная реализация в объектно-ориентированных языках программирования, таких, как Pascal и C++, имеет существенные недостатки: отсутствуют стандарты компоновки двоичных результатов компиляции объектов в единое целое даже в пределах одного языка программирования; изменение в реализации одного программного объекта связано с перекомпиляцией модуля и перекомпоновкой всего программного обеспечения, использующего данный объект. Таким образом, сохраняется объективная зависимость модулей программного обеспечения от адресов экспортируемых полей и методов, а также структур и форматов данных. Связи модулей нельзя разорвать, но можно стандартизировать их взаимодействие, на чем и основан компонентный подход к программированию.
Четвертый этап (90-е годы XX века - наше время) - компонентный подход и CASE-технологии. Компонентный подход предполагает построение программного обеспечения из отдельных компонентов, которые взаимодействуют между собой через стандартизованные двоичные интерфейсы. В отличие от обычных объектов объекты-компоненты можно собрать в динамически вызываемые библиотеки или исполняемые файлы, распространять в двоичном виде (без исходных текстов) и использовать в любом языке программирования, поддерживающем соответствующую технологию[1]. Компонентный подход лежит в основе технологий, разработанных на базе COM (Component Object Model - компонентная модель объектов, и технологии создания распределенных приложений CORBA (Common Object Request Broker Architecture - общая архитектура с посредником обработки запросов объектов), которые используют сходные принципы и различаются лишь особенностями реализации.
Дополнительную информацию по теме можно получить в [1, 2, 3, 5, 19].
2 Лекция № 2. Разработка сложных программных систем
Содержание лекции: обзор современных технологий программирования; разработка сложных программных систем.
Цель лекции: получить представление о технологиях COM, CORBA, CASE; выявить проблемы разработки сложных систем; рассмотреть блочно-иерархический подход к их созданию.
Среди современных технологий программирования по праву считаются лидерами технологии COM, CORBA и CASE.
Технология СОМ фирмы Microsoft является развитием технологии OLE I (Object Linking and Embedding - связывание и внедрение объектов), которая использовалась в ранних версиях Windows для создания составных документов. Она определяет общую концепцию взаимодействия программ любых типов (библиотек, приложений, операционной системы), т. е. позволяет одной части программного обеспечения использовать функции (службы), предоставляемые другой (рисунок А3). Модификация СОМ, обеспечивающая передачу вызовов между компьютерами, называется DCOM (Distributed COM - распределенная СОМ). Приложение предоставляет свои службы, используя специальные объекты - объекты СОМ (экземпляры классов СОМ). Объект СОМ включает поля и методы, но в отличие от обычных, каждый объект СОМ может реализовывать несколько интерфейсов, обеспечивающих доступ к его полям и функциям за счет организации отдельной таблицы адресов методов для каждого интерфейса. Классы СОМ поддерживают наследование интерфейсов, но не поддерживают наследования реализации, т. е. не наследуют код методов. Объект всегда функционирует в составе сервера - динамической библиотеки или исполняемого файла, которые обеспечивают функционирование объекта. Различают три типа серверов: внутренний, локальный и удаленный (например, MS Word является локальным сервером). Для обращения к службам клиент должен получить указатель на соответствующий интерфейс. Взаимодействие клиента и сервера обеспечивается базовыми механизмами СОМ или DCOM, поэтому клиенту безразлично местонахождение объекта. При использовании локальных и удаленных серверов в адресном пространстве клиента создается proxy-объект - заместитель объекта СОМ, а в адресном пространстве сервера СОМ-заглушка, соответствующая клиенту. Получив задание от клиента, заместитель упаковывает его параметры и, используя службы операционной системы, передает вызов заглушке. Заглушка распаковывает задание и передает его объекту СОМ. Результат возвращается клиенту в обратном порядке. На базе технологии СОМ и ее распределенной версии DCOM были разработаны компонентные технологии, решающие различные задачи разработки программного обеспечения [1]. К технологиям, реализующим компонентный подход, заложенный в СОМ, относятся:
а) OLE-automation - технология создания программируемых приложений, обеспечивающая программируемый доступ к их внутренним службам (например, MS Excel поддерживает ее, предоставляя другим приложениям свои службы);
б) ActiveX - технология, построенная на базе OLE-automation и предназначенная для создания как сосредоточенного на одном компьютере программного обеспечения, так и распределенного в сети. Предполагает использование визуального программирования для создания компонентов - элементов управления ActiveX, которые устанавливаются на компьютер дистанционно с удаленного сервера и применяются в клиентских частях приложений Интернет. Преимуществами технологии ActiveX являются: быстрое написание кода; открытость и мобильность; возможность написания приложений с использованием знакомых средств разработки (Visual Basic, Visual C++, Borland Delphi, Borland C++, Java); большое количество существующих бесплатных программных элементов ActiveX; стандартность;
в) MTS (Microsoft Transaction Server - сервер управления транзакциями) - технология, обеспечивающая безопасность и стабильную работу распределенных приложений при больших объемах передаваемых данных;
г) MIDAS (Multitier Distributed Application Server - сервер многозвенных распределенных приложений) - технология, организующая доступ к данным разных компьютеров с учетом балансировки нагрузки сети.
Технология CORBA, разработанная группой компаний OMG (Object Management Group - группа внедрения объектной технологии программирования), реализует подход аналогичный СОМ, на базе объектов и интерфейсов CORBA. Программное ядро CORBA реализовано для всех основных аппаратных и программных платформ, и потому технологию можно использовать для создания распределенного программного обеспечения в разнородной вычислительной среде. Организация взаимодействия между объектами клиента и сервера в CORBA осуществляется с помощью посредника (VisiBroker) и специализированного программного обеспечения.
Отличительной особенностью современного этапа развития технологии программирования, кроме изменения подхода, является создание и внедрение автоматизированных технологий разработки и сопровождения программного обеспечения, которые были названы CASE-технологиями (Computer-Aided Software/System Engineering - разработка программного обеспечения/программных систем с использованием компьютерной поддержки). Без средств автоматизации разработка достаточно сложного программного обеспечения на настоящий момент становится трудно осуществимой: память человека уже не в состоянии фиксировать все детали, которые необходимо учитывать при разработке программного обеспечения. CASE-технологии поддерживают как структурный, так и объектный (компонентный) подходы к программированию [5].
Большинство современных программных систем являются достаточно сложными. Эта сложность обуславливается многими причинами, главной из которых является логическая сложность решаемых ими задач. Раньше компьютеры применяли в очень узких областях науки и техники, в первую очередь там, где задачи были хорошо детерминированы и требовали значительных вычислений. Сейчас, когда созданы мощные компьютерные сети, появилась возможность переложить на них решение сложных ресурсоемких задач, о компьютеризации которых раньше не задумывались. В процесс компьютеризации вовлекаются новые предметные области, а для освоенных областей усложняются уже сложившиеся постановки задач. Сложность разработки программных систем увеличивается за счет сложности формального определения требований к этим системам, отсутствия удовлетворительных средств описания поведения дискретных систем с большим числом состояний при недетерминированной последовательности входных воздействий, коллективной разработки, необходимости увеличения степени повторяемости кодов. Однако все эти факторы напрямую связаны со сложностью объекта разработки - программной системы [4].
Подавляющее большинство сложных систем, как в природе, так и в технике имеет иерархическую внутреннюю структуру. Связи элементов сложных систем различны как по типу, так и по силе, что и позволяет рассматривать эти системы как некоторую совокупность взаимозависимых подсистем. Внутренние связи элементов таких подсистем сильнее, чем связи между подсистемами. Например, компьютер состоит из процессора, памяти и внешних устройств, а Солнечная система включает Солнце и планеты, вращающиеся вокруг него. Используя то же различие связей, каждую подсистему можно аналогично разделить на подсистемы до «элементарного» уровня, причем выбор уровня, компоненты которого следует считать элементарными, остается за исследователем. На элементарном уровне система, состоит из немногих типов подсистем, по-разному скомбинированных и организованных. Иерархии такого типа получили название «целое-часть».
В природе существует еще один вид иерархии - иерархия «простое-сложное» или иерархия развития (усложнения) систем в процессе эволюции. В этой иерархии любая функционирующая система является результатом развития более простой системы. Именно этот вид иерархии реализуется механизмом наследования объектно-ориентированного программирования.
Будучи отражением природных и технических систем, программные системы являются иерархическими и обладают описанными выше свойствами. На этих свойствах иерархических систем строится блочно-иерархический подход к их исследованию или созданию, предполагающий сначала создание частей объекта (блоков и модулей), а затем сборку из них самого объекта.
Процесс разбиения сложного объекта на сравнительно независимые части получил название декомпозиции. При декомпозиции учитывают, что связи между отдельными частями должны быть слабее, чем связи элементов внутри частей. Чтобы из полученных частей можно было собрать разрабатываемый объект, в процессе декомпозиции необходимо определить все виды связей частей между собой. При создании сложных объектов процесс декомпозиции выполняется многократно: каждый блок, в свою очередь, декомпозируют на части, пока не получают блоки, которые сравнительно легко разработать. Этот метод разработки получил название пошаговой детализации. В процессе декомпозиции стараются выделить аналогичные блоки, которые можно было бы разрабатывать на общей основе. Таким образом, обеспечивают увеличение степени повторяемости кодов и, соответственно, снижение стоимости разработки. Результат декомпозиции обычно представляют в виде схемы иерархии, на нижнем уровне которой располагают сравнительно простые блоки, а на верхнем - объект, подлежащий разработке. На каждом иерархическом уровне описание блоков выполняют с определенной степенью детализации, абстрагируясь от несущественных деталей. Как правило, для объекта в целом, удается сформулировать лишь общие требования, а блоки нижнего уровня должны быть специфицированы таким образом, чтобы из них действительно можно было собрать работающий объект. Другими словами, чем больше блок, тем более абстрактным должно быть его описание (рисунок А.4). При соблюдении этого принципа разработчик сохраняет возможность осмысления проекта и принимает наиболее правильные решения на каждом этапе, что называют локальной оптимизацией (в отличие от глобальной оптимизации характеристик объектов, которая для действительно сложных объектов не всегда возможна).
Итак, в основе блочно-иерархического подхода лежат иерархическое упорядочение и декомпозиция. Важную роль играют следующие принципы:
а) непротиворечивость - контроль согласованности элементов;
б) полнота - контроль на присутствие лишних элементов;
в) формализация - строгость методического подхода;
г) повторяемость -
необходимость выделения одинаковых блоков для
удешевления и
ускорения разработки;
д) локальная оптимизация - оптимизация в пределах уровня иерархии.
Совокупность языков моделей, постановок задач, методов описаний некоторого иерархического уровня принято называть уровнем проектирования. Различные взгляды на объект проектирования принято называть аспектами проектирования. Достоинства блочно-иерархического подхода: возможность создания сложных систем; упрощение проверки работоспособности отдельных блоков и системы в целом; обеспечение возможности модернизации систем. Использование блочно-иерархического подхода применительно к программным системам стало возможным только после конкретизации общих положений подхода и внесения изменений в процесс проектирования. При этом структурный подход учитывает только свойства иерархии «целое-часть», а объектный дополнительно использует свойства иерархии «простое-сложное».
Дополнительную информацию по теме можно получить в [1, 4, 5, 10].
3 Лекция № 3. Жизненный цикл программного обеспечения
Содержание лекции: жизненный цикл и этапы разработки программного обеспечения; современные CASE-технологии.
Цель лекции: получить представление о составе процессов и эволюции моделей жизненного цикла, а также рассмотреть влияние CASE-технологий на изменение жизненного цикла программного обеспечения.
Жизненным циклом программного обеспечения (ПО) называют период от момента появления идеи создания некоторого программного обеспечения до момента завершения его поддержки фирмой-разработчиком или фирмой, выполняющей сопровождение [4]. Состав процессов жизненного цикла регламентируется международным стандартом ISO/IEC 12207: 1995 «Information Technologe - Software Life Cycle Processes» («Информационные технологии - Процессы жизненного цикла программного обеспечения»). Стандарт описывает структуру жизненного цикла ПО, называет и определяет процессы жизненного цикла ПО, не конкретизируя в деталях, как реализовывать или выполнять действия и задачи, включенные в эти процессы. Процесс жизненного цикла – это совокупность взаимосвязанных действий, преобразующих некоторые входные данные в выходные. На рисунке A.5 представлены процессы жизненного цикла по указанному стандарту, каждый из которых характеризуется определенными задачами и методами их решения, а также исходными данными и результатами.
Процесс разработки (development process) в соответствии со стандартом предусматривает действия: подготовительную работу, анализ требований к системе, проектирование архитектуры системы, анализ требований к ПО, проектирование архитектуры ПО, детальное проектирование ПО, кодирование и тестирование ПО, интеграцию ПО, квалификационное тестирование ПО, интеграцию системы, квалификационное тестирование системы, установку и приемку ПО. Сгруппировав указанные действия, условно выделяют следующие основные этапы разработки программного обеспечения (в скобках указаны соответствующие стадии разработки по ГОСТ 19.102-77 «Стадии разработки»):
а) постановка задачи (стадия «Техническое задание») - формулируется назначение программного обеспечения, а также определяются основные требования к нему (функциональные и эксплуатационные). Результатом является разработка технического задания, фиксирующего принципиальные требования, и принятие основных проектных решений;
б) анализ требований и разработка спецификаций
(стадия «Эскизный
проект») - выполняется анализ требований технического задания, формулируется
содержательная постановка задачи, выбирается математический аппарат
формализации, строится модель предметной области, определяются подзадачи и
выбираются или разрабатываются методы их решения, формируются тесты для поиска
ошибок в проектируемом программном обеспечении с указанием ожидаемых результатов.
Точное формализованное описание функций и ограничений разрабатываемого ПО
называется спецификациями, часть из которых может быть определена в процессе
предпроектных исследований и зафиксирована в техническом задании; различают
функциональные и эксплуатационные спецификации. Совокупность спецификаций
представляет собой общую логическую модель проектируемого программного
обеспечения;
в) проектирование (стадия «Технический проект») - определяются подробные спецификации разрабатываемого программного продукта, выполняется проектирование общей структуры, декомпозиция компонентов и построение структурных иерархий в соответствии блочно-иерархическим подхода, проектирование компонентов. Результат - детальная модель разрабатываемого ПО со спецификациями компонентов всех уровней; тип модели зависит от выбранного подхода и конкретной технологии проектирования. Различают логическое и физическое проектирование;
г) реализация (стадия «Рабочий проект») - процесс поэтапного написания кодов программы на выбранном языке программирования (кодирование), их тестирование и отладка.
Сопровождение - это процесс создания и внедрения новых версий программного обеспечения, причинами выпуска которых могут служить необходимость исправления ошибок, выявленных в процессе эксплуатации предыдущих версий; необходимость совершенствования предыдущих версий (улучшение интерфейса, расширение состава выполняемых функций или повышение его производительности); изменение среды функционирования, (появление новых технических средств и/или программных продуктов, с которыми взаимодействует сопровождаемое программное обеспечение). В программный продукт вносят необходимые изменения, которые могут потребовать пересмотра уже принятых проектных решений. С изменением модели жизненного цикла ПО роль этого этапа существенно возросла, так как продукты теперь создаются итерационно: сначала выпускается сравнительно простая версия, затем следующая с большими возможностями, затем следующая и т. д. Поэтому этап сопровождения был выделен в отдельный процесс жизненного цикла в соответствии со стандартом ISO/IEC 12207.
На протяжении последних тридцати лет в программировании сменились три модели жизненного цикла программного обеспечения: каскадная, модель с промежуточным контролем и спиральная [1].
Первоначально (1970-1985) была предложена и использовалась каскадная схема разработки ПО (рисунок Б.1), которая предполагала, что переход на следующую стадию осуществляется только после того, как полностью будут завершены проектные операции предыдущей стадии и получены все исходные данные для следующей стадии. Достоинствами такой схемы являются получение в конце каждой стадии законченного набора проектной документации, отвечающего требованиям полноты и согласованности, а также простота планирования процесса разработки. Именно эту схему используют обычно при блочно-иерархическом подходе к разработке сложных технических объектов, обеспечивая очень высокие параметры эффективности разработки. Однако схема оказалась применимой только к созданию систем, для которых в самом начале разработки удавалось точно и полно сформулировать все требования, что уменьшало вероятность возникновения в процессе разработки проблем, связанных с принятием неудачного решения на предыдущих стадиях. На практике такие разработки встречается крайне редко. В целом необходимость возвратов на предыдущие стадии обусловлена следующими причинами: неточные спецификации; изменение требований заказчика непосредственно в процессе разработки; быстрое моральное устаревание используемых технических и программных средств; отсутствие удовлетворительных средств описания разработки на стадиях постановки задачи, анализа и проектирования. Реальный же процесс носит итерационный характер.
Схема, поддерживающая итерационный характер процесса разработки, была названа моделью с промежуточным контролем (рисунок Б.2). Контроль, выполняемый по данной схеме после завершения каждого этапа, позволяет вернуться на любой уровень и внести изменения. Основная опасность использования такой схемы связана с тем, что разработка никогда не будет завершена, постоянно находясь в состоянии уточнения и усовершенствования.
Для преодоления перечисленных проблем в середине 80-х годов XX века была предложена спиральная схема (рисунок Б.3). В соответствии с данной схемой ПО создается не сразу, а итерационно с использованием метода прототипирования, базирующегося на создании прототипов - действующих программных продуктов, реализующих отдельные функции и внешние интерфейсы разрабатываемого программного обеспечения. На первой итерации специфицируют, проектируют, реализуют и тестируют интерфейс пользователя; на второй - добавляют некоторый ограниченный набор функций; на последующих этапах набор расширяют, наращивая возможности продукта. Достоинство схемы: начиная с некоторой итерации, на которой обеспечена определенная функциональная полнота, продукт можно предоставлять пользователю, что позволяет сократить время до появления первых версий программного продукта; заинтересовать большое количество пользователей, обеспечивая быстрое продвижение следующих версий продукта на рынке; ускорить формирование и уточнение спецификаций за счет появления практики использования продукта; уменьшить вероятность морального устаревания системы за время разработки. Основной проблемой использования схемы является определение моментов перехода на следующие стадии, для чего ограничивают сроки прохождения каждой стадии, основываясь на экспертных оценках.
Изменение жизненного цикла программного обеспечения стало возможным в результате использования при разработке ПО CASE-технологий. CASE-технологии представляют собой совокупность методологий анализа, проектирования, разработки и сопровождения сложных программных систем, основанных как на структурном, так и на объектном подходах, которые поддерживаются комплексом взаимосвязанных средств автоматизации. В основу любой CASE-технологии положены методология, метод, нотация и средства [5].
Среди средств различают CASE-средства
анализа требований, проектирования спецификаций и структуры,
редактирования интерфейсов (первое поколение CASE-I, в основном
включают средства для поддержки графических моделей, проектирования
спецификаций, экранных редакторов и словарей данных); CASE-средства
генерации исходных текстов и реализации интегрированного окружения поддержки
полного жизненного цикла разработки ПО (второе поколение CASE-II, существенно
отличается большими возможностями, обеспечивая контроль, анализ и связывание
системной информации и информации по управлению процессом проектирования,
построение прототипов и моделей системы, тестирование, верификацию и анализ
сгенерированных программ). Автоматизируя трудоемкие операции, современные
CASE-средства существенно повышают производительность труда программистов и
улучшают качество создаваемого программного обеспечения, поскольку обеспечивают
автоматизированный контроль совместимости спецификаций проекта; уменьшают время
создания прототипа системы; ускоряют процесс проектирования и разработки; автоматизируют
формирование проектной документации для всех этапов жизненного цикла в
соответствии с современными стандартами; частично генерируют коды программ для
различных платформ разработки; поддерживают технологии повторного использования
компонентов системы; обеспечивают возможность восстановления проектной
документации
по имеющимся исходным кодам.
Появление CASE-технологий изменило все этапы жизненного цикла программного обеспечения, при этом наибольшие изменения касаются анализа и проектирования, которые предполагают строгое и наглядное описание разрабатываемого программного обеспечения. Однако современные CASE-средства дороги, а их использование требует более высокой квалификации разработчиков, следовательно, имеет смысл использовать их в сложных проектах, причем, чем сложнее разрабатываемое программное обеспечение, тем больше выигрыш от использования CASE-технологий. На сегодняшний день практически все промышленно производимое сложное программное обеспечение разрабатывается с использованием CASE-средств.
Разработка спиральной модели жизненного цикла программного обеспечения и CASE-технологии позволили сформулировать условия, выполнение которых сокращает сроки создания программного обеспечения.
Дополнительную информацию по теме можно получить в [1, 4, 5, 8].
4 Лекция № 4. Быстрая разработка приложений. Технологичность программного обеспечения
Содержание лекции: технология быстрой разработки приложений; оценка качества процессов создания программного обеспечения; технологичность ПО.
Цель лекции: рассмотреть использование RAD-технологии и существующие методы оценки качества процессов создания программного обеспечения; а также приемы обеспечения эффективности и технологичности программного обеспечения.
Современная технология проектирования, разработки и сопровождения программного обеспечения, должна отвечать следующим требованиям [1]:
а) поддержка полного жизненного цикла программного обеспечения;
б) гарантированное достижение целей разработки с заданным качеством
и в установленное время;
в) координация ведения проекта с возможностью выполнения крупных проектов в виде подсистем, разрабатываемых группами исполнителей ограниченной численности, с последующей интеграцией составных частей;
г) минимальное время получения работоспособной системы;
д) возможность управления конфигурацией проекта, ведения версий и автоматического выпуска проектной документации по каждой версии;
е) независимость проектных решений от средств реализации;
ж) поддержка комплексом CASE-средств, обеспечивающих автоматиза-цию процессов, выполняемых на всех стадиях жизненного цикла.
Этим требованиям отвечает технология RAD (Rapid Application Development - Быстрая разработка приложений), ориентирована на максимально быстрое получение первых версий разрабатываемого программного обеспечения и предусматривающая выполнение следующих условий [3]:
а) ведение разработки небольшими группами исполнителей (3-7 человек), каждая из которых проектирует и реализует отдельные подсистемы проекта, что позволяет улучшить управляемость проекта;
б) использование итерационного подхода, способствующего уменьшению времени получения работоспособного прототипа;
в) наличие четко
проработанного графика цикла, рассчитанного не более
чем на три месяца, что существенно
увеличивает эффективность работы.
Процесс разработки делится на этапы анализа и планирования требований пользователей, проектирования, реализации, внедрения.
На этапе анализа и планирования требований формулируют наиболее приоритетные требования, что ограничивает масштаб проекта.
На этапе проектирования, используя имеющиеся CASE-средства, детально описывают процессы системы, устанавливают требования разграничения доступа к данным и определяют состав необходимой документации. При этом для наиболее сложных процессов создают частичный прототип: разрабатывают экранную форму и диалог. По результатам анализа процессов определяют количество так называемых функциональных точек и принимают решение о количестве подсистем и, соответственно, команд, участвующих в разработке. Под функциональной точкой в технологии RAD понимают любой из функциональных элементов разрабатываемой системы: входной элемент приложения; выходной элемент приложения; запрос; логический файл; интерфейс приложения. В соответствии с нормами, рассчитанными исходя из экспертных оценок, разрабатываемую систему делят на подсистемы, слабо связанные по данным и функциям, и точно определяют интерфейсы между различными частями. Использование CASE-средств позволяет избежать неконтролируемого искажения данных при передаче информации о проекте со стадии на стадию. Далее разработка ведется группами разработчиков, которые продолжают прорабатывать свои части системы, при этом их должны быть хорошо скоординированы.
На этапе реализации выполняют итеративное построение реальной системы, причем для контроля над выполнением требований к создаваемой системе привлекаются будущие пользователи. Части постепенно интегрируют в систему, при подключении каждой части выполняют тестирование. Определяют необходимость создания соответствующих баз данных, подключаемых к системе, формулируют требования к аппаратным средствам, устанавливают способы увеличения производительности и завершают подготовку документации по проекту.
На этапе внедрения проводят обучение пользователей и осуществляют постепенный переход на новую систему, причем эксплуатация старой версии продолжается до полного внедрения новой системы.
Технология RAD хорошо зарекомендовала себя для небольших проектов, разрабатываемых для конкретного заказчика. Такие системы не требуют высокого уровня планирования и жесткой дисциплины проектирования. Однако эта технология неприменима для построения сложных расчетных программ, операционных систем или программ управления сложными объектами в реальном масштабе времени, т. е. программ с большим процентом уникального кода. Ее использование полностью исключается в случае создания приложений, от которых зависит безопасность людей, так как технология RAD предполагает, что первые версии не будут полностью работоспособны.
Текущий период на рынке программного обеспечения характеризуется переходом от штучного ремесленного производства программных продуктов к их промышленному созданию. Существенно возросли требования к качеству разрабатываемого программного обеспечения, что требует совершенствования процессов их разработки. К наиболее известным стандартам, связанным с оценкой качества этих процессов относят [4]:
а) международные стандарты серии ISO 9000 (ISO 9000 - ISO 9004), где сформулированы необходимые условия для достижения некоторого минимального уровня организации процесса, но не дается никаких рекомендаций по дальнейшему совершенствованию процессов;
б) СММ - Capability Maturity Model - модель зрелости (совершенствования) процессов создания программного обеспечения, предложенная SEI (Software Engineering Institute - институт программирования при университете Карнеги-Меллон), которая представляет собой совокупность критериев оценки зрелости организации-разработчика и рецептов улучшения существующих процессов. СММ определяет пять уровней зрелости организаций-разработчиков, причем каждый последующий уровень включает в себя все ключевые характеристики предыдущих: 1 - начальный уровень (initial level); 2 - повторяемый уровень (repeatable level); 3 - определенный уровень (defined level); 4 - управляемый уровень (managed level); 5 - оптимизирующий уровень (optimizing level). При этом сертификационная оценка соответствия ключевых областей проводится по 10-балльной шкале. Оценка ключевой области выполняется по следующим показателям: заинтересованность руководства в данной области; насколько широко область применяется в организации; успешность использования данной области на практике. Допускается сертификация одного процесса или подразделения организации;
в) рабочая версия международного стандарта ISO/IEC 15504: Information Technology - Software Process Assessment, более известная под названием SPICE - (Software Process Improvement and Capability Determination - определение возможностей и улучшение процесса создания программного обеспечения), унаследовавшая многие черты более ранних стандартов, в том числе ISO 9001 и СММ. Так же, как и в СММ, основной задачей является постоянное улучшение процесса разработки программного обеспечения, кроме того, в SPICE тоже используется схема с различными уровнями возможностей (в SPICE определено 6 различных уровней). В основу стандарта положена оценка процессов, которая выполняется путем сравнения процесса разработки программного обеспечения, существующего в данной организации, с описанной в стандарте моделью. Анализ результатов помогает определить сильные и слабые стороны процесса, а также внутренние риски, присущие данному процессу, что позволяет оценить эффективность процессов, определить причины ухудшения качества и связанные с этим издержки во времени или стоимости.
Таким образом, создание программных продуктов по-прежнему предъявляет повышенные требования к квалификации проектировщиков и программистов. Качество проекта программного продукта, от которого зависят трудовые и материальные затраты на его реализацию и последующие модификации, называют технологичностью. Хороший проект быстро и легко кодируется, тестируется, отлаживается и модифицируется. Технологичность программного обеспечения определяется проработанностью его моделей, уровнем независимости модулей, стилем программирования и степенью повторного использования кодов. Высокая технологичность проекта особенно важна, если необходимо обеспечить повышенные требования к его качеству или разрабатывается программный продукт, рассчитанный на многолетнее интенсивное использование.
Традиционно эффективными считаются программы, требующие минимального времени выполнения и/или минимального объема оперативной памяти. Особые требования к эффективности программного обеспечения предъявляются при наличии ограничений (на объем оперативной памяти, время реакции системы). Разумный подход к обеспечению эффективности программного обеспечения состоит в том, чтобы в первую очередь оптимизировать те фрагменты программы, которые существенно влияют на характеристики эффективности. Однако многие способы снижения временных затрат приводят к увеличению емкостных и, наоборот, уменьшение объема памяти может потребовать дополнительного времени на обработку. Частично проблему эффективности программ решают за программиста компиляторы. Используемые ими средства оптимизации делятся на машинно-зависимые и машинно-независимые. Конечно, нельзя вмешаться в работу компилятора, но существуют возможности оптимизации на уровне команд.
Принятие мер по экономии памяти предполагает, что в каких-то случаях эта память неэкономно использовалась. Имеет смысл анализировать только операции размещения данных, существенно влияющие на характеристику эффективности (например, выделение памяти под данные структурных типов: массивов, записей, объектов). Следует выбирать алгоритмы обработки, не требующие дублирования исходных данных структурных типов в процессе обработки. Если в программе имеются большие массивы, используемые ограниченное время, их можно размещать в динамической памяти и удалять при завершении обработки. При передаче структурных данных в подпрограмму «по значению», копии этих данных размещаются в стеке. Избежать копирования иногда удается, если передавать данные «по ссылке», но как неизменяемые const (в стеке размещается только адрес данных).
Для уменьшения времени выполнения в первую очередь необходимо анализировать циклические участки программы с большим количеством повторений: по возможности следует выносить вычисление константных выражений из циклов, избегать «длинных» операций умножения и деления, заменяя их сложением, вычитанием и сдвигами, минимизировать преобразования типов в выражениях, исключать лишние проверки при записи условных выражений и многократные обращения к элементам массивов по индексам, избегать использования различных типов в выражении.
За увеличение эффективности не следует «платить» снижением технологичности разрабатываемого программного обеспечения. Исключения возможны лишь при очень жестких требованиях и наличии соответствующего контроля за качеством.
Дополнительную информацию по теме можно получить в [1, 3, 4, 7, 8].
5 Лекция № 5. Приемы обеспечения технологичности программных продуктов
Содержание лекции: модули и их свойства; нисходящая и восходящая разработка ПО.
Цель лекции: рассмотреть существующие способы декомпозиции ПО, методы разработки программного обеспечения.
При проектировании достаточно сложного ПО используют два способа декомпозиции разрабатываемого программного обеспечения, связанные с соответствующим подходом: процедурный (структурный) и объектный.
Результатом процедурной декомпозиции является иерархия подпрограмм (процедур), где функции принятия решения реализуются подпрограммами верхних уровней, а обработка - подпрограммами нижних уровней. Это согласуется с принципом вертикального управления, который был сформулирован вместе с другими рекомендациями структурного подхода к программированию и ограничивает возможные варианты передачи управления, требуя, чтобы любая процедура возвращала управление той подпрограмме, которая ее вызвала. Результатом объектной декомпозиции является совокупность объектов, которые реализуются как переменные некоторых специально разрабатываемых типов.
При любом способе декомпозиции получают набор связанных с соответствующими данными подпрограмм, которые в процессе реализации организуют в модули - автономно компилируемые программные единицы. Первоначально, когда размер программ был невелик, и подпрограммы компилировались отдельно, под модулем понималась последовательность связанных фрагментов программы, обращение к которой выполняется по имени. Со временем, когда размер программ значительно вырос, и появилась возможность создавать библиотеки ресурсов, под модулем стали понимать автономно компилируемый набор программных ресурсов. Данные модуль получает и/или возвращает через общие области памяти или параметры. Чем выше степень независимости модулей, тем легче разобраться в отдельном модуле и всей программе, тестировать, отлаживать и модифицировать ее; меньше вероятность появления новых ошибок при исправлении старых или внесении изменений в программу; проще организовать разработку программы группой программистов и легче ее сопровождать. Уменьшение зависимости модулей улучшает технологичность проекта. Степень независимости модулей оценивается двумя критериями: сцеплением и связностью.
Сцепление - это мера взаимозависимости модулей, определяющая насколько хорошо модули отделены друг от друга. Модули независимы, если каждый из них не содержит никакой информации о другом модуле. Различают пять типов сцепления модулей:
а) сцепление по данным - модули обмениваются данными в скалярных значениях. При небольшом количестве передаваемых параметров этот тип обеспечивает наилучшие технологические характеристики ПО;
б) сцепление по образцу - модули обмениваются данными, объединен-ными в структуры. Однако, уменьшается «прозрачность» связи между модулями, так как передаваемые данные «спрятаны» в структуры, а при изменении структуры необходимо модифицировать все использующие ее модули. Дает неплохие характеристики, но хуже, чем у предыдущего типа;
в) сцепление по управлению - один модуль посылает другому некоторый информационный объект (флаг), предназначенный для управления внутренней логикой модуля. Такие настройки снижают наглядность взаимодействия модулей и обеспечивают худшие характеристики технологичности программ по сравнению с предыдущими типами;
г) сцепление по общей области данных - модули работают с общей областью данных. Считается недопустимым, поскольку программы, использующие данный тип сцепления, сложны для понимания при сопровождении ПО; ошибка одного модуля, приводящая к изменению общих данных, может проявиться при выполнении другого модуля; при ссылке к данным в общей области модули используют конкретные имена, что уменьшает гибкость разрабатываемого ПО;
д) сцепление по содержимому - один модуль содержит обращения к внутренним компонентам другого (передает управление внутрь, читает и/или изменяет внутренние данные или сами коды), что полностью противоречит блочно-иерархическому подходу. Отдельный модуль в этом случае уже не является блоком («черным ящиком»): его содержимое должно учитываться в процессе разработки другого модуля. Такой вид сцепления остается возможным для языков низкого уровня, например, Ассемблера.
Допустимыми считают первые три типа сцепления, использование остальных приводит к резкому ухудшению технологичности программ. Как правило, модули сцепляются между собой несколькими способами. Учитывая это, качество принято определять по типу сцепления с худшими характеристиками. Например, при использовании сцепления по данным и сцепления по управлению, определяющим считают сцепление по управлению.
Связность - мера прочности соединения функциональных и информационных объектов внутри одного модуля, т.е. степень взаимосвязи элементов, реализуемых одним модулем. Размещение сильно связанных элементов в одном модуле уменьшает межмодульные связи и взаимовлияние модулей. В то же время размещение сильно связанных элементов в разных модулях не только усиливает межмодульные связи, но и усложняет понимание их взаимодействия. Объединение слабо связанных элементов также уменьшает технологичность модулей, так как такими элементами сложнее мысленно манипулировать. Различают следующие виды связности:
а) функциональная - все объекты модуля предназначены для выполнения одной функции;
б) последовательная - выход одной функции служит исходными данными для другой функции;
в) информационная - функции, обрабатывающие одни и те же данные;
г) процедурная - функции или данные, которые являются частями одного процесса;
д) временная - функции выполняются параллельно или в течение некоторого периода времени;
е) логическая - базируется на объединении данных или функций в одну логическую группу;
ж) случайная - связь между элементами мала или отсутствует.
Целесообразно использовать функциональную, последовательную и информационную связности.
При рассмотрении модуля как библиотеки ресурсов выделяют библиотеки подпрограмм, реализующие функции, близкие по назначению, и библиотеки классов, реализующие близкие по назначению классы. В качестве средства улучшения технологических характеристик библиотек ресурсов используют разделение тела модуля на интерфейсную часть и область реализации (в Паскале –Interface и Implementation, в C++ - h и cpp-файлы). Интерфейсная часть содержит совокупность объявлений ресурсов (заголовков функций, имен переменных, типов, классов), предоставляемых другим модулям. Необъявленные ресурсы извне не доступны. Область реализации содержит тела подпрограмм и внутренние ресурсы (подпрограммы, переменные, типы), используемые этими подпрограммами. При такой организации любые изменения реализации библиотеки, не затрагивающие ее интерфейс, не требуют пересмотра модулей, связанных с библиотекой, что улучшает технологичность модулей-библиотек.
При проектировании, реализации и тестировании компонентов структурной иерархии применяют два подхода: восходящий и нисходящий [8].
При использовании восходящего подхода сначала проектируют и реализуют компоненты нижнего уровня, затем предыдущего и т.д. По мере завершения тестирования и отладки компонентов осуществляется их сборка, причем компоненты нижнего уровня помещают в библиотеки компонентов. Для тестирования и отладки разрабатывают специальные тестирующие программы. Недостатки: увеличивается вероятность несогласованности компонентов из-за неполноты спецификаций; издержки на проектирование и реализацию тестирующих программ, которые не преобразуют в компоненты; позднее проектирование интерфейса, невозможность продемонстрировать его заказчику для уточнения спецификаций. При промышленном изготовлении ПО восходящий подход практически не используют.
Нисходящий подход предполагает, что проектирование и последующая реализация компонентов выполняется «сверху-вниз»: вначале проектируют компоненты верхних уровней иерархии, затем следующих и так далее до самых нижних уровней. В той же последовательности выполняют и реализацию компонентов. При программировании компоненты нижних не реализованных уровней заменяют специально разработанными отладочными модулями - «заглушками», что позволяет тестировать и отлаживать уже реализованную часть. При использовании нисходящего подхода применяют иерархический, операционный и комбинированный методы определения последовательности проектирования и реализации компонентов.
Иерархический метод предполагает выполнение разработки строго по уровням. Исключения допускаются при наличии зависимости по данным (если обнаруживается, что некоторый модуль использует результаты другого, то его программируют после этого модуля). Недостаток метода: большое количество достаточно сложных заглушек, а при использовании данного метода основная масса модулей разрабатывается и реализуется в конце работы над проектом, что затрудняет распределение человеческих ресурсов.
Операционный метод связывает последовательность разработки модулей с порядком их выполнения при запуске программы. Применение метода усложняется тем, что порядок выполнения модулей может зависеть от данных, а модули вывода результатов должны разрабатываться одними из первых, чтобы не проектировать сложную заглушку, обеспечивающую вывод результатов при тестировании. С точки зрения распределения человеческих ресурсов сложным является начало работ, пока не закончены все модули, находящиеся на так называемом критическом пути.
Комбинированный метод учитывает все факторы, влияющие на последовательность разработки: достижимость модуля (наличие всех модулей в цепочке вызова данного модуля); зависимость по данным (модули, формирующие некоторые данные, должны создаваться раньше обрабатывающих); обеспечение возможности выдачи результатов (модули вывода результатов должны создаваться раньше обрабатывающих); готовность вспомогательных модулей (вспомогательные модули, например, модули закрытия файлов, завершения программы, должны создаваться раньше обрабатывающих); наличие необходимых ресурсов. Кроме того, при прочих равных условиях сложные модули должны разрабатываться прежде простых, так как при их проектировании могут выявиться неточности в спецификациях, а чем раньше это произойдет, тем лучше.
Нисходящий подход допускает нарушение нисходящей последовательности разработки компонентов в специально оговоренных случаях. Его используют и при объектно-ориентированном программировании: вначале проектируют и реализуют пользовательский интерфейс ПО, затем разрабатывают классы базовых объектов предметной области, а уже потом, используя эти объекты, проектируют и реализуют остальные компоненты. Нисходящий подход обеспечивает максимально полное определение спецификаций проектируемого компонента и согласованность компонентов между собой, раннее определение интерфейса пользователя, демонстрация которого позволяет уточнить требования заказчика к создаваемому ПО, возможность нисходящего тестирования и комплексной отладки.
Дополнительную информацию по теме можно получить в [1, 4, 7, 8, 9].
6 Лекция № 6. Структурное и «неструктурное» программирование
Содержание лекции: понятия структурного и «неструктурного» программирования; программирование с «защитой от ошибок»; сквозной структурный контроль.
Цель лекции: выявить разницу между структурным и «неструктурным» программированием, а также приемы обеспечения защиты от ошибок.
Одним из способов обеспечения высокого уровня технологичности разрабатываемого ПО является структурное программирование. Различают три вида вычислительного процесса, реализуемого программами: линейный, разветвленный и циклический. Линейная структура процесса вычислений предполагает, что для получения результата необходимо выполнить операции в определенной последовательности. При разветвленной структуре процесса вычислений конкретная последовательность операций зависит от значений одной или нескольких переменных. Для получения результата при циклической структуре некоторые действия необходимо выполнить несколько раз. Для реализации этих вычислительных процессов в программах используют соответствующие управляющие операторы. Для изображения схем алгоритмов таких программ был разработан ГОСТ 19.701-90, согласно которому каждой группе действий ставится в соответствие специальный блок. Стандарт предусматривает блоки для обозначения циклов, не запрещает произвольной передачи управления и допускает использование команд условной и безусловной передачи управления при реализации алгоритма.
После того, как в 60-х годах XX в. было доказано, что любой сложный алгоритм можно представить, используя три основные управляющие конструкции, в языках программирования высокого уровня появились управляющие операторы для их реализации [6]. К базовым относят:
а) следование - обозначает последовательное выполнение действий;
б) ветвление - выбор одного из двух вариантов действий;
в) цикл-пока - определяет повторение действий, пока не будет нарушено некоторое условие, выполнение которого проверяется в начале цикла.
Кроме базовых, процедурные языки программирования высокого уровня используют три дополнительные конструкции, реализуемые через базовые:
а) выбор - выбор одного варианта из нескольких в зависимости от значения некоторой величины;
б) цикл-до - повторение действий до выполнения заданного условия, проверка которого осуществляется после выполнения действий в цикле;
в) цикл с заданным числом повторений (счетный цикл) - повторение некоторых действий указанное количество раз.
Перечисленные конструкции были положены в основу структурного программирования. Программы, написанные с использованием только структурных операторов передачи управления, называют структурными, чтобы подчеркнуть их отличие от программ, разрабатываемых с использованием низкоуровневых способов передачи управления. Недостатки схем:
а) низкий уровень детализации, что скрывает суть сложных алгоритмов;
б) использование неструктурных способов передачи управления, которые на схеме выглядят проще, чем эквивалентные структурные.
Кроме схем, для описания алгоритмов можно использовать псевдокоды, Flow-формы и диаграммы Насси-Шнейдермана, которые базируются на тех же основных структурах, допускают разные уровни детализации и делают невозможным описание неструктурных алгоритмов [1].
Псевдокод - формализованное текстовое описание алгоритма (текстовая нотация в нескольких вариантах, таблица В.1). Изначально ориентирует проектировщика только на структурные способы передачи управления и требует более тщательного анализа разрабатываемого алгоритма. Псевдокоды не ограничивают степень детализации проектируемых операций, позволяют соизмерять степень детализации действия с рассматриваемым уровнем абстракции и хорошо согласуются с методом пошаговой детализации.
Flow-формы - графическая нотация описания структурных алгоритмов, иллюстрирующая вложенность структур. Каждому символу Flow-формы соответствует управляющая структура, изображаемая в виде прямоугольника и содержащая текст в математической нотации или на естественном языке. Для демонстрации вложенности структур символ Flow-формы вписывается в соответствующую область прямоугольника любого другого символа. Размер прямоугольника определяется длиной вписанного в него текста и размерами вложенных прямоугольников. В таблице В.1 приведены символы Flow-форм, соответствующие основным и дополнительным управляющим конструкциям.
Диаграммы Насси-Шнейдермана являются развитием Flow-форм лишь с той разницей, что область обозначения условий и вариантов ветвления изображают в виде треугольников (таблица В.1), обеспечивающих большую наглядность представления алгоритма.
Графические нотации лучше отображают вложенность конструкций, чем псевдокоды. Недостаток: сложность построения изображений символов усложняет их практическое применение для описания больших алгоритмов.
С точки зрения технологичности хорошим считают стиль оформления программы, облегчающий ее восприятие, как самим автором, так и другими программистами, которым придется ее проверять или модифицировать. Автор известной монографии, посвященной проблемам программирования, Д. Ван Тассел призывал: «Помните, программы читаются людьми» [7]. Исходя из того, что любую программу придется неоднократно просматривать, следует придерживаться хорошего стиля написания программ, который включает:
а) правила именования объектов программы;
б) правила оформления модулей;
в) стиль оформления текстов модулей.
Любая из ошибок программирования, которая не обнаруживается на этапах компиляции и компоновки программы, в итоге может проявиться тремя способами: привести к выдаче системного сообщения об ошибке, «зависанию» компьютера и получению неверных результатов. Однако до того, как результат работы программы становится фатальным, ошибки много раз проявляются в виде неверных типах данных, неверных промежуточных результатах, неверных управляющих переменных, индексах структур данных и т. п. (рисунок В.1). Часть ошибок можно обнаружить и нейтрализовать, пока они не привели к тяжелым последствиям. Программирование, при котором применяют специальные приемы раннего обнаружения и нейтрализации ошибок, названо защитным или программированием «с защитой от ошибок». Детальный анализ ошибок и их возможных ранних проявлений показывает, что целесообразно проверять правильность выполнения операций ввода-вывода, а также допустимость промежуточных результатов (значений управляющих переменных, индексов, типов данных, числовых аргументов).
Причинами неверного определения исходных данных могут являться, как внутренние ошибки (ошибки устройств ввода-вывода или программного обеспечения), так и внешние ошибки (ошибки пользователя). Различают:
а) ошибки передачи - аппаратные средства искажают данные;
б) ошибки преобразования - программа неверно преобразует исходные данные из входного формата во внутренний;
в) ошибки перезаписи - пользователь ошибается при вводе данных;
г) ошибки данных — пользователь вводит неверные данные.
Ошибки передачи обычно контролируются аппаратно.
Для защиты от ошибок преобразования данные после ввода сразу демонстрируют пользователю («эхо»), выполняя преобразование сначала во внутренний формат и обратно. Предотвратить все ошибки преобразования на этом этапе крайне сложно, поэтому фрагменты программы тестируют [15], используя методы эквивалентного разбиения и граничных значений.
Обнаружить и устранить ошибки перезаписи можно только при вводе избыточных данных, например, контрольных сумм. Если ввод избыточных данных нежелателен, то по возможности проверяют входные данные и контролируют интервалы возможных значений, определенных в техническом задании, а также выводят введенные данные для проверки пользователю.
Неверные данные обычно может обнаружить только пользователь.
Проверки промежуточных результатов позволяют снизить вероятность позднего проявления не только ошибок неверного определения данных, но и некоторых ошибок кодирования и проектирования. Для этого необходимо, чтобы в программе использовались переменные с ограничениями любого происхождения, например, связанные с сущностью моделируемых процессов.
Любые дополнительные операции в программе требуют использования дополнительных ресурсов (времени, памяти) и могут содержать ошибки. Имеет смысл проверять только те промежуточные результаты, проверка которых целесообразна и не сложна, например, допустимость индекса.
Для снижения погрешности результатов вычислений следует
а) избегать вычитания близких чисел (машинный ноль);
б) избегать деления больших чисел на малые;
в) сложение длинной последовательности чисел начинать с меньших по абсолютной величине;
г) стремиться по возможности уменьшать количество операций;
д) использовать методы с известными оценками погрешностей;
е) не использовать условие равенства вещественных чисел;
ж) вычислять с двойной точностью, а результат выдавать - с одинарной.
Поскольку полный контроль данных на входе и в процессе вычислений невозможен, следует предусматривать перехват и обработку аварийных ситуаций. Для перехвата и обработки аппаратно и программно фиксируемых ошибок в некоторых языках программирования (Delphi Pascal, C++ и Java) предусмотрены средства обработки исключений. Использование этих средств позволяет не допустить выдачи пользователю сообщения об аварийном завершении программы, а программист получает возможность предусмотреть действия, позволяющие исправить эту ошибку или выдать пользователю сообщение с точным описанием ситуации и продолжить работу.
Сквозной структурный контроль (ССК) – это совокупность технологических операций контроля на всех этапах разработки при наличии четких рекомендаций по их выполнению, позволяющих обеспечить как можно более раннее обнаружение ошибок в процессе разработки. ССК должен выполняться на специальных контрольных сессиях, в которых, помимо разработчиков, могут участвовать специально приглашенные эксперты. Время между сессиями определяет объем материала, который выносится на сессию. Материалы для очередной сессии должны выдаваться участникам заранее для обдумывания. Одна из первых сессий должна быть организована на этапе определения спецификаций для проверки полноты и точности спецификаций. На этапе проектирования вручную проверяют алгоритмы разрабатываемого ПО на конкретных наборах данных и сверяют полученные результаты с соответствующими спецификациями, чтобы убедиться в правильности понимания спецификаций и проанализировать достоинства и недостатки концептуальных решений, закладываемых в проект. На этапе реализации проверяют последовательность реализации модулей, набор тестов, а также тексты отдельных модулей. Для всех этапов следует иметь списки наиболее часто встречающихся ошибок, формируемые по литературным источникам и опыту предыдущих разработок. Такие списки позволяют сконцентрировать усилия на конкретных моментах, а не проверять все подряд. При этом все найденные ошибки фиксируют в специальном документе, но не исправляют. Помимо раннего обнаружения ошибок, ССК обеспечивает своевременную подготовку качественной документации по проекту.
Дополнительную информацию по теме можно получить в [1, 6, 7, 15].
7 Лекция № 7. Определение требований к программному обеспечению и исходных данных для его проектирования
Содержание лекции: классификация программных продуктов по функциональному признаку; основные эксплуатационные требования к ним; разработка технического задания.
Цель лекции: получить представление о классификации программных продуктов и эксплуатационных требованиях к ним; ознакомиться с процессом разработки технического задания.
Каждый программный продукт предназначен для выполнения определенных функций. По назначению все программные продукты можно разделить на три группы [4]: системные, прикладные и гибридные (рисунок Г.1).
К системным относят программные продукты, обеспечивающие функционирование вычислительных систем (операционные системы, оболочки, утилиты).
Прикладные программы и системы ориентированы на решение конкретных пользовательских задач. Среди их пользователей различают разработчиков программ и непрограммистов, использующих компьютерные системы для достижения своих целей.
Разработчики программ используют специальные инструментальные средства (компиляторы, компоновщики, отладчики), которые интегрируют в системы программирования и среды разработки. Современные среды программирования (Delphi, Visual C++) реализуют визуальную технологию разработки программных продуктов и предоставляют программистам огромные библиотеки компонентов. К этой же группе относят инструментальные комплексы создания баз данных (Access, FoxPro, Oracle), средства создания интеллектуальных систем (экспертных, обучающих, систем контроля знаний). Последнее достижение в этом направлении - CASE-средства разработки программного обеспечения (ERwin, BPwin, Paradigm Plus, Rational Rose и другие).
В соответствии с современными требованиями непрограммисты не должны быть профессионалами в проблемах создания программных продуктов и специфике их взаимодействия с операционной системой. Для них разрабатывают специальные программные продукты, ориентированные на определенную предметную область. Такие продукты условно разделяют на:
а) продукты общего назначения:
1)текстовые редакторы;
2)электронные таблицы;
3)графические редакторы;
4)информационные системы общего назначения;
5)программы-переводчики;
б) профессиональные среды:
1)системы автоматизации проектирования;
2)системы-тренажеры;
3)бухгалтерские системы;
4)издательские системы;
5)профессиональные графические системы;
6)экспертные системы;
в) обучающие системы;
г) развлекающие программы:
1)информационные системы с тестами развлекающего характера;
2)музыкальные программы;
3)игровые программы.
Гибридные системы – это большие, узкоспециализированные системы для управления технологическими процессами различных типов в режиме реального времени, сочетающие признаки системного и прикладного ПО. Для повышения надежности и снижения времени обработки в них включают программы, обеспечивающие выполнение функций операционных систем.
К каждому из перечисленных типов программного обеспечения при разработке обычно предъявляют еще и эксплуатационные требования, определяющие некоторые характеристики разрабатываемого программного продукта, которые проявятся в процессе его функционирования. К таким характеристикам относят:
а) правильность - функционирование в соответствии с техническим заданием;
б) универсальность - обеспечение правильной работы при любых допустимых данных и защиты от неправильных данных;
в) надежность (помехозащищенность) - обеспечение полной повторяемости результатов (правильности при наличии различного рода сбоев);
г) проверяемость - возможность проверки получаемых результатов;
д) точность - обеспечение погрешности результатов не выше заданной;
е) защищенность - обеспечение конфиденциальности информации;
ж) программная совместимость - возможность совместного функционирования с другим программным обеспечением;
з) аппаратная совместимость - возможность совместного функциони-рования с некоторым оборудованием (указывается минимально возможная конфигурация оборудования, на котором будет работать ПО);
и) эффективность - использование минимально возможного количества ресурсов технических средств (время ответа системы, объем оперативной и внешней памяти, количество обслуживаемых внешних устройств);
к) адаптируемость - возможность быстрой модификации с целью приспособления к изменяющимся условиям функционирования;
л) повторная входимость - возможность повторного выполнения без перезагрузки с диска;
м) реентерабельность - возможность «параллельного» использования несколькими процессами (все данные, изменяемые программой в процессе выполнения, должны быть выделены в специальный блок, копия которого создается для каждого процесса при вызове программы).
Сложность многих программных систем не позволяет сразу сформулировать четкие требования к ним. Обычно для перехода от идеи создания программного обеспечения к четкой формулировке требований, которые могут быть занесены в техническое задание, необходимо выполнить предпроектные исследования в области разработки. Их целью является преобразование общих нечетких знаний о предназначении будущего программного обеспечения в сравнительно точные требования к нему. Существуют два варианта неопределенности:
а) неизвестны методы решения формулируемой задачи - такого типа неопределенности обычно возникают при решении научно-технических задач, поэтому во время предпроектных исследований определяют возможность решения поставленной задачи и методы, позволяющие получить требуемый результат, что может потребовать соответствующих научных исследований как фундаментального, так и прикладного характера, разработки и исследования новых моделей объектов реального мира;
б) неизвестна структура автоматизируемых информационных процессов - обычно встречается при построении автоматизированных систем управления предприятиями, поэтому в этом случае определяют:
1)структуру и взаимосвязи информационных процессов;
2)распределение функций между человеком и системой, аппаратурой и программным обеспечением;
3)функции программного обеспечения, условия его функционирования, особенности аппаратных и пользовательских интерфейсов;
4)требования к программным и информационным компонентам, необходимые аппаратные ресурсы, требования к базам данных и физические характеристики программных компонент.
Результаты предпроектных исследований предметной области используются в процессе разработки технического задания. Техническое задание представляет собой документ, в котором сформулированы основные цели разработки, требования к программному продукту, определены сроки и этапы разработки и регламентирован процесс приемно-сдаточных испытаний. В разработке технического задания участвуют как представители заказчика, так и представители исполнителя. В основе этого документа лежат исходные требования заказчика, анализ передовых достижений техники, результаты выполнения научно-исследовательских работ, предпроектных исследований, научного прогнозирования и т. п. Основными факторами, определяющими характеристики разрабатываемого ПО являются:
а) исходные данные и требуемые результаты, определяющие функции программы или системы;
б) среда функционирования (программная и аппаратная) - задается или выбирается для обеспечения параметров, указанных в техническом задании;
в) возможное взаимодействие с другим программным обеспечением и/или специальными техническими средствами - задается или выбирается исходя из набора выполняемых функций.
Разработка технического задания - процесс трудоемкий, требующий определенных навыков, выполняется в следующей последовательности. Прежде всего, устанавливают набор выполняемых функций, а также перечень и характеристики исходных данных. Затем определяют перечень результатов, их характеристики и способы представления. Далее уточняют среду функционирования ПО: конкретную комплектацию и параметры технических средств, версию используемой операционной системы, версии и параметры другого установленного ПО, с которым предстоит взаимодействовать будущему программному продукту. В случаях, когда разрабатываемое ПО собирает и хранит некоторую информацию или включается в управление каким-либо техническим процессом, необходимо также четко регламентировать действия программы в случае сбоев оборудования и энергоснабжения.
На техническое задание существует стандарт ГОСТ 19.201-78 «Техническое задание. Требования к содержанию и оформлению». В соответствии с этим стандартом техническое задание должно содержать следующие разделы:
а) введение;
б) основания для разработки;
в) назначение разработки;
г) требования к программе или программному изделию;
д) требования к программной документации;
е) технико-экономические показатели;
ж) стадии и этапы разработки;
з) порядок контроля и приемки.
При необходимости допускается в техническое задание включать приложения, в которых при необходимости приводят перечень научно-исследовательских работ, обосновывающих разработку; схемы алгоритмов, таблицы, описания, обоснования, расчеты и другие документы, которые следует использовать при разработке. В зависимости от особенностей разрабатываемого продукта разрешается использовать подразделы, вводить новые разделы или объединять их. Если какие-либо требования, предусмотренные техническим заданием, заказчик не предъявляет, следует в соответствующем месте указать «Требования не предъявляются». Подробно содержание каждого раздела рассматривается в методических указаниях к лабораторным работам.
Дополнительную информацию по теме можно получить в [1, 4, 9, 18].
8 Лекция № 8. Принципиальные решения начальных этапов проектирования
Содержание лекции: архитектура программного обеспечения; типы пользовательских интерфейсов; технологии работы с документами; языки и среды программирования.
Цель лекции: ознакомиться с особенностями принятия принципиальных решений начальных этапов проектирования.
После утверждения технического задания организация-разработчик непосредственно приступает к созданию ПО. Однако переход к этапу уточнения спецификаций требует принятия некоторых принципиальных решений, от которых во многом зависят характеристики, возможности разрабатываемого ПО, особенности разработки. К таким решениям относят выбор архитектуры программного обеспечения, типа пользовательского интерфейса, технологии работы с документами, выбор подхода к разработке, а также выбор языка и среды программирования. Другими словами, эти решения определяют, что проектируется, с какими потребительскими характеристиками, как и какими средствами. Часть решений может быть определена в техническом задании, образовав группу технологических требований, остальные должны быть приняты как можно раньше, так как представляют собой исходные данные для процесса проектирования. Рассмотрим их более подробно.
Архитектура программного обеспечения – это совокупность базовых принципов его построения. Она определяется сложностью решаемых задач, степенью универсальности разрабатываемого программного обеспечения и числом пользователей, одновременно работающих с одной его копией. Различают однопользовательскую архитектуру, при которой программное обеспечение рассчитано на одного пользователя, и многопользовательскую архитектуру, которая рассчитана на работу в локальной или глобальной сети. В рамках однопользовательской архитектуры различают программы, пакеты программ, программные комплексы и системы. Многопользовательскую архитектуру реализуют системы, построенные по принципу «клиент-сервер».
Программой называют адресованный компьютеру набор инструкций, точно описывающий последовательность действий, которые необходимо выполнить для решения конкретной задачи. При структурном подходе программы представляют собой иерархию подпрограмм, вызывающих друг друга в процессе решения поставленной задачи, при объектном подходе - совокупность обменивающихся сообщениями объектов, для реализации которых разработаны специальные классы. Программа в этом случае представляет собой отдельно компилируемую программную единицу, которая может использовать стандартные библиотеки подпрограмм, но не организует свои. Это самый простой вид архитектуры, используется при решении небольших задач.
Пакеты программ представляют собой совокупность программ, решающих задачи некоторой прикладной области. Программы пакета связаны между собой только принадлежностью к определенной прикладной области. Пакет программ реализуют в виде набора отдельных программ (библиотеки), каждая из которых сама вводит необходимые данные и выводит результаты.
Программные комплексы - совокупность программ, обеспечивающих совместное решение небольшого класса сложных задач одной прикладной области. Для решения может потребоваться решить несколько подзадач, последовательно вызывая программы комплекса с помощью специальной программы - диспетчера, который обеспечивает интерфейс с пользователем и выдачу некоторой справочной информации. Несколько программ комплекса могут последовательно или циклически вызываться для решения одной задачи, поэтому желательно хранить исходные данные и результаты вызовов в пределах одного пользовательского проекта. Программы в этом случае могут реализовываться как отдельно или совместно компилируемые программные единицы, а исходные данные храниться в оперативной памяти или в файлах.
Программные системы - организованная совокупность программ (подсистем), позволяющая решать широкий класс задач из некоторой прикладной области. Программы, входящие в программную систему, взаимодействуют через общие данные. Программные системы обычно имеют развитые пользовательский и внутренние интерфейсы, что требует их тщательного проектирования. Многопользовательские программные системы должны организовывать сетевое взаимодействие отдельных компонентов ПО, что усложняет процесс его разработки, поэтому для разработки используют специальные технологии или платформы (технологии CORBA, COM, Java).
Тип пользовательского интерфейса во многом определяет сложность и трудоемкость разработки. По последним данным до 80 % программного кода может реализовывать именно пользовательский интерфейс [14]. Различают четыре типа пользовательских интерфейсов:
а) примитивные - реализуют единственный сценарий работы, используя операции ввода данных, их обработки и вывода результатов;
б) меню - реализуют множество сценариев работы, операции которых организованы в иерархические структуры;
в) со свободной навигацией - реализуют множество сценариев, операции которых не привязаны к уровням иерархии, и предполагают определение множества возможных операций на конкретном шаге работы; интерфейсы данной формы в основном используют Windows-приложения;
г) прямого манипулирования - реализуют множество сценариев, представленных в операциях над объектами, инициируемых перемещением пиктограмм объектов мышью; данная форма реализована в интерфейсе операционной системы Windows.
Появление объектно-ориентированных визуальных сред разработки программного обеспечения, использующих событийный подход к программированию и в основном рассчитанных на создание интерфейсов со свободной навигацией, существенно снизило трудоемкость разработки подобных интерфейсов и упростило реализацию интерфейсов прямого манипулирования. Выбор типа интерфейса включает выбор технологии работы с документами. Различают две технологии:
а) однодокументная, которая предполагает однодокументный интерфейс (SDI - Single Document Interface) и используется, если одновременная работа с несколькими документами не обязательна;
б) многодокументная, которая предполагает многодокументный интерфейс (MDI - Multiple Document Interface) и используется, если программное обеспечение должно работать с несколькими документами одновременно, например, с несколькими текстами или несколькими изображениями.
Трудоемкость реализации многодокументных интерфейсов с использованием современных библиотек примерно на 3...5 % выше, чем однодокументных, однако тип влияет на трудоемкость более существенно.
При выборе интерфейса прямого манипулирования или со свободной навигацией практически однозначно предполагается использование объектного подхода и событийного программирования, так как современные среды визуального программирования, такие как Visual C++, Delphi, Builder C++, предоставляют интерфейсные компоненты именно в виде объектов библиотечных классов. При этом в зависимости от сложности предметной области программное обеспечение может реализовываться как с использованием объектов и, соответственно, классов, так и чисто процедурно. Исключение составляют случаи использования специализированных языков разработки Интернет-приложений (Perl), построенных по совершенно другому принципу. Примитивный интерфейс и интерфейс типа меню совместимы как со структурным, так и с объектным подходами к разработке. Поэтому выбор подхода осуществляют с использованием дополнительной информации.
Практика показывает, что объектный подход эффективен для разработки очень больших программных систем (более 100000 операторов) и в случаях, когда объектная структура предметной области ярко выражена. Следует осторожно использовать объектный подход при жестких ограничениях на эффективность разрабатываемого ПО (при разработке систем реального времени). Во всех прочих случаях выбор подхода остается за разработчиком.
В большинстве случаев проблемы выбора языка программирования реально не существует. Язык может быть определен организацией, ведущей разработку; программистом, который по возможности всегда будет использовать хорошо знакомый язык, или устоявшимся мнением. Все существующие языки программирования модно разделить на четыре группы, которые позже будут рассмотрены более подробно [2].
Среда программирования - программный комплекс, включающий текстовый редактор, встроенные компилятор, компоновщик, отладчик, справочную систему и другие программы, использование которых упрощает процесс написания и отладки программ. Последнее время широкое распространение получили среды визуального программирования, позволяющие визуально подключать к программе коды из специальных библиотек компонентов. Наиболее часто используют визуальные среды Delphi, C++ Builder фирмы Borland (Inprise Corporation), Visual C++, Visual Basic фирмы Microsoft, Visual Ada фирмы IBM. Причем, среды фирмы Microsoft обеспечивают более низкий уровень программирования «под Windows». Это является их достоинством (уменьшается вероятность возникновения «нестандартной» ситуации) и недостатком (существенно загружает программиста «рутинной» работой, от которой избавлен программист, работающий с Delphi или C++ Builder). В общем случае, выбор среды в значительной степени должен определяться характером проекта.
Реальное применение любой технологии проектирования требует формирования или выбора ряда стандартов, которые должны соблюдаться всеми участниками проекта:
а) стандарт проектирования;
б) стандарт оформления проектной документации;
в) стандарт интерфейса пользователя.
Стандарт проектирования должен определять набор необходимых моделей (схем, диаграмм) на каждой стадии проектирования и степень их детализации, правила фиксации проектных решений на диаграммах (включая правила именования объектов и соглашения по терминологии, набор атрибутов для всех объектов и правила их заполнения на каждой стадии, правила оформления диаграмм, включая требования к форме и размерам объектов), требования к конфигурации рабочих мест разработчиков (включая настройки операционной системы и используемых CASE-средств), механизм обеспечения совместной работы над проектом (включая и правила интеграции подсистем проекта и анализа проектных решений на непротиворечивость).
Стандарт оформления проектной документации регламентирует: комплектность, состав и структуру документации на каждой стадии; требования к ее содержанию и оформлению; правила подготовки, рассмотрения, согласования и утверждения документов.
Стандарт интерфейса пользователя определяет: правила оформления экранов (шрифты и цветовую палитру), состав и расположение окон и элементов управления; правила пользования клавиатурой и мышью; правила оформления текстов помощи; перечень стандартных сообщений; правила обработки реакции пользователя.
Описанные проектные решения существенно влияют на трудоемкость и сложность разработки. Только после их принятия переходят к анализу требований и разработке спецификаций проектируемого ПО.
Дополнительную информацию по теме можно получить в [1, 2, 4, 14].
9 Лекция № 9. Алгоритмические языки и предъявляемые к ним требования
Содержание лекции: алгоритмические языки и предъявляемые к ним требования.
Цель лекции: ознакомиться с классификацией и особенностями современных языков программирования.
Одной из проблем, возникающих на начальных этапах разработки программного продукта, является выбор языка программирования, который в свою очередь влияет на выбор среды программирования. Существует масса факторов, влияющих на выбор языка. Однако прежде чем принять решение в пользу того или иного языка программирования, следует иметь представление об их классификации и особенностях. Все существующие языки программирования разделяются на следующие группы [1]:
а) универсальные языки высокого уровня;
б) специализированные языки разработчика программного обеспечения;
в) специализированные языки пользователя;
г) языки низкого уровня.
В группе универсальных языков высокого уровня безусловным лидером сегодня является язык С (вместе с C++). Действительно различные версии С и C++ имеют целый ряд очень существенных достоинств [17]:
а) многоплатформенность - для всех используемых в настоящее время платформ существуют компиляторы с языка С и C++;
б) наличие операторов, реализующих основные структурные алгоритмические конструкции (условную обработку, все виды циклов);
в) возможность программирования на низком (системном) уровне с использованием адресов оперативной памяти;
г) огромные библиотеки подпрограмм и классов.
Все это сделало С и C++ основными языками, используемыми для создания операционных систем, и, в свою очередь, служит для них дополнительной рекламой. Однако они имеют и серьезные недостатки:
а) отсутствие полноценных встроенных структурных типов данных (имеющиеся псевдоструктурные типы, использующие адресную арифметику, недостаточно жестко определены, чтобы контролировать многие операции над этими данными, что приводит к большому количеству ошибок, выявляемых только в процессе отладки программы);
б) наличие синтаксических неоднозначностей, которые также не позволяют компилятору контролировать правильность программы;
в) ограниченный контроль параметров, передаваемых в подпрограмму, что также обнаруживается только в процессе отладки программы.
Альтернативой С и C++ среди универсальных языков программирования, используемых для создания прикладного программного обеспечения, на сегодня является Pascal, компиляторы которого в силу четкого синтаксиса обнаруживают помимо синтаксических и большое количество семантических ошибок. Версия Object Pascal, использованная в среде Delphi, сопровождается профессиональными библиотеками классов, упрощающими ведение больших разработок, в том числе и требующих использования баз данных, что делает Delphi достаточно эффективной средой для создания приложений Windows. Кроме этих языков к группе универсальных принадлежат также Basic, Modula, Ada и некоторые другие. Каждый из указанных языков, так же, как C++ и Pascal, имеет свои особенности и, соответственно, свою область применения.
Специализированные языки разработчика используют для создания конкретных типов программного обеспечения. К ним относят:
а) языки баз данных;
б) языки создания сетевых приложений;
в) языки создания систем искусственного интеллекта и т. д.
Специализированные языки пользователя обычно являются частью профессиональных сред, характеризуются узкой направленностью и разработчиками программного обеспечения не используются.
Языки низкого уровня позволяют осуществлять программирование практически на уровне машинных команд. При этом получают самые оптимальные, как с точки зрения времени выполнения, так и с точки зрения объема необходимой памяти программы. Но эти языки совершенно не годятся для создания больших программ и, тем более, программных систем. Основная причина - низкий уровень абстракций, которыми должен оперировать разработчик, откуда недопустимо большое время разработки. Существенно и то, что сами языки низкого уровня не поддерживают принципов структурного программирования, что значительно ухудшает технологичность разрабатываемых программ. В настоящее время языки типа Ассемблера обычно используют:
а) при написании сравнительно простых программ, взаимодействующих непосредственно с техническими средствами (например, драйверов), поскольку в этом случае приходится кропотливо настраивать соответствующее оборудование, преимущества языков программирования высокого уровня становятся несущественными;
б) в виде вставок в программы на языках высокого уровня (например, для ускорения преобразования данных в циклах с большим количеством повторений).
Таким образом, при выборе языка программирования следует руководствоваться следующими соображениями:
а) язык должен быть удобен для программиста;
б) язык должен быть пригоден для данного компьютера;
в) язык должен быть пригоден для решения данной задачи.
Дополнительную информацию по теме можно получить в [1, 2, 3, 7, 17].
10 Лекция № 10. Структурный подход. Анализ требований, определение спецификаций
Содержание лекции: спецификации программного обеспечения; структуры данных; математические модели задач, разработка и выбор методов решения;
Цель лекции: ознакомиться с особенностями структурного подхода к определению спецификаций, структур данных, моделей и методов решения задач.
Собственно разработка любого программного обеспечения начинается с анализа требований к будущему программному продукту. В результате анализа получают спецификации разрабатываемого ПО: выполняют декомпозицию и содержательную постановку решаемых задач, уточняют их взаимодействие и эксплуатационные ограничения. В целом в процессе определения спецификаций строят общую модель предметной области, как некоторой части реального мира, с которой будет тем или иным способом взаимодействовать разрабатываемое программное обеспечение, и конкретизируют его основные функции.
Спецификации - полное и точное описание функций и ограничений разрабатываемого программного обеспечения. Функциональные спецификации описывают функции разрабатываемого программного продукта, а эксплуатационные - определяют требования к техническим средствам, надежности, информационной безопасности и т. д.
Естественный язык для описания спецификаций не подходит, поскольку не обеспечивает необходимой точности. Точные спецификации можно определить лишь разработав некоторую формальную модель ПО. Формальные модели можно разделить на две группы: модели, зависящие от подхода к разработке, и модели, не зависящие от него. Диаграммы переходов состояний, которые демонстрируют особенности поведения разрабатываемого ПО при получении тех или иных сигналов извне, и математические модели предметной области, позволяющие уточнить основные соотношения анализируемых величин и накладываемые на них ограничения, используются при любом подходе к разработке.
В рамках структурного подхода на этапе анализа и определения спецификаций используют три типа моделей: ориентированные на функции, ориентированные на данные и ориентированные на потоки данных, каждая из которых пригодна для своего класса программных разработок. Поскольку разные модели описывают проектируемое ПО с разных сторон, рекомендуется использовать сразу несколько моделей и сопровождать их текстами (словарями, описаниями), которые поясняют соответствующие диаграммы.
Спецификации процессов обычно представляют в виде краткого текстового описания, схем алгоритмов, псевдокодов, Flow-форм или диаграмм Насси-Шнейдермана. Для краткости и понятности описания не только разработчику, но и заказчику, чаще всего используют псевдокоды.
Словарь терминов – краткое описание основных понятий, используемых при составлении спецификаций, который включает определение основных понятий предметной области, описание структур элементов данных, их типов и форматов, а также всех сокращений и условных обозначений. Предназначен для повышения степени понимания предметной области и исключения риска возникновения разногласий при обсуждении моделей между заказчиками и разработчиками. Описание термина в словаре выполняется по схеме [1]:
«термин – категория– краткое описание».
Диаграмма переходов состояний демонстрирует поведение разрабатываемой программной системы при получении управляющих воздействий (управляющей информации, поступающей извне). Для ее построения в соответствии с теорией конечных автоматов необходимо определить: основные состояния, управляющие воздействия (или условия перехода), выполняемые действия и возможные варианты переходов из одного состояния в другое.
Если программная система в процессе функционирования активно не взаимодействует с окружающей средой (пользователем или датчиками), например, использует примитивный интерфейс и выполняет некоторые вычисления по заданным исходным данным, то диаграмма переходов состояний обычно интереса не представляет, поскольку она демонстрирует только последовательно выполняемые переходы (рисунок Г.2а): из исходного состояния в состояние ввода данных, после выполнения вычислений - в состояние вывода и, наконец, в состояние завершения работы. Для интерактивного ПО с развитым пользовательским интерфейсом характерно получение команд различных типов (рисунок Г.2б), а для ПО реального времени - однотипных сигналов (либо от многих датчиков, либо требующих продолжительной обработки). Общим для них является наличие состояния ожидания, когда ПО приостанавливает работу до получения очередного управляющего воздействия. В отличие от интерактивных систем для систем реального времени обычно установлено более жесткое ограничение на время обработки полученного сигнала ПО. Такое ограничение часто требует выполнения дополнительных исследований поведения системы во времени. К ПО, требующему уточнения особенностей поведения посредством построения диаграммы переходов состояний, относится и ПО, ориентированное на работу в сети. При этом отдельно строят модели поведения сервера и клиента, представляя сообщения, передаваемые между ними, в виде управляющих воздействий. Полученную диаграмму переходов состояний обязательно согласовывают с заказчиком.
Функциональными называют диаграммы, отражающие взаимосвязи функций разрабатываемого программного обеспечения. Отображение взаимосвязи функций осуществляется посредством построения иерархии функциональных диаграмм, схематически представляющих взаимосвязи нескольких функций. Каждый блок такой диаграммы соответствует некоторой функции, для которой должны быть определены: исходные данные, результаты, управляющая информация и механизмы ее осуществления - человек или технические средства. Все перечисленные выше связи функции представляются дугами, причем тип связи и ее направление строго регламентированы. Дуги, изображающие каждый тип связей, должны подходить к блоку с определенной стороны (рисунок 10.1), а направление связи должно указываться стрелкой в конце дуги.
Рисунок 10.1 – Функциональный блок и интерфейсные дуги
Физически дуги исходных данных, результатов и управления представляют собой наборы данных, передаваемые между функциями. Дуги, определяющие механизм выполнения функции, используются при описании сложных информационных систем. Блоки и дуги маркируются текстами на естественном языке. Блоки на диаграмме размещают по «ступенчатой» схеме в соответствии с последовательностью их работы или доминированием, которое понимается как влияние, оказываемое одним блоком на другие. Дуги могут разветвляться и соединяться различными способами. Разветвление означает, что часть или вся информация может использоваться в каждом ответвлении дуги. В процессе построения иерархии диаграмм фиксируют всю уточняющую информацию и строят словарь данных, в котором определяют структуры и элементы данных, показанных на диаграммах. В результате получают спецификацию, которая состоит из иерархии функциональных диаграмм, спецификаций функций нижнего уровня и словаря, имеющих ссылки друг на друга. Функциональную модель целесообразно применять для определения спецификаций ПО, не предусматривающего работу со сложными структурами данных, так как она ориентирована на декомпозицию функций.
Диаграммы потоков данных позволяют специфицировать как функции разрабатываемого ПО, так и обрабатываемые им данные. При использовании этой модели систему представляют в виде иерархии диаграмм потоков данных, описывающих асинхронный процесс преобразования информации с момента ввода в систему до выдачи пользователю. На каждом следующем уровне иерархии происходит уточнение процессов, пока очередной процесс не будет признан элементарным. В основе модели лежат понятия внешней сущности, процесса, хранилища (накопителя) данных и потока данных.
Структура данных - совокупность правил и ограничений, которые отражают связи, существующие между отдельными элементами данных.
Различают абстрактные структуры данных, используемые для уточнения связей между элементами, и конкретные структуры, используемые для представления данных в программах. Все абстрактные структуры данных можно разделить на три группы: структуры, элементы которых не связаны между собой, таблицы (структуры с неявными связями элементов) и графы (структуры, связь элементов которых указывается явно). В первую группу входят множества и кортежи. Наиболее существенная характеристика элемента данных в этих структурах - отношение вхождения (его принадлежность некоторому набору). Ко второй группе относят векторы, матрицы, массивы (многомерные), записи, строки, а также таблицы, включающие перечисленные структуры в качестве частей. В тех случаях, когда существенны связи элементов данных между собой, в качестве модели структур данных используют графы. В зависимости от описываемых типов отношений модели структур данных принято делить на иерархические и сетевые.
Для задач, алгоритм решения которых не очевиден, используют разного рода математические модели. Процесс построения такой модели включает:
а) анализ условия задачи;
б) выбор математических абстракций, адекватно, т. е. с требуемой точностью и полнотой представляющих исходные данные и результаты;
в) формальную постановку задачи;
г) определение метода преобразования исходных данных в результат (метода решения задачи).
Для многих задач, которые часто встречаются на практике, в математике определены как модели, так и методы решения. В ряде случаев формальная постановка задачи однозначно определяет метод ее решения, но, как правило, методов решения существует несколько, и тогда для выбора метода решения может потребоваться специальное исследование. При выборе метода учитывают: особенности данных конкретной задачи, связанные с предметной областью (погрешность, возможные особые случаи и т. п.); требования к результатам (допустимую погрешность); характеристики метода (точный или приближенный, погрешности результатов, вычислительную и емкостную сложности, сложность реализации).
Определив методы решения, целесообразно для некоторых вариантов исходных данных вручную подсчитать ожидаемые результаты. Эти данные будут использованы при тестировании ПО. Выполнение операций вручную позволяет точно уяснить последовательность действий, что упростит разработку алгоритмов. Имеет смысл продумать, для каких сочетаний исходных данных результат не существует или не может быть получен данным методом, что тоже необходимо учесть при разработке ПО.
Дополнительную информацию по теме можно получить в [1, 4, 6, 8, 11].
11 Лекция № 11. Структурный подход. Проектирование программного обеспечения
Содержание лекции: разработка структурной и функциональной схем; проектирование структур данных.
Цель лекции: ознакомиться с проектированием ПО при структурном подходе.
Процесс проектирования сложного программного обеспечения начинают с уточнения его структуры, т. е. определения структурных компонентов и связей между ними. Результат уточнения структуры может быть представлен в виде структурной и/или функциональной схем и описания (спецификаций) компонентов.
Структурной называют схему, отражающую состав и взаимодействие по управлению частей разрабатываемого ПО. Структурные схемы пакетов программ не информативны, поскольку организация программ в пакеты не предусматривает передачи управления между ними. Поэтому структурные схемы разрабатывают для каждой программы пакета, а список программ пакета определяют, анализируя функции, указанные в техническом задании.
Разработку структурной схемы самого простого вида ПО - программы, включающей в качестве структурных компонентов только подпрограммы и библиотеки ресурсов, выполняют методом пошаговой детализации. Структурными компонентами программной системы (комплекса) служат программы, библиотеки ресурсов, подсистемы, базы данных. Структурная схема программного комплекса демонстрирует передачу управления от программы-диспетчера соответствующей программе (рисунок 11.1а).
Рисунок 11.1 - Пример схем программного комплекса: а) структурной;
б) функциональной
Структурная схема программной системы показывает наличие подсистем или других структурных компонентов. В отличие от программного комплекса отдельные части (подсистемы) программной системы интенсивно обмениваются данными между собой и с основной программой. Структурная схема программной системы этого не показывает (рисунок 11.2а).
Рисунок 11.2 – Пример схем программной системы: а) структурной;
б) функциональной
Более полное представление о проектируемом ПО с точки зрения взаимодействия его компонентов между собой и с внешней средой дает функциональная схема. Функциональная схема (схема данных, ГОСТ 19.701-90) - схема взаимодействия компонентов ПО с описанием информационных потоков, состава данных в потоках и указанием используемых файлов и устройств. Для изображения функциональных схем используют специальные обозначения, установленные стандартом. Основные обозначения схем данных приведены в таблице Г.1. Функциональные схемы более информативны, чем структурные. На рисунках 11.1б и 11.2б приведены функциональные схемы программных комплексов и систем. Все компоненты структурных и функциональных схем должны быть описаны. Следует тщательно прорабатывать спецификации межпрограммных интерфейсов, так как от качества их описания зависит количество самых дорогостоящих ошибок, к которым относятся ошибки, обнаруживаемые при комплексном тестировании.
Структурный подход к программированию изначально предлагал осуществлять декомпозицию программ методом пошаговой детализации. Результат - структурная схема программы, т.е. многоуровневая иерархическая схема взаимодействия подпрограмм по управлению. Минимально такая схема отображает два уровня иерархии (показывает общую структуру программы). Тот же метод позволяет получить структурные схемы с большим количеством уровней. Разбиение на модули выполняется эвристически, исходя из рекомендуемых размеров модулей (20-60 строк) и сложности структуры (2-3 вложенных управляющих конструкции). Для анализа технологичности иерархии модулей используют методики Константайна или Джексона [4].
На структурной карте Константайна отношения между модулями представляют в виде графа, вершинам которого соответствуют модули и общие области данных, а дугам - межмодульные вызовы и обращения к общим областям данных. Различают четыре типа вершин: модуль – подпрограмма; подсистема – программа; библиотека - совокупность подпрограмм, размещенных в отдельном модуле; область данных - специальным образом оформленная совокупность данных, к которой возможно обращение извне. При этом отдельные части программной системы могут вызываться последовательно, параллельно или как сопрограммы.
Практически одновременно появились методики проектирования ПО Джексона и Варнье-Орра, также основанные на декомпозиции данных. Обе методики предназначены для создания «простых» программ, работающих со сложными, но иерархически организованными структурами данных. При разработке программных систем предлагается вначале разбить систему на отдельные программы, а затем использовать эти методики. Они могут использоваться только в том случае, если данные разрабатываемых программ могут быть представлены в виде иерархии или совокупности иерархий.
Методика Джексона основана на поиске соответствий структур исходных данных и результатов. Однако при ее применении возможны ситуации, когда на каких-то уровнях соответствия отсутствуют. Например, записи исходного файла сортированы не в том порядке, в котором соответствующие строки должны появляться в отчете. Такие ситуации были названы «столкновениями».
Методика Варнье-Орра базируется на том же положении, что и методика Джексона, но основными при построении программы считаются структуры выходных данных и, если структуры входных данных не соответствуют структурам выходных, то их допускается менять. Таким образом, ликвидируется основная причина столкновений. Однако на практике не всегда существует возможность пересмотра структур входных данных: эти структуры уже могут быть строго заданы, например, если данные получены при выполнении других программ, поэтому эту методику применяют реже.
Под проектированием структур данных понимают разработку их представлений в памяти [6]. Основными параметрами, которые необходимо учитывать при проектировании структур данных, являются:
а) вид хранимой информации каждого элемента данных - определяет тип соответствующего поля памяти;
б) связи элементов данных и вложенных структур, а также совокупность операций над ними - определяют структуры памяти, используемые для представления данных;
в) время хранения данных структуры («время жизни») - учитывается при размещении данных в статической или динамической памяти, а также во внешней памяти.
Различают две базовые структуры организации данных в оперативной памяти: векторную и списковую. Векторная структура - последовательность байт памяти, которые используются для размещения полей данных. Последовательное размещение организованных структур данных позволяет осуществлять прямой доступ к элементам: по индексу (в массивах или строках) или по имени поля (в записях или объектах). Однако выполнение операций добавления и удаления элементов для размещения элементов массивов требует осуществления многократных сдвигов элементов. Расположение векторных представлений в динамической памяти позволяет существенно увеличить эффективность использования оперативной памяти. Списковые структуры строят из специальных элементов, включающих помимо информационной части один или несколько указателей - адресов элементов или вложенных структур, связанных с этим элементом. Размещая их в динамической памяти, организуют различные внутренние структуры. Обычно векторное представление используют для хранения статических множеств, таблиц (одномерных и многомерных: матриц, строк, записей), а также графов, представленных матрицей смежности, матрицей инцидентности или аналитически [10]. Списковое представление удобно для хранения динамических (изменяемых) структур и структур со сложными связями.
Современные операционные системы поддерживают два способа организации данных во внешней памяти: последовательный и с прямым доступом. При последовательном доступе к данным возможно выполнение только последовательного чтения элементов данных или последовательная их запись (работа с клавиатурой или дисплеем, обработка текстовых файлов или файлов, формат записей которых меняется в процессе работы). Прямой доступ возможен только для дисковых файлов, обмен информацией с которыми осуществляется записями фиксированной длины (двоичные файлы С или типизированные файлы Pascal). Адрес записи такого файла можно определить по ее номеру, что и позволяет напрямую обращаться к нужной записи. В оперативной памяти размещают данные, к которым необходим быстрый доступ как для чтения, так и для их изменения; во внешней - данные, которые должны сохраняться после завершения программы.
Возможно, что во время работы данные целесообразно хранить в оперативной памяти для ускорения доступа к ним, а при ее завершении - переписывать во внешнюю память для длительного хранения. Именно этот способ используют большинство текстовых редакторов: во время работы с текстом он весь или его часть размещается в оперативной памяти, откуда по мере надобности переписывается во внешнюю память. В подобных случаях разрабатывают два представления данных: в оперативной и во внешней памяти.
Правильный выбор структур во многом определяет эффективность разрабатываемого ПО и его технологические качества, поэтому при проектировании этому вопросу следует уделять достаточно внимания.
Дополнительную информацию по теме можно получить в [1, 4, 6, 8, 10].
12 Лекция № 12. Объектный подход. Проектирование программного обеспечения
Содержание лекции: объектно-ориентированное программирование; объекты, создание и их использование; язык описания разработки UML.
Цель лекции: ознакомиться с основными понятиями объектного программирования, особенностями создания программного продукта при объектном подходе.
Как показала практика, традиционные методы процедурного программирования не способны справиться ни с нарастающей сложностью программ и их разработки, ни с необходимостью повышения их надежности. В середине 80-х годов ХХ века для разработки ПО большого объема было предложено использовать объектный подход, а в качестве технологии выбрано объектно-ориентированное программирование (ООП) - методика разработки программ, в основе которой лежит понятие объекта.
Объект - это некоторая структура, соответствующая объекту реального мира, его поведению. Каждый объект имеет состояние, обладает четко определенным поведением и уникальной идентичностью. Совокупность атрибутов (свойств) и их значений характеризует объект. Объекты, описываемые одинаковыми наборами атрибутов, объединяются в классы. Данные класса называются полями, процедуры и функции — методами. Все экземпляры одного класса (объекты, порожденные от одного класса) имеют один и тот же набор свойств и общее поведение, то есть одинаково реагируют на одинаковые сообщения. Каждый объект имеет определенное время жизни. В процессе выполнения программы или функционирования реальной системы, могут создаваться новые объекты и уничтожаться уже существующие. Поскольку объект - это динамическая структура, переменная-объект содержит не данные, а ссылку на данные объекта. Поэтому программист должен позаботиться о выделении памяти для этих данных. Выделение памяти при создании объекта осуществляется при помощи специального метода класса – конструктора (constructor), а освобождение памяти при его уничтожении - при помощи деструктора (destructor).
Важнейшими понятиями ООП являются инкапсуляция, наследование, полиморфизм, которые позволяют конструировать сложные объекты из сравнительно простых. Программа, написанная с использованием ООП, состоит из множества объектов, взаимодействующих между собой путем передачи сообщений.
В основе объектного подхода к разработке ПО лежит объектная декомпозиция, т. е. представление разрабатываемого программного продукта в виде совокупности объектов, в процессе взаимодействия которых через передачу сообщений и происходит выполнение требуемых функций. Объектно-ориентированный подход имеет следующие преимущества:
а) уменьшение сложности программного обеспечения;
б) повышение надежности программного обеспечения;
в) обеспечение возможности модификации отдельных компонентов программного обеспечения без изменения остальных его компонентов;
г) обеспечение возможности повторного использования отдельных компонентов программного обеспечения.
Систематическое применение объектного подхода позволяет разрабатывать хорошо структурированные, надежные в эксплуатации, достаточно просто модифицируемые программные системы, поэтому ООП является одним из наиболее интенсивно развивающихся направлений теоретического и прикладного программирования. Однако при объектном подходе сразу можно выполнить декомпозицию только очень простого ПО. На заре эпохи ООП были предложены методы анализа и проектирования в рамках объектного подхода, использующие различные модели и нотации.
Спорить о достоинствах и недостатках этих методов и моделей можно было бесконечно. Эта ситуация получила название «войны методов». Конец «войне методов» положило появление в 1995 г. первой версии языка UML (Unified Modeling Language - унифицированный язык моделирования), который был создан ведущими специалистами в этой области (Гради Бучем, Иваром Якобсоном и Джеймсом Рамбо) и в настоящее время фактически признан стандартным средством описания проектов, создаваемых с использованием объектно-ориентированного подхода [11].
Спецификация разрабатываемого программного обеспечения при использовании UML объединяет несколько моделей [12]: использования, логическую, реализации, процессов и развертывания (рисунок 12.1).
Рисунок 12.1 - Полная спецификация разрабатываемого программного обеспечения при объектном подходе (UML)
Логическая модель описывает ключевые абстракции ПО (классы, интерфейсы), т. е. средства, обеспечивающие требуемую функциональность. Модель реализации определяет реальную организацию программных модулей в среде разработки. Модель использования представляет собой описание функциональности программного продукта с точки зрения пользователя. Модель процессов отображает организацию вычислений и оперирует понятиями «процессы» и «нити». Она позволяет оценить производительность, масштабируемость и надежность программного обеспечения. И, наконец, модель развертывания показывает особенности размещения программных компонентов на конкретном оборудовании.
Каждая из указанных моделей характеризует определенный аспект проектируемой системы, а все вместе они составляют относительно полную модель разрабатываемого программного продукта. Всего UML предлагает девять дополняющих друг друга диаграмм, входящих в различные модели:
а) диаграммы вариантов использования (показывают основные функции системы для каждого типа пользователей);
б) диаграммы классов (контекстные, описания интерфейсов и реализации - демонстрируют отношения классов между собой);
в) диаграммы пакетов (демонстрируют связи наборов классов, объединенных в пакеты, между собой);
г) диаграммы последовательностей действий (отображают упорядоченное по времени взаимодействие объектов в процессе выполнения варианта использования);
д) диаграммы кооперации (предоставляют ту же информацию, что и диаграммы последовательности действий, но в форме, позволяющей лучше представить ответственности классов в целом);
е) диаграммы деятельностей (представляют собой схему потоков управления для решения некоторой задачи по отдельным действиям, допускают наличие параллельных и/или альтернативных действий);
ж) диаграммы состояний объектов (показывают состояния объекта и условия переходов из одного состояния в другое);
з) диаграммы компонентов (показывают из каких программных компонентов состоит программное обеспечение и как эти компоненты связаны между собой);
и) диаграммы размещения (позволяют связать программные и аппаратные компоненты системы).
Дополнениями к диаграммам служат формализованные и неформализованные текстовые описания, комментарии и словари. При построении этих и других диаграмм используют унифицированную систему обозначений. UML и предлагаемая теми же авторами методика Rational Unified Process поддерживаются пакетом Rational Rose фирмы Rational Software Corporation. Ряд диаграмм UML можно построить также средствами программы Microsoft Visual Modeler и других CASE-средств.
Дополнительную информацию по теме можно получить в [1, 11, 12, 13].
13 Лекция № 13. Пользовательские интерфейсы
Содержание лекции: типы пользовательских интерфейсов и этапы их разработки.
Цель лекции: ознакомиться с типами пользовательских интерфейсов и основными принципами их разработки.
На ранних этапах развития вычислительной техники пользовательский интерфейс рассматривался как средство общения человека с операционной системой и был достаточно примитивным (позволял запустить задание на выполнение, связать с ним конкретные данные и выполнить некоторые процедуры обслуживания вычислительной установки). Со временем появилась возможность создания интерактивного ПО, использующего специальные пользовательские интерфейсы. В настоящее время основной проблемой является разработка интерактивных интерфейсов к сложным программным продуктам для непрофессиональных пользователей, поэтому были сформулированы основные концепции их построения и предложено несколько методик создания.
Пользовательский интерфейс представляет собой совокупность программных и аппаратных средств, обеспечивающих взаимодействие пользователя с компьютером. Основу такого взаимодействия составляют диалоги. Под диалогом понимают регламентированный обмен информацией между человеком и компьютером, осуществляемый в реальном масштабе времени и направленный на совместное решение конкретной задачи: обмен информацией и координация действий. Каждый диалог состоит из отдельных процессов ввода-вывода, которые физически обеспечивают связь пользователя и компьютера. Обмен информацией осуществляется передачей сообщений и управляющих сигналов. Сообщение - порция информации, участвующая в диалоговом обмене. Различают:
а) входные сообщения, которые генерируются человеком с помощью средств ввода: клавиатуры, манипуляторов, например мыши;
б) выходные сообщения, которые генерируются компьютером в виде текстов, звуковых сигналов и/или изображений и выводятся пользователю на экран монитора или другие устройства вывода информации (рисунок 13.1).
В основном пользователь генерирует сообщения следующих типов: запрос информации, запрос помощи, запрос операции или функции, ввод или изменение информации, выбор поля кадра и т. д. В ответ он получает: подсказки или справки, информационные сообщения, не требующие ответа, приказы, требующие действий, сообщения об ошибках, нуждающиеся в ответных действиях, изменение формата кадра и т. д.
Рисунок 13.1 - Организация взаимодействия компьютера и пользователя
Основные устройства, обеспечивающие выполнение операций ввода-вывода:
а) для вывода сообщений:
1) монохромные и цветные мониторы - вывод оперативной текстовой и графической информации;
2) принтеры - получение «твердой копии» текстовой и графической информации;
3) графопостроители - получение твердой копии графической информации;
4) синтезаторы речи - речевой вывод;
5) звукогенераторы - вывод музыки;
б) для ввода сообщений:
1) клавиатура - текстовый ввод;
2) планшеты - графический ввод;
3) сканеры - графический ввод;
4) манипуляторы, световое перо, сенсорный экран - выбор информации и позиционирование на экране и т. п.
Различают процедурно-ориентированный и объектно-ориентированный подходы к разработке интерфейсов (рисунок 13.2).
Рисунок 13.2 - Типы интерфейсов
Процедурно-ориентированные интерфейсы используют традиционную модель взаимодействия с пользователем, основанную на понятиях «процедура» и «операция». В рамках этой модели программное обеспечение предоставляет пользователю возможность выполнения некоторых действий, для которых пользователь определяет соответствующие данные и следствием выполнения которых является получение желаемых результатов. Применение процедурно-ориентированных интерфейсов не означает использования структурного подхода к разработке соответствующего ПО. Реализация современного процедурно-ориентированного пользовательского интерфейса на базе структурного подхода является очень сложной и трудоемкой задачей.
Объектно-ориентированные интерфейсы используют несколько иную модель взаимодействия с пользователем, ориентированную на манипулирование объектами предметной области. В рамках этой модели пользователю предоставляется возможность напрямую взаимодействовать с каждым объектом и инициировать выполнение операций, в процессе которых взаимодействуют несколько объектов. Задача пользователя формулируется как целенаправленное изменение некоторого объекта, имеющего внутреннюю структуру, определенное содержание и внешнее символьное или графическое представление. Пользователю предоставляется возможность создавать объекты, изменять их параметры и связи с другими объектами, а также инициировать взаимодействие этих объектов. Элементы интерфейсов данного типа включены в пользовательский интерфейс Windows.
В таблице Г.2 перечислены основные отличия пользовательских моделей интерфейсов процедурного и объектно-ориентированного типов. Различают процедурно-ориентированные интерфейсы трех типов: примитивные, меню и со свободной навигацией [14].
Примитивным называют интерфейс, который организует взаимодействие с пользователем в консольном режиме. Обычно такой интерфейс реализует конкретный сценарий работы программного обеспечения (ввод данных - решение задачи - вывод результата). Единственное отклонение от последовательного процесса, которое обеспечивается данным интерфейсом, заключается в организации цикла для обработки нескольких наборов данных. Подобные интерфейсы в настоящее время используют только в процессе обучения программированию или в тех случаях, когда вся программа реализует одну функцию, например, в некоторых системных утилитах.
Интерфейс-меню позволяет пользователю выбирать необходимые операции из специального списка, выводимого ему программой. Эти интерфейсы предполагают реализацию множества сценариев работы, последовательность действий в которых определяется пользователем. Различают одноуровневые и иерархические меню. Интерфейсы данного типа несложно реализовать в рамках структурного подхода к программированию. Древовидная организация меню предполагает строго ограниченную навигацию: либо переходы «вверх» к корню дерева, либо - «вниз» по выбранной ветви. Каждому уровню иерархического меню соответствует свое определенное окно, содержащее пункты данного уровня. При этом возможны два варианта реализации меню: каждое окно меню занимает весь экран или на экране одновременно присутствуют несколько меню разных уровней. Во втором случае окна меню появляются при выборе пунктов соответствующего верхнего уровня - «выпадающие» меню. Интерфейсы-меню в настоящее время используют редко и только для сравнительно простого программного обеспечения или в разработках, которые должны быть выполнены по структурной технологии и без использования специальных библиотек.
Интерфейсы со свободной навигацией также называют графическими пользовательскими интерфейсами (GUI - Graphic User Interface) или интерфейсами WYSIWYG (What You See Is What You Get - что видишь, то и получишь, т. е., что пользователь видит на экране, то он и получит при печати). Эти названия подчеркивают, что интерфейсы данного типа ориентированы на использование экрана в графическом режиме с высокой разрешающей способностью. Графические интерфейсы поддерживают концепцию интерактивного взаимодействия с ПО, осуществляя визуальную обратную связь с пользователем и возможность прямого манипулирования объектами и информацией на экране. Кроме того, интерфейсы данного типа поддерживают концепцию совместимости программ, позволяя перемещать между ними информацию. Интерфейс со свободной навигацией обеспечивает возможность осуществления любых допустимых в конкретном состоянии операций, доступ к которым возможен через различные интерфейсные компоненты. Например, окна программ, реализующих интерфейс Windows, обычно содержат меню различных типов (ниспадающее, кнопочное, контекстное), разного рода компоненты ввода данных. Причем выбор следующей операции в меню осуществляется как мышью, так и с помощью клавиатуры. Существенной особенностью интерфейсов данного типа является способность изменяться в процессе взаимодействия с пользователем, предлагая выбор только тех операций, которые имеют смысл в конкретной ситуации. Реализуют интерфейсы со свободной навигацией, используя событийное программирование и объектно-ориентированные библиотеки, что предполагает применение визуальных сред разработки программного обеспечения.
Объектно-ориентированные интерфейсы пока представлены только интерфейсом прямого манипулирования. Этот тип предполагает, что взаимодействие пользователя с ПО осуществляется посредством выбора и перемещения пиктограмм, соответствующих объектам предметной области. Для их реализации используют событийное программирование и объектно-ориентированные библиотеки.
Разработка пользовательского интерфейса включает те же основные этапы, что и разработка программного обеспечения:
а) постановка задачи - определение типа интерфейса и общих требований к нему;
б) анализ требований и определение спецификаций - определение сценариев использования и пользовательской модели интерфейса;
в) проектирование - проектирование диалогов и их реализация в виде процессов ввода-вывода;
г) реализация - программирование и тестирование интерфейсных процессов.
Дополнительную информацию по теме можно получить в [1, 4, 14].
14 Лекция № 14. Особенности разработки пользовательских интерфейсов
Содержание лекции: психофизические особенности человека, связанные с восприятием, запоминанием и обработкой информации; пользовательская и программная модель интерфейса.
Цель лекции: ознакомиться с основными требованиями к разработке интерфейсов с учетом психофизических особенностей человека.
При проектировании пользовательских интерфейсов необходимо учитывать психофизические особенности человека, связанные с восприятием, запоминанием и обработкой информации. Исследованием принципов работы мозга человека занимается когнитивная психология [1].
Информация о внешнем мире поступает в мозг в огромных количествах. Часть мозга («процессор восприятия») постоянно без участия сознания перерабатывает ее, сравнивает с прошлым опытом, и помещает в хранилище уже в виде зрительных, звуковых и прочих образов. Любые внезапные или просто значимые для нас изменения в окружении привлекают внимание, и тогда интересующая информация поступает в кратковременную память. Если же внимание не было привлечено, то информация в хранилище пропадает, замещаясь следующими порциями. В каждый момент времени фокус внимания фиксируется в одной точке. При необходимости одновременно отслеживать несколько ситуаций фокус перемещается с одного элемента на другой. При этом внимание «рассредоточивается», и какие-то детали могут быть упущены. Так, при «прокрутке» текста или рисунка с использованием линейки прокрутки окна Windows приходится одновременно смотреть на текст и на ползунок. Поскольку текст важнее, фокус внимания перестает перемещаться на мышь, и она «соскакивает» с ползунка линейки. Следует иметь в виду, что обработка процессором восприятия требует некоторого времени и, если сигнал выдается в течение времени, меньшем времени обработки, то наш мозг его не воспринимает. Восприятие во многом основано на мотивации. Например, если человек голоден, то он в первую очередь будет замечать все съедобное, а если устал - то, войдя в комнату, он в первую очередь увидит диван. Следует учитывать, что при переработке информации мозг сравнивает поступающие данные с предыдущими. Так, если показать человеку последовательность символов «А, 13, С», то он может принять «13» за «В». При смене кадра мозг на некоторое время блокируется: он «осваивает» новую картинку, выделяя наиболее существенные детали, поэтому не стоит резко менять картинку, если необходима быстрая реакция пользователя.
Краткосрочная память является своего рода оперативной памятью мозга, именно с ней работает процессор познания, но не востребованная информация хранится в ней не более 30 секунд. Ее емкость приблизительно равна 7 ± 2 несвязанных объектов. Чтобы не забыть важную информацию, мы обычно повторяем ее «про себя», «обновляя» информацию в краткосрочной памяти. Поэтому при проектировании интерфейсов следует иметь в виду, что большинству людей сложно, например, запомнить и ввести на другом экране число, содержащее более 5 цифр (7 - 2), или некоторое сочетание букв.
Каждый человек вносит в деятельность свое понимание того, как она должна выполняться. Это понимание - модель деятельности - базируется на его прошлом опыте. Множество таких моделей хранится в долговременной памяти человека - хранилище информации с неограниченной емкостью и временем хранения. В нее записываются постоянно повторяемые сведения или информация, связанная с сильными эмоциями. Однако механизмы извлечения информации из памяти имеют ассоциативный характер. Специальная методика запоминания информации (мнемоника) использует именно это свойство памяти: для запоминания информации ее «привязывают» к тем данным, которые память уже хранит и позволяет легко получить. Поскольку доступ к долговременной памяти затруднен, целесообразно рассчитывать не на то, что пользователь вспомнит нужную информацию, а на то, что он ее узнает. Именно поэтому так широко используется интерфейс типа меню.
Цвет в сознании человека ассоциируется с эмоциональным фоном: теплые цвета – возбуждают, а холодные - успокаивают. Цвет является для человека сильным раздражителем, поэтому применять цвета в интерфейсе необходимо крайне осторожно. Следует иметь в виду, что обилие оттенков привлекает внимание, но быстро утомляет. Не стоит ярко раскрашивать окна, с которыми пользователь будет долго работать. Необходимо учитывать и индивидуальные особенности восприятия цветов человеком: примерно каждый десятый плохо различает какие-либо цвета, поэтому в ответственных случаях необходимо предоставить пользователю возможность их настройки.
В интерфейсах звук используют с разными целями: для привлечения внимания, как фон, обеспечивающий некоторое состояние пользователя, как источник дополнительной информации. Применяя звук, следует учитывать, что большинство людей очень чувствительны к звуковым сигналам, особенно, если они указывают на наличие ошибки. Поэтому при создании звукового сопровождения целесообразно предусматривать возможность его отключения.
Человеку свойственно субъективное восприятие времени. Считают, что внутреннее время связано со скоростью и количеством воспринимаемой и обрабатываемой информации. Занятый человек времени не замечает. Зато в состоянии ожидания время тянется бесконечно: в это время мозг оказывается в состоянии информационного вакуума. Доказано, что при ожидании более 1-2 секунд пользователь может отвлечься, «потерять мысль», что увеличивает усталость и неблагоприятно сказывается на результатах работы. Сократить время ожидания можно, заняв пользователя, но не отвлекая его от работы. Например, предоставить ему какую-либо информацию для обдумывания или выводить промежуточные результаты.
Известны попытки использования для «развлечения» пользователя анимации. Следует иметь в виду, что интересно смотреть анимацию первый раз, а когда в течение получаса при скачивании файлов из Интернета наблюдаешь, как «летают» листочки, то это начинает раздражать. Поэтому необходимо соблюдать основное правило: информировать пользователя, что заказанные операции потребуют некоторого времени выполнения, используя индикаторы оставшегося времени, анимацию и изменение формы курсора мыши на песочные часы. Важно точно обозначить момент, когда система готова продолжать работу, для чего значительно изменяют внешний вид экрана.
В итоге взаимодействие пользователя с интерфейсом определяется не только его физическими возможностями и особенностями по восприятию информации, но и пользовательской моделью интерфейса. Существуют три модели пользовательского интерфейса: модель программиста, модель пользователя, программная модель. Программист при разработке интерфейса исходит из того, управление какими операциями нужно реализовать в нем, и как это осуществить, не затрачивая существенных ресурсов компьютера, своих сил и времени. Его интересуют эффективность, функциональность, технологичность, внутренняя стройность и другие не связанные с удобством пользователя характеристики ПО. Именно поэтому большинство интерфейсов существующих программ вызывают серьезные нарекания пользователей. С точки зрения здравого смысла хорошим считается интерфейс, при работе с которым пользователь получает именно то, что он ожидал. Представление пользователя о функциях интерфейса можно описать в виде пользовательской модели интерфейса - совокупности обобщенных представлений конкретного пользователя или группы пользователей о процессах, происходящих во время работы программной системы. Модель базируется на особенностях опыта конкретных пользователей, который характеризуется уровнем подготовки в предметной области разрабатываемого ПО, интуитивными моделями выполнения операций в этой области, уровнем подготовки в области владения компьютером, а также устоявшимися стереотипами работы с компьютером. Для ее построения необходимо изучить особенности опыта предполагаемых пользователей, для чего используют опросы, тесты и фиксируют на пленку последовательность выполнения операций в реальном процессе. Приведение в соответствие моделей пользователя и программиста, а также построение на их базе программной модели интерфейса (рисунок 14.1) задача не простая. Чем сложнее автоматизируемая предметная область, тем сложнее строить программную модель интерфейса, учитывающую особенности модели программиста и пользовательской модели. С этой точки зрения наиболее перспективны объектные интерфейсы, так как в их основе лежит отображение объектов предметной области, которыми оперируют пользователи. Основой для разработки интерфейса должны стать интуитивные модели выполнения операций в предметной области. Нежелание или невозможность следования интуитивным моделям приводит к созданию искусственных надуманных интерфейсов, которые негативно воспринимаются пользователями.
Рисунок 14.1 - Процесс разработки пользовательского интерфейса
Иногда кажется, что единственно доступный для изменения элемент - устоявшийся стереотип работы с компьютером. Но ломка стереотипов - процедура болезненная. На это стоит решаться, если некоторое революционное изменение значительно расширяет возможности пользователя или облегчает его работу, например, переход к Windows-интерфейсам существенно упростил работу с компьютером для пользователей-непрофессионалов. Ломая стереотипы по мелочам, разработчик рискует оттолкнуть пользователей, которые просто не будут понимать, что происходит.
Основными критериями оценки интерфейсов пользователем являются:
а) простота освоения и запоминания операций системы - оценивают время освоения и продолжительность сохранения информации в памяти;
б) скорость достижения результатов при использовании системы - определяется количеством вводимых или выбираемых мышью команд и настроек;
в) субъективная удовлетворенность при эксплуатации (удобство работы, утомляемость и т. д.).
Для пользователей-профессионалов, постоянно работающих с одним и тем же пакетом, на первое место достаточно быстро выходят критерии б и в, а для пользователей-непрофессионалов, работающих с ПО периодически и выполняющих сравнительно несложные задачи – а и в. Поэтому наилучшими характеристиками для профессионалов обладают интерфейсы со свободной навигацией, а для непрофессионалов - интерфейсы прямого манипулирования.
Дополнительную информацию по теме можно получить в [1, 4, 14].
15 Лекция № 15. Компоненты пользовательских интерфейсов. Технология Drag&Drop
Содержание лекции: диалоговые средства связи пользователей с ПК; технология Drag&Drop; интеллектуальные элементы пользовательских интерфейсов.
Цель лекции: ознакомиться с компонентами пользовательских интерфейсов и технологиями, применяемыми при их создании.
Диалог - это процесс обмена информацией между пользователем и программной системой, осуществляемый через интерактивный терминал и по определенным правилам. Различают тип диалога и его форму. Тип диалога определяет, кто из «собеседников» управляет обменом информацией. Соответственно различают диалоги, управляемые программой и управляемые пользователем. Диалог, управляемый программой, предусматривает наличие жесткого, линейного или древовидного сценария диалога, заложенного в ПО. Его сопровождают большим количеством подсказок, уточняющих, какую информацию необходимо вводить на каждом шаге. Диалог, управляемый пользователем, подразумевает, что сценарий диалога зависит от пользователя, применяющего систему для выполнения операций, а система обеспечивает возможность реализации различных сценариев пользователя.
Диалог невозможен без понятного «собеседникам» языка, описание которого включает синтаксис (правила, определяющие допустимые конструкции языка или его форму) и семантику (правила, определяющие смысл синтаксически корректных конструкций языка или его содержание). В зависимости от вида синтаксиса и семантики различают три формы диалога: фразовую, директивную и табличную.
Фразовая форма предполагает «общение» на естественном языке или его подмножестве. Содержание диалога в данной форме составляют повелительные, повествовательные и вопросительные предложения, а также ответы на вопросы. Общение может осуществляться в свободном формате, но возможна и фиксация отдельных фраз. Поскольку организовать диалог на естественном языке достаточно сложно, чаще всего используют диалоги, предполагающие односложные ответы. В этом случае программа содержит ограниченное описание синтаксиса и семантики используемого ограниченно-естественного языка. Для интеллектуальных систем интерфейсы создаются на базе ограниченного подмножества предложений естественного языка. Синтаксис и семантика языков диалога, реализуемых в таких интерфейсах, достаточно сложны. При обработке фраз в этих случаях оперируют понятием словоформа. Таким образом, интерфейс, реализующий фразовую форму диалога, должен преобразовывать сообщения из естественно-языковой формы в форму внутреннего представления и обратно, выполнять анализ и синтез сообщений пользователя и системы, отслеживать и запоминать пройденную часть диалога. Недостатками фразовой формы при использовании подмножества естественного языка являются: большие затраты ресурсов, отсутствие гарантии однозначной интерпретации формулировок, необходимость ввода длинных грамматически правильных фраз. Достоинство состоит в относительно свободном общении с системой.
Директивная форма предполагает использование команд (директив) специально разработанного формального языка. Командой в этом случае называют предложение этого языка, описывающее комбинированные данные, которые включают идентификатор инициируемого процесса и данные для него. Достоинствами директивной формы являются сравнительно небольшой объем вводимой информации, гибкость, ориентация на диалог, управляемый пользователем, использование минимальной области экрана, возможность совмещения с другими формами. Недостатки: практическое отсутствие подсказок на экране; почти полное отсутствие обратной связи о состоянии инициированных процессов; необходимость навыков ввода текстовой информации или манипуляций мышью; отсутствие возможности настройки пользователем. Директивная форма удобна для профессионалов, которые быстро запоминают синтаксис команд или комбинации клавиш.
Табличная форма предполагает, что пользователь выбирает ответ из вариантов, предложенных программой. Язык диалога для табличной формы имеет простейший синтаксис и однозначную семантику. Однако применение табличной формы возможно не всегда: ее можно использовать только, если ограничено множество возможных ответов на конкретный вопрос (менее 20). Достоинствами табличной формы являются: наличие подсказки; сокращение количества ошибок ввода (пользователь не вводит информацию, а указывает на нее); сокращение времени обучения пользователя; возможность совмещения с другими формами; возможность настройки пользователем. Недостатки: необходимость наличия навыков навигации по экрану; использование сравнительно большой площади экрана для изображения визуальных компонентов; интенсивное использование ресурсов компьютера, связанное с необходимостью постоянного обновления информации на экране.
Типы и формы диалога выбирают независимо друг от друга: любая форма применима для обоих типов диалогов (рисунок 15.1).
Рисунок 15.1 - Соответствие типов диалогов и его форм
Сложное программное обеспечение взаимодействует с пользователем посредством диалогов различных типов и форм в зависимости от решаемых задач. Для выдачи экстренных сообщений от системы или пользователя используют синхронные и асинхронные диалоги. В процессе проектирования и реализации используют абстрактные, конкретные и технические диалоги.
Пользовательские интерфейсы большинства современных программ строятся по технологии WIMP [14]: W - Windows (окна), I - Icons (пиктограммы), М - Mouse (мышь), Р - Pop-up (всплывающие или выпадающие меню). Основными элементами графических интерфейсов являются: окна, пиктограммы, компоненты ввода-вывода и мышь, используемая в качестве указующего устройства и устройства прямого манипулирования объектами на экране.
Окно - прямоугольная, ограниченная рамкой область физического экрана. Окно может менять размеры и местоположение в пределах экрана. Все окна можно разделить на основные окна (окна приложений); дочерние или подчиненные окна, окна диалога, информационные окна и окна меню.
Пиктограмма - это небольшое окно с графическим изображением, отражающим содержимое буфера, с которым она связана. Различают программные пиктограммы, пиктограммы дочерних окон, пиктограммы панели инструментов, пиктограммы объектов.
Прямое манипулирование изображением - это возможность замены команды воздействия на некоторый объект физическим действием в интерфейсе, осуществляемым с помощью мыши. При этом любая область экрана рассматривается как адресат, который может быть активизирован при подведении курсора и нажатии клавиши мыши. По реакции на воздействие различают следующие типы адресатов: указание и выбор, буксировка и «резиновая нить» (перенос объекта или его границ), экранные кнопки и «скользящие» барьеры (выполнение дискретных или циклических действий).
Для предоставления пользователям дополнительной информации в графических интерфейсах применяются динамические визуальные сигналы (изменение изображения объекта на экране при выполнении действий).
В окнах приложений могут размещаться специальные компоненты ввода-вывода информации. Интерфейс обычно включает несколько меню: основное или «ниспадающее» иерархическое меню, пиктографические меню (панели инструментов) и контекстные меню - компоненты ввода-вывода, реализующие диалог с пользователем в табличной форме. Кроме меню в интерфейсе используют и другие компоненты ввода-вывода, которые можно разделить на три группы в зависимости от формы реализуемого диалога: фразовую, табличную или смешанную. Директивная форма диалога предполагает ввод комбинаций клавиш или перемещение пиктограмм, а потому не требует использования компонентов ввода-вывода.
Возможность прямого манипулирования, предусмотренная в WIMP-интерфейсах, позволяет разрабатывать для приложений объектно-ориентированные интерфейсы прямого манипулирования. Интерфейсы данного типа на внешнем уровне используют директивную форму диалога: ввод команды осуществляется при выполнении определенных действий с пиктограммой объекта мышью. Их основными элементами являются: метафоры, объекты, представления объектов и технология Drag&Drop [1].
Технология Drag&Drop («перетащил и бросил») определяет основные принципы прямого манипулирования, описанные в руководстве по разработке пользовательских интерфейсов фирмы IBM (CUA - Common User Access):
а) результат перемещения объекта должен соответствовать ожиданиям;
б) пользователи не должны неожиданно терять информацию;
в) пользователь должен иметь возможность отменить действие.
Эта технология также определяет основные принципы визуализации операции прямого манипулирования:
а) исходное выделение - используется в качестве обратной связи пользователю, чтобы сообщить ему, что объект захвачен;
б) визуализация перемещения - идентификация выполняемого действия;
в) целевое выделение - идентификация пункта назначения;
г) визуализация действия - используется для обозначения времени ожидания завершения операции (изменение формы курсора на «песочные часы»).
В последние годы появилось много новых перспективных элементов пользовательских интерфейсов, привносящих в них элементы искусственного интеллекта: Мастер, Советчик, Агент. Сделано множество попыток создания социализированного пользовательского интерфейса, в основе которого интерфейса лежит идея создания персонифицированного («имеющего личность») интерфейса. Однако в этой области существуют психологические проблемы. Например, «безобидный» Советчик Microsoft Office вызывает у многих пользователей резко отрицательную реакцию.
Советчики представляют собой форму подсказки, вызываемой с помощью меню справки, командной строки окна или всплывающего меню. Они помогают пользователям в выполнении конкретных задач, в случае, если пользователь представляет, что ему нужно сделать.
Программа-мастер служит для выполнения общераспространенных, но редко выполняемых отдельным пользователем задач (установка программ или оборудования). Выполнение подобных действий требует принятия сложных взаимосвязанных решений, последовательность которых диктует программа-мастер. Интеллектуальные Мастера способны демонстрировать в окне просмотра результаты ответов пользователя на предыдущие вопросы на каждом шаге, помогая сориентироваться в ситуации.
Программные агенты - это элемент ПО, которому пользователь может передать часть своих обязанностей, используемый для выполнения рутинной работы. Их основные функции: наблюдение, поиск и управление. Различают:
а) программы-агенты, настраиваемые на выполнение указанных задач;
б) программы-агенты, способные обучаться, например, фиксируя действия пользователя (по типу магнитофона).
Дополнительную информацию по теме можно получить в [1, 5, 14, 18].
16 Лекция № 16. Тестирование и отладка программных продуктов
Содержание лекции: виды контроля качества разрабатываемого ПО; ручной контроль; структурное, функциональное и оценочное тестирование; классификация ошибок; методы и средства отладки ПО.
Цель лекции: ознакомиться с видами и способами контроля и тестирования ПО, методами и средствами отладки программ.
Недостаточно выполнить проектирование и кодирование программного продукта, также необходимо обеспечить его соответствие требованиям и спецификациям. Многократно проводимые исследования показали, что чем раньше обнаруживаются те или иные несоответствия или ошибки, тем больше вероятность их исправления и ниже его стоимость [4]. Современные технологии разработки ПО предусматривают раннее обнаружение ошибок за счет выполнения контроля результатов всех этапов и стадий разработки. На начальных этапах контроль осуществляют вручную или с использованием CASE-средств, на последних - он принимает форму тестирования.
Тестирование - это процесс выполнения программы, целью которого является выявление ошибок. Никакое тестирование не может доказать отсутствие ошибок в сложном ПО, поскольку выполнение полного тестирования становится невозможным и имеется вероятность, что остались невыявленные ошибки. Соблюдение основных правил тестирования и научно обоснованный подбор тестов может уменьшить их количество. Процесс разработки согласно современной модели жизненного цикла ПО предполагает три стадии тестирования: автономное тестирование компонентов ПО; комплексное тестирование разрабатываемого ПО; системное или оценочное тестирование на соответствие основным критериям качества. Для повышения качества тестирования рекомендуется соблюдать следующие основные принципы:
а) предполагаемые результаты должны быть известны до тестирования;
б) следует избегать тестирования программы автором;
в) необходимо досконально изучать результаты каждого теста;
г) необходимо проверять действия программы на неверных данных;
д) необходимо проверять программу на неожиданные побочные эффекты на неверных данных.
Вероятность наличия необнаруженных ошибок в части программы пропорциональна количеству ошибок уже найденных в этой части. Удачным считают тест, который обнаруживает хотя бы одну ошибку. Формирование набора тестов имеет большое значение, поскольку тестирование является одним из наиболее трудоемких этапов создания ПО. Доля стоимости тестирования в общей стоимости разработки возрастает при увеличении сложности ПО и повышении требований к их качеству.
Существуют два принципиально различных подхода к формированию тестовых наборов: структурный и функциональный. Структурный подход базируется на том, что известна структура тестируемого ПО, в том числе его алгоритмы («стеклянный ящик»). Тесты строятся для проверки правильности реализации заданной логики в коде программы. Функциональный подход основывается на том, что структура ПО не известна («черный ящик»). В этом случае тесты строят, опираясь на функциональные спецификации. Этот подход называют также подходом, управляемым данными, так как при его использовании тесты строят на базе различных способов декомпозиции множества данных. Наборы тестов, полученные в соответствии с методами этих подходов, объединяют, обеспечивая всестороннее тестирование ПО.
Ручной контроль используют на ранних этапах разработки. Все проектные решения анализируются с точки зрения их правильности и целесообразности как можно раньше, пока их можно легко пересмотреть. Различают статический и динамический подходы к ручному контролю. При статическом подходе анализируют структуру, управляющие и информационные связи программы, ее входные и выходные данные. При динамическом - выполняют ручное тестирование (вручную моделируют процесс выполнения программы на заданных исходных данных). Исходными данными для таких проверок являются: техническое задание, спецификации, структурная и функциональная схемы программного продукта, схемы отдельных компонентов, а для более поздних этапов - алгоритмы и тексты программ, а также тестовые наборы. Доказано, что ручной контроль способствует существенному увеличению производительности и повышению надежности программ и с его помощью можно находить от 30 до 70 % ошибок логического проектирования и кодирования. Основными методами ручного контроля являются: инспекции исходного текста, сквозные просмотры, проверка за столом, оценки программ.
В основе структурного тестирования лежит концепция максимально полного тестирования всех маршрутов, предусмотренных алгоритмом (последовательности операторов программы, выполняемых при конкретном варианте исходных данных). Недостатки: построенные тестовые наборы не обнаруживают пропущенных маршрутов и ошибок, зависящих от заложенных данных; не дают гарантии, что программа правильна.
Другим способом проверки программ является функциональное тестирование: программа рассматривается как «черный ящик», целью тестирования является выяснение обстоятельств, когда поведение программы не соответствует спецификации. Для обнаружения всех ошибок необходимо выполнить исчерпывающее тестирование (при всех возможных наборах данных), что для большинства случаев невозможно. Поэтому обычно выполняют «разумное» или «приемлемое» тестирование, ограничивающееся прогонами программы на небольшом подмножестве всех возможных входных данных. При функциональном тестировании различают следующие методы формирования тестовых наборов: эквивалентное разбиение; анализ граничных значений; анализ причинно-следственных связей; предположение об ошибке.
При комплексном тестировании используют тесты, построенные по методам эквивалентных классов, граничных условий и предположении об ошибках, поскольку структурное тестирование для него не применимо. Одним из самых сложных является вопрос о завершении тестирования, так как невозможно гарантировать, что в программе не осталось ошибок. Часто тестирование завершают потому, что закончилось время, отведенное на его выполнение. Его сворачивают, обходясь минимальным тестированием [15], которое предполагает: тестирование граничных значений, тщательную проверку руководства, тестирование минимальных конфигураций технических средств, возможности редактирования команд и повторения их в любой последовательности, устойчивости к ошибкам пользователя.
После завершения комплексного тестирования приступают к оценочному тестированию, целью которого является поиск несоответствий техническому заданию. Оценочное тестирование включает тестирование: удобства использования, на предельных объемах, на предельных нагрузках, удобства эксплуатации, защиты, производительности, требований к памяти, конфигурации оборудования, совместимости, удобства установки, удобства обслуживания, надежности, восстановления, документации, процедуры.
Отладка - это процесс локализации (определения оператора программы, выполнение которого вызвало нарушение вычислительного процесса) и исправления ошибок, обнаруженных при тестировании ПО. Для исправления ошибки необходимо определить ее причину. Отладка требует от программиста глубоких знаний специфики управления используемыми техническими средствами, операционной системы, среды и языка программирования, реализуемых процессов, природы и специфики ошибок, методик отладки и соответствующих программных средств; психологически дискомфортна (нужно искать собственные ошибки в условиях ограниченного времени); оставляет возможность взаимовлияния ошибок в разных частях программы. Четко сформулированные методики отладки отсутствуют. Различают:
а) синтаксические ошибки – сопровождаются комментарием с указанием их местоположения, фиксируются компилятором (транслятором) при выполнении синтаксического и частично семантического анализа;
б) ошибки компоновки - обнаруживаются компоновщиком (редактором связей) при объединении модулей программы;
в) ошибки выполнения - обнаруживаются аппаратными средствами, операционной системой или пользователем при выполнении программы, проявляются разными способами и в свою очередь делятся на группы:
1)ошибки определения исходных данных (ошибки передачи, ошибки преобразования, ошибки перезаписи и ошибки данных);
2)логические ошибки проектирования (неприменимый метод, неверный алгоритм, неверная структура данных, другие) и кодирования (ошибки некорректного использования переменных, вычислений, межмодульного интерфейса, реализации алгоритма, другие);
3)ошибки накопления погрешностей результатов вычислений (игнорирование ограничений разрядной сетки и способов уменьшения погрешности).
Отладка программы в любом случае предполагает обдумывание и логическое осмысление всей имеющейся информации об ошибке. Большинство ошибок можно обнаружить по косвенным признакам посредством тщательного анализа текстов программ и результатов тестирования без получения дополнительной информации с помощью следующих методов:
а) ручного тестирования (при обнаружении ошибки нужно выполнить тестируемую программу вручную, используя тестовый набор, при работе с которым была обнаружена ошибка);
б) индукции (основан на тщательном анализе симптомов ошибки, которые могут проявляться как неверные результаты вычислений или как сообщение об ошибке);
в) дедукции (вначале формируют множество причин, которые могли бы вызвать данное проявление ошибки, а затем анализируя причины, исключают те, которые противоречат имеющимся данным);
г) обратного прослеживания (для точки вывода неверного результата строится гипотеза о значениях основных переменных, которые могли бы привести к получению данного результата, а затем, исходя из этой гипотезы, делают предположения о значениях переменных в предыдущей точке).
Для получения дополнительной информации об ошибке выполняют добавочные тесты и используют специальные методы и средства: отладочный вывод; интегрированные средства отладки; независимые отладчики.
Общая методика отладки программных продуктов, написанных для выполнения в операционных системах MS DOS и Win32:
1 этап - изучение проявления ошибки;
2 этап – определение локализации ошибки;
3 этап - определение причины ошибки;
4 этап — исправление ошибки;
5 этап - повторное тестирование.
Процесс отладки можно существенно упростить, если следовать основным рекомендациям структурного подхода к программированию:
а) программу наращивать «сверху-вниз», от интерфейса к обрабатывающим подпрограммам, тестируя ее по ходу добавления подпрограмм;
б) выводить пользователю вводимые им данные для контроля и проверять их на допустимость сразу после ввода;
в) предусматривать вывод основных данных во всех узловых точках алгоритма (ветвлениях, вызовах подпрограмм).
Дополнительную информацию по теме можно получить в [1, 2, 4, 7, 9, 14, 15].
17 Лекция № 17. Составление программной документации
Содержание лекции: виды программных документов; пояснительная записка; руководство пользователя.
Цель лекции: ознакомиться с видами программных документов и основными правилами оформления программной документации.
Одним из главных отличий программы от программного продукта является наличие разнообразной, хорошо подготовленной документации. Составление программной документации - важный процесс. На каждый программный продукт должна разрабатываться документация двух типов: для пользователей различных групп и для разработчиков. Отсутствие документации любого типа для конкретного ПО не допустимо. При подготовке документации не следует забывать, что она разрабатывается для того, чтобы ее использовали, и потому она должна содержать все необходимые сведения [1].
К программным относят документы, содержащие сведения, необходимые для разработки, сопровождения и эксплуатации программного обеспечения. Документирование программного обеспечения осуществляется в соответствии с Единой системой программной документации (ГОСТ 19.ХХХ). Так ГОСТ 19.101-77 устанавливает виды программных документов для ПО различных типов. К основным программным документам по этому стандарту относятся: спецификация, ведомость держателей подлинников, текст программы, описание программы, ведомость эксплуатационных документов, формуляр, описание применения, руководство системного программиста, руководство программиста, руководство оператора, описание языка, руководство по техническому обслуживанию, программа и методика испытаний, пояснительная записка. Допускается объединять отдельные виды эксплуатационных документов. Необходимость объединения указывается в техническом задании, а имя берут у одного из объединяемых документов. При оформлении текстовых и графических материалов, входящих в программную документацию также следует придерживаться действующих стандартов. Рассмотрим подробнее некоторые из перечисленных документов.
Самым главным документом для разработчиков является техническое задание (ТЗ), в котором описываются цели и задачи работы, заказчик и исполнители, технические требования, сроки и этапы, требования секретности, форс-мажорные обстоятельства и правила предъявления результатов. ТЗ должно быть составлено таким образом, чтобы исключить возможные разночтения, все требования должны быть сформулированы так, чтобы их можно было проверить однозначным образом.
Следующим по важности документом является программа и методика испытаний (ПМИ). Структурно она подобна ТЗ – практически для каждого пункта ТЗ в ПМИ говорится, как этот пункт будет проверяться. Способы проверки могут быть самыми разными – от пропуска специального теста до изучения исходных текстов программы, но они должны быть предусмотрены заранее, а не придумываться в момент испытаний. Новички приступают к составлению ПМИ непосредственно перед завершением работ, а опытные руководители составляют и согласовывают с заказчиками одновременно с ТЗ. Хорошо составленная ПМИ является гарантией успешной сдачи работ.
Руководство системного программиста, на современном языке называется руководством по инсталляции. В нем описывается порядок установки системы, как проверить корректность поставленной системы, как вносить изменения и т.п. Обычно это простой короткий документ.
Руководство оператора (пользователя) – это основной документ, описывающий, как пользоваться системой [16]. В хорошем руководстве сначала описывается идея системы, основные функции и как ими пользоваться, а уже потом идет описание всех клавиш и меню.
Руководство программиста - это самый объемный документ, описывающий внутреннюю организацию программы. Обычно этот документ идет в паре с документом "текст программы" – одностраничным документом с оглавлением дискеты или CD. Руководство программиста дает заказчику возможность дописать новые фрагменты программы или переделать старые. В современной литературе этот документ называется SDK (Software Development Kit). Продукт, снабженный SDK, может стоить на порядок дороже, чем такой же продукт без него. Сейчас не принято продавать исходные тексты программ – проблемы с интеллектуальной собственностью, даже при наличии SDK трудно "влезть" в чужую программу – как говорится, себе дороже. Поэтому большое распространение получили API (Application Program Interface). Программа передается только в виде DLL (библиотека двоичных кодов), но известно, как обратиться к каждой функции из других программ, т.е. известно имя точки входа, количество, типы и значения параметров. Наличие множества API, конечно, хуже, чем наличие исходных текстов (например, нельзя переделать что-то в середине функции), зато много проще в использовании. С другой стороны, все большую популярность приобретает FSF (Free Software Foundation). Основателем этого движения был Ричард Столман [4], который забил тревогу по поводу попыток крупных фирм запатентовать многие основные алгоритмы и программы: "Дойдет до того, что они запатентуют понятия "цикл" и "подпрограмма", что мы будем тогда делать?" FSF представляет собой собрание программ в исходных текстах; любой программист может свободно использовать их в своих целях, но все добавления и улучшения, которые он сделал, тоже следует положить в FSF. Таким образом, FSF представляет собой одно из самых больших доступных хранилищ программ.
Дополнительную информацию по теме можно получить в [1, 4, 16].
Приложение А
Основные этапы развития технологий программирования
Рисунок А.1 – Структурный подход. Модульное программирование
Рисунок А.2 – Объектный подход. Архитектура программы при объектно-ориентированном программировании
Рисунок А.3 – Компонентный подход. Технология СОМ
Рисунок А.4 – Соотношение абстрактного и конкретного в описании блоков
при блочно-иерархическом подходе
Рисунок А.5 – Структура процессов жизненного цикла программного обеспечения
Приложение Б
Эволюция моделей жизненного цикла
Рисунок Б.1 – Каскадная схема разработки программного обеспечения
Рисунок Б.2 – Схема разработки программного обеспечения с промежуточным контролем
Рисунок Б.3 – Спиральная схема разработки программного обеспечения
Приложение В
Структурное и «неструктурное» программирование
Таблица В.1 – Соответствие различных способов описания алгоритмов
Струк-тура |
Псевдокоды |
Flow-формы |
Диаграммы Насси-Шнейдермана |
Следо-вание |
<действие 1> <действие 2> |
|
|
Ветвле-ние |
Если <условие> то <действие 1> иначе <действие 2> Все-если |
|
|
Цикл-пока |
Цикл-пока <условие> <действие> Все-цикл |
||
Выбор |
Выбор <код> <код 1>: <действие 1> <код 2>: <действие 2> иначе <действие 3> Все-выбор |
|
|
Цикл с парамет-ром |
Для <индекс> = <n>,<m>,<h> <действие > Все-цикл |
|
|
Цикл-до |
Выполнять <действие> До <условие> |
|
Рисунок В.1 – Способы проявления ошибок
Приложение Г
Проектирование программного обеспечения
Рисунок Г.1 – Классификация программных продуктов по их назначению
Рисунок Г.2 - Пример диаграммы переходов состояний ПО:
а) не взаимодействующего с окружающей средой;
б) активно взаимодействующего с окружающей средой
Таблица Г.1 – Основные обозначения схем данных по ГОСТ 19.701-90
Название блока |
Обозначение |
Назначение блока |
Запоминаемые данные |
|
Обозначение таблиц и других структур данных, которые должны быть сохранены без уточнения типа устройства |
Оперативное запоминающее устройство |
|
Для обозначения таблиц и других структур данных, хранящихся в оперативной памяти |
Запоминающее устройство с последовательной выборкой |
|
Для обозначения таблиц и других структур данных, хранящихся на устройствах с последовательной выборкой (магнитной ленте и т.п.) |
Запоминающее устройство с прямым доступом |
|
Для обозначения таблиц и других структур данных, хранящихся на устройствах с прямым доступом (дисках) |
Документ |
|
Для обозначения таблиц и других структур данных, выводимых на печатающее устройство |
Ручной ввод |
|
Для обозначения ручного ввода данных с клавиатуры |
Карта |
|
Для обозначения данных на магнитных или перфорированных картах |
Дисплей |
|
Для обозначения данных, выводимых на дисплей |
Таблица Г.2 – Основные отличия пользовательских моделей интерфейсов
Процедурно-ориентированные пользовательские интерфейсы |
Объектно-ориентированные пользовательские интерфейсы |
Обеспечивают пользователей функциями, необходимыми для выполнения задач |
Обеспечивают пользователям возможность взаимодействия с объектами |
Акцент делается на задачи |
Акцент делается на входные данные и результаты |
Пиктограммы представляют приложения, окна или операции |
Пиктограммы представляют объекты |
Содержание папок и справочников отображается с помощью таблиц и списков |
Папки и справочники являются визуальными контейнерами объектов |
Список литературы
1. Иванова Г.С. Технология программирования. - М.: Изд-во МГТУ им. Н.Э.Баумана, 2002.
2. Аляев Ю.А., Козлов О.А. Алгоритмизация и языки программирования Pascal, C++, Visual Basic: Учебно-справочное пособие. – М.: Финансы и статистика, 2004.
3. Иванова Г.С. Основы программирования. - М.: Изд-во МГТУ им. Н.Э.Баумана, 2001.
4. Терехов А.Н. Технология программирования. – М.: БИНОМ. Лаборатория знаний, Интернет-университет информационных технологий - Intuit.ru, 2006.
5. Вендров А.М. CASE-технологии. Современные методы и средства проектирования информационных систем. - М.: Финансы и статистика, 1998.
6. Вирт Н. Алгоритмы и структуры данных. – М.: Мир, 1989.
7. Тассел Д. Ван. Стиль, разработка, эффективность, отладка и испытание программ. – М.: Мир, 1985.
8. Соммервиль И. Инженерия программного обеспечения. - М.: Изд-во Вильямс, 2002.
9. Кантор М. Управление программными проектами. Практическое руководство по разработке успешного программного обеспечения. - М.: Вильямс, 2002.
10. Бахман П., Френцель М., Ханцшманн К и др. Программные системы. – М.: Мир, 1988.
11. Фаулер М., Скотт К. UML в кратком изложении. Применение стандартного языка объектного моделирования. – М.: Мир, 1999.
12. Буч Г., Рамбо Д., Джекобсон А. Язык UML. Руководство пользователя. – М.: ДМК Пресс, 2001.
13. Кватрани Т. Rational Rose 2000 и UML. Визуальное моделирование. - М.: ДМК Пресс, 2001.
14. Мандел Т. Разработка пользовательского интерфейса. – М.: ДМК Пресс, 2001.
15. Канер С., Фолк Д., Нгуен Е.К. Тестирование программного обеспечения. - Киев: «ДиаСофт», 2000.
16. Гримм С.Дж. Как писать руководства для пользователей. – М.: Радио и связь, 1985.
17. Ашарина И.В. Основы программирования на языках С и С++.- М.: Горячая линия - Телеком, 2002.
18. Попов В.Б. Основы информационных и телекоммуникационных технологий. Программные средства информационных технологий. – М.: Финансы и статистика, 2005.
19. Архангельский А.Я. Язык Pascal и основы программирования в Delphi. – М.: ЗАО Бином, 2004.