МИНИСТЕРСТВО ОБРАЗОВАНИЯ РЕСПУБЛИКИ КАЗАХСТАН
Некоммерческое акционерное общество
АЛМАТИНСКИЙ УНИВЕРСИТЕТ ЭНЕРГЕТИКИ И СВЯЗИ
Н.В.Сябина
ТЕХНОЛОГИИ ПРОГРАММИРОВАНИЯ
Учебное пособие
Алматы 2012
УДК 004.412/416.2 (075.8)
ББК 32.973-018 я 73
С99 Технологии программирования:
Учебное пособие/Н.В.Сябина;
АУЭС, Алматы, 2011. - 99 с.
Табл.5, Ил.30, Библиогр.– 42 назв.
ISBN 978-601-7307-07-03
В учебном пособии излагаются основные понятия и подходы к технологиям программирования, особенности проектирования сложного программного обеспечения, вопросы разработки пользовательских интерфейсов, тестирования, отладки программных и документирования программного обеспечения.
Учебное пособие предназначено для студентов специальности 5В070200 - Автоматизация и управление.
ББК 32.973-018 я 73
РЕЦЕНЗЕНТЫ: КазНТУ, канд.тех.наук, доцент Байматаева Ш.М., АУЭС, канд.тех.наук, доцент Аманбаев А.А.
Печатается по плану издания Министерства образования Республики Казахстан на 2011 г.
ISBN 978-601-7307-07-03
© НАО «Алматинский университет энергетики и связи», 2012
Содержание
Введение 4
1 глава. Введение в технологию программирования. Основные понятия и
подходы 5
1.1 Понятие технологии программирования и ее роль 5
1.2 Основные этапы развития технологии программирования 5
1.3 Краткий обзор наиболее известных технологий 11
2 глава. Особенности разработки сложных программных систем 14
2.1 Основные принципы разработки 14
2.2 Жизненный цикл программного обеспечения 16
2.3 Качество программного обеспечения 26
2.4 Роль модулей в обеспечении технологичности 27
2.5 Основные подходы к разработке программного обеспечения 32
2.6 Стили оформления программы 43
2.7 Программирование без ошибок 46
3 глава. Требования и исходные данные к разработке программного
обеспечения 49
3.1 Классификация программного обеспечения по функциональному
признаку 49
3.2 Эксплуатационные требования к программному обеспечению 51
3.3 Постановка задачи 52
3.4 Анализ требований и определение спецификаций 60
4 глава. Особенности проектирования программного обеспечения при различных подходах 65
4.1 Структурный подход 65
4.2 Объектный подход 68
5 глава. Пользовательские интерфейсы 74
5.1 Основные понятия 75
5.2 Виды пользовательских интерфейсов 76
5.3 Типы пользовательских интерфейсов 80
5.4 Особенности разработки пользовательских интерфейсов 82
6 глава. Тестирование и отладка программных продуктов 87
6.1 Основы тестирования программного обеспечения 87
6.2 Отладка программного обеспечения 90
7 глава. Составление программной документации 92
Заключение 94
Приложение А 95
Список литературы 97
Введение
С каждым годом все более совершенствуются и усложняются автоматизированные технические и технологические системы и комплексы. Современные системы управления снабжаются высокотехнологичным компьютерным оборудованием, а к современным специализированным программным продуктам, предназначенным для обеспечения их функционирования, предъявляются повышенные требования. В этих условиях специалист по автоматизации и информатизации в системах управления должен на хорошем профессиональном уровне владеть знаниями в области проектирования и реализации программного обеспечения.
Дисциплина «Технологии программирования» включена в учебный план специальности «Автоматизация и управление» с целью ознакомить будущих специалистов по автоматизации с современными тенденциями развития технологий программирования, а также основными принципами и технологиями разработки программного обеспечения. Настоящее учебное пособие адаптировано для студентов младших курсов специальности и предназначено в помощь при освоении основных разделов дисциплины. Кроме того, пособие будет полезно студентам старших курсов при выполнении курсовых и дипломных работ.
Изложение материала учебного пособия строится в соответствии с рабочей программой одноименной дисциплины, читаемой в Алматинском университете энергетики и связи для специальности 5B070200 – «Автоматизация и управление».
В первой главе рассматриваются основные понятия и подходы к технологии программирования. Вторая глава посвящена особенностям разработки сложного программного обеспечения. В третьей главе анализируются требования и исходные данные к разработке программного обеспечения. В четвертой главе рассматриваются вопросы проектирования программного обеспечения при различных подходах. Пятая глава описывает особенности пользовательских интерфейсов. Шестая глава посвящена тестированию и отладке программных продуктов, а седьмая – вопросам документирования программного обеспечения.
В учебном пособии не рассматриваются вопросы программирования на конкретном языке.
Материал сопровождается сравнительно простыми примерами, иллюстрациями и таблицами.
1 глава. Введение в технологию программирования. Основные понятия и подходы
1.1 Понятие технологии программирования и ее роль
Под технологией программирования понимают совокупность методов и средств, используемых в процессе разработки программного обеспечения [16]. Она представляет собой набор технологических инструкций, включающих:
1) указание последовательности выполнения технологических операций;
2) перечисление условий, при которых выполняются операции;
3) описания самих операций с определением исходных данных, результатов, инструкций, нормативов, стандартов, критериев и методов оценки.
4) определяет способ описания проектируемой системы (модели), используемой на конкретном этапе разработки.
Различают технологии, используемые на конкретных этапах разработки, в основе которых лежит ограниченно применимый метод, и технологии, охватывающие несколько этапов разработки, в основе которых лежит базовый метод или методология.
В литературе имеются и другие, несколько отличающиеся, определения технологии программирования [14]. Кроме того, используется близкое к технологии программирования понятие программной инженерии (software engineering), определяемой как систематический подход к разработке, эксплуатации, сопровождению и изъятию из обращения программных средств.
Главное различие между технологией программирования и программной инженерией как дисциплинами для изучения заключается в способе рассмотрения и систематизации материала. В технологии программирования акцент делается на изучении технологических процессов разработки программного обеспечения, при этом методы и инструментальные средства разработки используются для формирования этих процессов. Тогда как в программной инженерии изучаются различные методы и инструментальные средства разработки программного обеспечения с точки зрения достижения определенных целей.
1.2 Основные этапы развития технологии программирования
Среди основных этапов развития технологий программирования выделяют «стихийное» программирование, структурный, объектный и компонентный подходы к программированию [16].
1.2.1 Этап «стихийного» программирования.
Характерной особенностью периода от момента появления первых ЭВМ до середины 60-х годов XX века является то, что сформулированные технологии программирования практически отсутствовали, а само программирование было искусством.
В 50-е годы мощность компьютеров (первого поколения) была невелика, а программирование для них велось, в основном, в машинном коде. Решались, главным образом, научно-технические задачи, а задание на программирование содержало, как правило, достаточно точную постановку задачи. Первые программы имели простейшую структуру: программа на машинном языке и обрабатываемые данные. Сложность программ в машинных кодах ограничивалась способностью программиста одновременно мысленно отслеживать последовательность выполняемых операций и местонахождение данных при программировании. Использовалась интуитивная технология программирования: почти сразу приступали к составлению программы по заданию, при этом часто задание несколько раз изменялось, что сильно увеличивало время процесса составления программы, а минимальная документация оформлялась уже после того, как программа начинала работать.
В результате появления ассемблеров вместо двоичных кодов стали использовать символические имена данных и мнемоники кодов операций, а программы стали более «читаемыми». Именно в этот период зародилась ставшая впоследствии фундаментальной для технологии программирования концепция модульного программирования [14], ориентированная на преодоления трудностей программирования в машинном коде. Создание языков программирования высокого уровня (FORTRAN, ALGOL) существенно упростило программирование вычислений, снизив уровень детализации операций, что позволило увеличить сложность программ. Из первых языков модульного программирования сохранился только FORTRAN благодаря грандиозной библиотеке накопленных программных модулей.
В результате появления средств, позволяющих оперировать подпрограммами, были созданы огромные библиотеки расчетных и служебных подпрограмм. Типичная программа состояла из основной программы, области глобальных данных и набора подпрограмм (см. рисунок 1.1а). Однако при увеличении количества подпрограмм возрастала вероятность искажения части глобальных данных какой-либо подпрограммой, поэтому было предложено размещать в них локальные данные (см. рисунок 1.1б), а появление новых средств поддержки подпрограмм позволило разрабатывать программное обеспечение нескольким программистам параллельно.
Рисунок 1.1 - Архитектура программ с глобальной и локальной областями данных
В начале 60-х годов XX века разразился «кризис программирования»: разработчики сложного программного обеспечения срывали все сроки завершения проектов: проект устаревал раньше, чем был готов к внедрению, его стоимость увеличивалась, в результате многие проекты так никогда и не были завершены. Все это было вызвано несовершенством технологии программирования. Использование разработки «снизу-вверх» при отсутствии четких моделей описания подпрограмм и методов проектирования превращало создание программ в непростую задачу. Интерфейсы программ получались сложными, а при сборке программного продукта выявлялось большое количество ошибок согласования, исправление которых требовало серьезного изменения уже разработанных частей программ. При этом в программу часто вносились новые ошибки, в результате чего процесс тестирования и отладки программ занимал более 80% времени разработки, если вообще когда-нибудь заканчивался. Анализ причин возникновения ошибок позволил сформулировать новый подход к программированию - структурный.
1.2.2 Этап структурного программирования.
Структурный подход к программированию, который развивался на втором этапе развития технологий в 60-70 годы XX века, представляет собой совокупность рекомендуемых технологических приемов, охватывающих выполнение всех этапов разработки программного обеспечения. В его основе лежит декомпозиция сложных систем с целью последующей реализации в виде отдельных небольших (до 40-50 операторов) подпрограмм, позже названная процедурной декомпозицией. Структурный подход требовал представления задачи в виде иерархии подзадач простейшей структуры, а проектирование осуществлялось «сверху-вниз» и подразумевало реализацию общей идеи. Были введены ограничения на конструкции алгоритмов, рекомендованы формальные модели их описания, а также специальный метод проектирования алгоритмов - метод пошаговой детализации. Принципы структурного программирования были заложены в основу процедурных языков программирования, которые включали основные «структурные» операторы передачи управления, поддерживали вложение подпрограмм, локализацию и ограничение области «видимости» данных (PL/1, ALGOL-68, Pascal, С). Дальнейший рост сложности и размеров разрабатываемого программного обеспечения потребовал развития структурирования данных, в языках появляется возможность определения пользовательских типов данных [1].
Стремление разграничить доступ к глобальным данным программы дало толчок к появлению и развитию технологии модульного программирования (см. рисунок 1.2), что предполагало выделение групп подпрограмм, использующих одни и те же глобальные данные в отдельно компилируемые модули (библиотеки).
Связи между модулями осуществлялись через специальный интерфейс, в то время как доступ к реализации модуля (телам подпрограмм и некоторым «внутренним» переменным) был запрещен. Эту технологию поддерживают современные версии Pascal, С, C++, Ада и Modula.
Рисунок 1.2 – Архитектура программы при структурном подходе
Разработка программ несколькими программистами существенно упростилась: модули разрабатывались независимо друг от друга и могли использоваться без изменений в других разработках, а их взаимодействие обеспечивалось через специально оговоренные межмодульные интерфейсы. Структурный подход в сочетании с модульным программированием позволяет получать надежные программы, размером не более 100 000 операторов. Существенным недостатком является тот факт, что ошибка в интерфейсе при вызове подпрограммы выявляется только при выполнении программы (из-за раздельной компиляции модулей), а при увеличении размера программы возрастает сложность межмодульных интерфейсов, поэтому предусмотреть взаимовлияние отдельных частей программы становится практически невозможно. Поэтому для разработки программного обеспечения большого объема было предложено использовать объектный подход.
1.2.3 Этап объектного программирования.
На третьем этапе (80-е - 90-е годы XX века) был сформирован объектный подход к программированию.
Вообще говоря, 80-е годы характеризуются широким внедрением персональных компьютеров во все сферы человеческой деятельности и тем самым созданием обширного и разнообразного контингента пользователей программного обеспечения. Это привело к бурному развитию пользовательских интерфейсов и созданию четкой концепции качества программного обеспечения [14]. Развиваются методы и языки спецификации. Начинается бурный процесс стандартизации технологических процессов и, прежде всего, документации, создаваемой в этих процессах. Развивается концепция компьютерных сетей. На этом фоне и создаются предпосылки к формированию совершенно нового подхода к разработке сложного программного обеспечения с интуитивно понятным и удобным пользовательским интерфейсом.
Технология создания сложного программного обеспечения, основанная на представлении программы в виде совокупности взаимодействующих путем передачи сообщений программных объектов, каждый из которых является экземпляром определенного класса, а классы образуют иерархию с наследованием свойств, была названа объектно-ориентированным программированием [16]. Объектная структура программы (см. рисунок 1.3) впервые была использована в языке имитационного моделирования сложных систем Simula, а затем использована в новых версиях универсальных языков программирования таких, как Pascal, C++, Modula, Java.
Рисунок 1.3 – Архитектура программы при объектно-ориентированном программировании
Достоинством объектно-ориентированного программирования является «естественная» декомпозиция программного обеспечения, существенно облегчающая разработку. Это приводит к более полной локализации данных и интегрированию их с подпрограммами обработки, что позволяет вести практически независимую разработку отдельных объектов программы. Кроме того, объектный подход предлагает новые способы организации программ, основанные на механизмах наследования, полиморфизма, композиции, наполнения, позволяющих конструировать из простых объектов сложные. В результате существенно увеличивается показатель повторного использования кодов и появляется возможность создания библиотек классов.
На основе объектного подхода были созданы среды, поддерживающие визуальное программирование (Delphi, C++ Builder, Visual C++), при использовании которого некоторая часть будущего продукта проектируется с применением визуальных средств добавления и настройки специальных библиотечных компонентов. В результате появляется заготовка будущей программы, в которую уже внесены коды.
Использование объектного подхода имеет много преимуществ. Однако его конкретная реализация в объектно-ориентированных языках программирования таких, как Pascal и C++, имеет существенные недостатки: отсутствуют стандарты компоновки двоичных результатов компиляции объектов в единое целое даже в пределах одного языка программирования; изменение в реализации одного программного объекта связано с перекомпиляцией модуля и перекомпоновкой всего программного обеспечения, использующего данный объект. Таким образом, сохраняется объективная зависимость модулей программного обеспечения от адресов экспортируемых полей и методов, а также структур и форматов данных. Связи модулей нельзя разорвать, но можно стандартизировать их взаимодействие, на чем и основан компонентный подход к программированию.
1.2.4 Компонентный подход и CASE-технологии.
Широким охватом всего человеческого общества международной компьютерной сетью знаменательны 90-е годы XX века. Персональные компьютеры стали подключаться к сети как терминалы, что поставило ряд проблем регулирования доступа к информации компьютерных сетей как технологического, так и юридического и этического характера. Остро встала проблема защиты компьютерной информации и передаваемых по сети сообщений. Начался решающий этап полной информатизации и компьютеризации общества. Четвертый этап развития технологий программирования - компонентный подход и CASE-технологии - не завершился до настоящего времени.
Компонентный подход предполагает построение программного обеспечения из отдельных компонентов, которые взаимодействуют между собой через стандартизованные двоичные интерфейсы. В отличие от обычных объектов объекты-компоненты можно собрать в динамически вызываемые библиотеки или исполняемые файлы, распространять в двоичном виде (без исходных текстов) и использовать в любом языке программирования, поддерживающем соответствующую технологию [16]. Компонентный подход лежит в основе технологий, разработанных на базе COM (Component Object Model - компонентная модель объектов), и технологии создания распределенных приложений CORBA (Common Object Request Broker Architecture - общая архитектура с посредником обработки запросов объектов), которые используют сходные принципы и различаются лишь особенностями реализации.
Кроме того, отличительной особенностью современного этапа развития технологии программирования, является создание и внедрение автоматизированных технологий разработки и сопровождения программного обеспечения, которые были названы CASE-технологиями (Computer-Aided Software/System Engineering - разработка программного обеспечения/программных систем с использованием компьютерной поддержки). Без средств автоматизации разработка достаточно сложного программного обеспечения на настоящий момент становится трудно осуществимой: память человека уже не в состоянии фиксировать все детали, которые необходимо учитывать при разработке программного обеспечения. CASE-технологии поддерживают как структурный, так и объектный (компонентный) подходы к программированию [7].
1.3 Краткий обзор наиболее известных технологий
1.3.1 Технология СОМ.
Технология СОМ фирмы Microsoft является развитием технологии OLE I (Object Linking and Embedding - связывание и внедрение объектов), которая использовалась в ранних версиях Windows для создания составных документов. Она определяет общую концепцию взаимодействия программ любых типов (библиотек, приложений, операционной системы), т. е. позволяет одной части программного обеспечения использовать функции (службы), предоставляемые другой (см. рисунок 1.4).
Рисунок 1.4 – Компонентный подход. Технология СОМ
Модификация СОМ, обеспечивающая передачу вызовов между компьютерами, называется DCOM (Distributed COM - распределенная СОМ).
Приложение предоставляет свои службы, используя специальные объекты - объекты СОМ (экземпляры классов СОМ). Объект СОМ включает поля и методы, но в отличие от обычных, каждый объект СОМ может реализовывать несколько интерфейсов, обеспечивающих доступ к его полям и функциям за счет организации отдельной таблицы адресов методов для каждого интерфейса.
Классы СОМ поддерживают наследование интерфейсов, но не поддерживают наследования реализации, т. е. не наследуют код методов.
Объект всегда функционирует в составе сервера - динамической библиотеки или исполняемого файла, которые обеспечивают функционирование объекта. Различают три типа серверов: внутренний, локальный и удаленный (например, MS Word является локальным сервером). Для обращения к службам клиент должен получить указатель на соответствующий интерфейс. Взаимодействие клиента и сервера обеспечивается базовыми механизмами СОМ или DCOM, поэтому клиенту безразлично местонахождение объекта. При использовании локальных и удаленных серверов в адресном пространстве клиента создается proxy-объект - заместитель объекта СОМ, а в адресном пространстве сервера - СОМ-заглушка, соответствующая клиенту. Получив задание от клиента, заместитель упаковывает его параметры и, используя службы операционной системы, передает вызов заглушке. Заглушка распаковывает задание и передает его объекту СОМ. Результат возвращается клиенту в обратном порядке.
На базе технологии СОМ и ее распределенной версии DCOM были разработаны компонентные технологии, решающие различные задачи разработки программного обеспечения [16]. На возможностях COM базируется технология COM+, которая обеспечивает поддержку распределенных приложений на компонентной основе и предназначена для поддержки систем обработки транзакций [41].
Кроме того, к технологиям, реализующим компонентный подход, заложенный в СОМ, относятся:
а) 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 - сервер многозвенных распределенных приложений) - технология, организующая доступ к данным разных компьютеров с учетом балансировки нагрузки сети.
1.3.2 Технология CORBA.
Технология CORBA, разработанная группой компаний OMG (Object Management Group - группа внедрения объектной технологии программирования), реализует подход аналогичный СОМ на базе объектов и интерфейсов CORBA.
Программное ядро CORBA реализовано для всех основных аппаратных и программных платформ, и потому технологию можно использовать для создания распределенного программного обеспечения в разнородной вычислительной среде. Организация взаимодействия между объектами клиента и сервера в CORBA осуществляется с помощью посредника (VisiBroker) и специализированного программного обеспечения.
К сожалению, в силу ряда причин разработчики были вынуждены отказаться от этой технологии [39]. Сегодня CORBA, главным образом, используется для связывания компонентов, выполняемых внутри корпоративных сетей, в которых коммуникации защищаются брандмауэрами от внешнего мира. Технология CORBA используется также при разработке систем реального времени и встроенных систем, секторе, в котором CORBA действительно развивается. Однако в целом CORBA находится в упадке, и теперь ее нельзя назвать никак иначе, кроме как нишевой технологией.
2 глава. Особенности разработки сложных программных систем
2.1 Основные принципы разработки
Большинство современных программных систем являются достаточно сложными. Эта сложность обуславливается многими причинами, главной из которых является логическая сложность решаемых ими задач.
Раньше компьютеры применяли в очень узких областях науки и техники, в первую очередь там, где задачи были хорошо детерминированы и требовали значительных вычислений. Сейчас, когда созданы мощные компьютерные сети, появилась возможность переложить на них решение сложных ресурсоемких задач, о компьютеризации которых раньше не задумывались. В процесс компьютеризации вовлекаются новые предметные области, а для освоенных областей усложняются уже сложившиеся постановки задач. Сложность разработки программных систем увеличивается за счет сложности формального определения требований к этим системам, отсутствия удовлетворительных средств описания поведения дискретных систем с большим числом состояний при недетерминированной последовательности входных воздействий, коллективной разработки, необходимости увеличения степени повторяемости кодов. Однако все эти факторы напрямую связаны со сложностью объекта разработки - программной системы [32].
Подавляющее большинство сложных систем как в природе, так и в технике имеет иерархическую внутреннюю структуру. Связи элементов сложных систем различны как по типу, так и по силе, что и позволяет рассматривать эти системы как некоторую совокупность взаимозависимых подсистем. Внутренние связи элементов таких подсистем сильнее, чем связи между подсистемами. Например, компьютер состоит из процессора, памяти и внешних устройств, а Солнечная система включает Солнце и планеты, вращающиеся вокруг него. Используя то же различие связей, каждую подсистему можно аналогично разделить на подсистемы до «элементарного» уровня, причем выбор уровня, компоненты которого следует считать элементарными, остается за исследователем. На элементарном уровне система, состоит из немногих типов подсистем, по-разному скомбинированных и организованных. Иерархии такого типа получили название «целое-часть».
В природе существует еще один вид иерархии - иерархия «простое-сложное» или иерархия развития (усложнения) систем в процессе эволюции. В этой иерархии любая функционирующая система является результатом развития более простой системы. Именно этот вид иерархии реализуется механизмом наследования объектно-ориентированного программирования.
Будучи отражением природных и технических систем, программные системы являются иерархическими и обладают описанными выше свойствами. На этих свойствах иерархических систем строится блочно-иерархический подход к их исследованию или созданию, предполагающий сначала создание частей объекта (блоков и модулей), а затем сборку из них самого объекта.
Процесс разбиения сложного объекта на сравнительно независимые части получил название декомпозиции. При декомпозиции учитывают, что связи между отдельными частями должны быть слабее, чем связи элементов внутри частей. Чтобы из полученных частей можно было собрать разрабатываемый объект, в процессе декомпозиции необходимо определить все виды связей частей между собой.
При создании сложных объектов процесс декомпозиции выполняется многократно: каждый блок, в свою очередь, декомпозируют на части, пока не получают блоки, которые сравнительно легко разработать. Этот метод разработки получил название пошаговой детализации. В процессе декомпозиции стараются выделить аналогичные блоки, которые можно было бы разрабатывать на общей основе. Таким образом, обеспечивают увеличение степени повторяемости кодов и, соответственно, снижение стоимости разработки.
Результат декомпозиции обычно представляют в виде схемы иерархии, на нижнем уровне которой располагают сравнительно простые блоки, а на верхнем - объект, подлежащий разработке [16]. На каждом иерархическом уровне описание блоков выполняют с определенной степенью детализации, абстрагируясь от несущественных деталей. Как правило, для объекта в целом, удается сформулировать лишь общие требования, а блоки нижнего уровня должны быть специфицированы таким образом, чтобы из них действительно можно было собрать работающий объект. Другими словами, чем больше блок, тем более абстрактным должно быть его описание (см. рисунок 2.1).
Рисунок 2.1 – Соотношение абстрактного и конкретного в описании блоков
при блочно-иерархическом подходе
При соблюдении этого принципа разработчик сохраняет возможность осмысления проекта и принимает наиболее правильные решения на каждом этапе, что называют локальной оптимизацией (в отличие от глобальной оптимизации характеристик объектов, которая для действительно сложных объектов не всегда возможна).
Итак, в основе блочно-иерархического подхода лежат иерархическое упорядочение и декомпозиция.
Важную роль играют следующие принципы:
а) непротиворечивость - контроль согласованности элементов;
б) полнота - контроль на присутствие лишних элементов;
в) формализация - строгость методического подхода;
г) повторяемость -
необходимость выделения одинаковых блоков для
удешевления и
ускорения разработки;
д) локальная оптимизация - оптимизация в пределах уровня иерархии.
Совокупность языков моделей, постановок задач, методов описаний некоторого иерархического уровня принято называть уровнем проектирования. Различные взгляды на объект проектирования принято называть аспектами проектирования.
Достоинства блочно-иерархического подхода:
1) возможность создания сложных систем;
2) упрощение проверки работоспособности отдельных блоков и системы в целом;
3) обеспечение возможности модернизации систем.
Использование блочно-иерархического подхода применительно к программным системам стало возможным только после конкретизации общих положений подхода и внесения изменений в процесс проектирования. При этом структурный подход учитывает только свойства иерархии «целое - часть», а объектный дополнительно использует свойства иерархии «простое - сложное».
2.2 Жизненный цикл программного обеспечения
2.2.1 Состав процессов жизненного цикла программного обеспечения.
Жизненным циклом программного обеспечения называется период от момента появления идеи создания некоторого программного обеспечения до момента завершения его поддержки фирмой-разработчиком или фирмой, выполняющей сопровождение [32].
Жизненный цикл охватывает довольно сложный процесс создания и использования ПО (software process). Этот процесс может быть организован по-разному для разных классов ПО и в зависимости от особенностей коллектива разработчиков.
Состав процессов жизненного цикла регламентируется международным стандартом ISO/IEC 12207: 1995 «Information Technologe - Software Life Cycle Processes» («Информационные технологии - Процессы жизненного цикла программного обеспечения»). В стандарте описывается структура жизненного цикла программного обеспечения, определяются его процессы, не конкретизируя в деталях их реализацию.
Процесс жизненного цикла – это совокупность взаимосвязанных действий, преобразующих некоторые входные данные в выходные. На рисунке 2.2 представлены процессы жизненного цикла по указанному стандарту. Согласно этой структуре процессы разработки и сопровождения программного обеспечения относятся к основным процессам [16]. Условно выделяют следующие основные этапы разработки программного обеспечения:
а) постановка задачи - формулируется назначение программного обеспечения, а также определяются основные требования к нему (функциональные и эксплуатационные). Результатами являются техническое задание, фиксирующее принципиальные требования, и принятие основных проектных решений;
б) анализ требований и разработка спецификаций - выполняется анализ требований технического задания, формулируется содержательная постановка задачи, строится модель предметной области, определяются подзадачи и выбираются или разрабатываются методы их решения, формируются тесты для поиска ошибок в проектируемом программном обеспечении с указанием ожидаемых результатов, т.е. разрабатывается общая логическая модель проектируемого программного обеспечения;
в) проектирование - определяются подробные спецификации разрабатываемого программного продукта, выполняется проектирование общей структуры, декомпозиция компонентов и проектирование компонентов. Результат - детальная модель разрабатываемого ПО со спецификациями компонентов всех уровней.
г) реализация - процесс поэтапного написания кодов программы на выбранном языке программирования (кодирование), их тестирование и отладка.
Рисунок 2.2 – Структура процессов жизненного цикла программного обеспечения
Сопровождение - это процесс создания и внедрения новых версий программного обеспечения.
Причинами выпуска новых версий могут служить:
- необходимость исправления ошибок, выявленных в процессе эксплуатации предыдущих версий;
- необходимость совершенствования предыдущих версий (улучшение интерфейса, расширение состава выполняемых функций или повышение его производительности);
- изменение среды функционирования, (появление новых технических средств и/или программных продуктов, с которыми взаимодействует сопровождаемое программное обеспечение);
- в программный продукт вносят необходимые изменения, которые могут потребовать пересмотра уже принятых проектных решений.
С изменением модели жизненного цикла ПО роль этого этапа существенно возросла, так как продукты теперь создаются итерационно: сначала выпускается сравнительно простая версия, затем следующая с большими возможностями, затем следующая и т. д. Поэтому в соответствии со стандартом ISO/IEC 12207 этап сопровождения был выделен в отдельный процесс жизненного цикла.
2.2.2 Модели жизненного цикла программного обеспечения.
На протяжении последних тридцати лет в программировании сменились несколько моделей жизненного цикла программного обеспечения [14]. Каждой из моделей соответствует определенная стратегия конструирования ПО [25]. Модели в процессе эволюции усложнялись и совершенствовались.
В 1970 году Уинстон Ройс предложил схему разработки, которая активно использовалась в течение последующих 15 лет (1970-1985). Каскадная схема разработки ПО предполагала, что переход на следующую стадию осуществляется только после того, как полностью будут завершены проектные операции предыдущей стадии и получены все исходные данные для следующей стадии (см. рисунок 2.3).
Рисунок 2.3 – Каскадная схема разработки программного обеспечения
Эту модель в разных источниках часто называют классическим жизненным циклом [25] или водопадной моделью [14].
Достоинствами такой схемы являются:
1) получение плана и временного графика по всем этапам проекта;
2) простота планирования процесса разработки;
3) получение в конце каждой стадии законченного набора проектной документации, отвечающего требованиям полноты и согласованности.
Именно эту схему используют обычно при блочно-иерархическом подходе к разработке сложных технических объектов, обеспечивая очень высокие параметры эффективности разработки.
Однако каскадная схема имеет недостатки:
1) реальные проекты часто требуют отклонения от стандартной последовательности шагов;
2) цикл основан на точной формулировке исходных требований к ПО;
3) результаты проекта доступны заказчику только в конце работы.
Схема оказалась применимой только к созданию систем, для которых в самом начале разработки удавалось точно и полно сформулировать все требования, что уменьшало вероятность возникновения в процессе разработки проблем, связанных с принятием неудачного решения на предыдущих стадиях. На практике такие разработки встречается крайне редко.
Каскадной (водопадной) схеме соответствует стратегия конструирования называемая однократным проходом или водопадной стратегией.
Реальный же процесс носит итерационный характер. Достаточно часто заказчик не может сформулировать подробные требования по вводу, обработке или выводу данных для будущего программного продукта. С другой стороны, разработчик может сомневаться в возможности приспособления продукта под операционную систему, в форме диалога с пользователем или в эффективности реализуемого алгоритма. В этих случаях используется макетирование, основная цель которого - снять неопределенности в требованиях заказчика.
При макетировании модель может принимать одну из трех форм:
1) бумажный макет или макет на основе компьютера (изображается человеко-машинный диалог);
2) работающий макет (выполняется некоторая часть требуемых функций);
3) существующая программа (впоследствии характеристики программы должны быть улучшены).
Макетирование основывается на многократном повторении итераций, в которых участвуют заказчик и разработчик (см. рисунок 2.4).
Макетирование начинается со сбора и уточнения требований к программе. Разработчик и заказчик встречаются и определяют все цели ПО, устанавливают, какие требования известны, а какие предстоит доопределить. Затем выполняется быстрое проектирование, причем внимание сосредотачивается на тех характеристиках программного обеспечения, которые должны быть видимы пользователю. Быстрое проектирование приводит к построению макета.
Рисунок 2.4 - Макетирование
Макет оценивается заказчиком и используется для уточнения требований к программному обеспечению. Итерации повторяются до тех пор, пока макет не выявит все требования заказчика и, тем самым, не даст возможность разработчику понять, что должно быть сделано.
Несомненным достоинством макетирования является то, что оно обеспечивает определение полных требований к программному продукту.
Однако, когда заказчик видит работающую версию программного продукта, он перестает осознавать, что это всего лишь макет, который далек от законченного программного продукта. При этом в погоне за работающим вариантом остаются нерешенными вопросы качества и удобства сопровождения программного обеспечения. Кроме того, разработчик так же как и заказчик может принять макет за продукт. Желаемое принимается за действительное.
С другой стороны, для быстрого получения работающего макета разработчик часто идет на определенные компромиссы. Могут использоваться не самые подходящие язык программирования или операционная система. Для простой демонстрации возможностей может применяться неэффективный алгоритм. Спустя некоторое время при разработке финишной версии разработчик забывает о причинах, по которым эти средства не подходят. В результате далеко не идеальный выбранный вариант интегрируется в систему.
Аналогичная схема, поддерживающая итерационный характер процесса разработки, была названа моделью с промежуточным контролем (см. рисунок 2.5).
Контроль, выполняемый по данной схеме после завершения каждого этапа, позволяет вернуться на любой уровень и внести изменения. Основная опасность использования такой схемы связана с тем, что разработка никогда не будет завершена, постоянно находясь в состоянии уточнения и усовершенствования.
Сочетание элементов последовательной водопадной модели с итерационной философией макетирования позволило получить инкрементную модель [25], которая соответствует инкрементной стратегии конструирования.
Рисунок 2.5 – Схема разработки программного обеспечения с промежуточным контролем
Инкрементная модель в отличие от макетирования позволяет получать на каждой итерации работающий продукт. Примерами современной реализации инкрементного подхода могут служить технология быстрой разработки приложений (RAD-технология) и экстремальное программирование ХР, предложенное Кентом Беком в 1999 году [5].
В конце 1980-х годов Германией и США независимо друг от друга была разработана концепция V-образной модели - вариации каскадной модели, в которой задачи разработки идут сверху вниз по левой стороне буквы V, а задачи тестирования — вверх по правой стороне буквы V (см. рисунок 2.6). Внутри V проводятся горизонтальные линии, показывающие, как результаты каждой из фаз разработки влияют на развитие системы тестирования на каждой из фаз тестирования.
Основной принцип V-образной модели заключается в том, что детализация проекта возрастает при движении слева направо, одновременно с течением времени, и ни то, ни другое не может повернуть вспять. Итерации в проекте производятся по горизонтали, между левой и правой сторонами буквы.
Немецкая V-модель была разработана аэрокосмической компанией IABG в Оттобрунне для Министерства обороны Германии и летом 1992 была принята немецкой федеральной администрацией для гражданских нужд. Американская V-Model (VEE) была разработана национальным советом по системной инженерии для спутниковых систем, включая оборудование, программное обеспечение и взаимодействие с пользователями. Современной версией V-Model является V-Model XT, которая была утверждена в феврале 2005 года и используется для управления процессом разработки программного обеспечения для немецкой федеральной администрации. Сейчас она является стандартом для немецких правительственных и оборонных проектов, а также для производителей программного обеспечения в Германии. V-Model представляет собой скорее набор стандартов в области проектов, касающихся разработки новых продуктов.
Рисунок 2.6 – Схема разработки программного обеспечения с использованием V-образной модели
Несомненным достоинством V-модели является то, что пользователи сами участвуют в процессах разработки и поддержки. Комитет по контролю за изменениями поддерживает проект и собирается раз в год для обработки всех полученных запросов на внесение изменений в V-Model. На старте любого проекта V-образная модель может быть адаптирована под этот проект. В модели особое значение придается планированию, направленному на верификацию и аттестацию разрабатываемого продукта на ранних стадиях его разработки. В V-образной модели определение требований выполняется перед разработкой проекта системы, а проектирование программного обеспечения - перед разработкой компонентов. Модель определяет продукты, которые должны быть получены в результате процесса разработки, причем каждые полученные данные должны подвергаться тестированию.
Несмотря на указанные достоинства, V-модель не предусматривает работу с параллельными событиями; не позволяет вносить требования динамических изменений на разных этапах жизненного цикла; тестирование требований в жизненном цикле происходит слишком поздно, а некоторый результат можно посмотреть только при достижении низа буквы V.
Для преодоления проблем моделей итеративной разработки в 1988 году Барри Боэмом была предложена спиральная схема (см. рисунок 2.7).
Спиральная модель базируется на лучших свойствах классического жизненного цикла и макетирования, к которым добавляется новый элемент — анализ риска. В соответствии с приведенной выше схемой программное обеспечение создается не сразу, а итерационно с использованием метода прототипирования.
Рисунок 2.7 – Спиральная схема разработки программного обеспечения
Метод базируется на создании прототипов - действующих программных продуктов, реализующих отдельные функции и внешние интерфейсы разрабатываемого программного обеспечения. Создание программного обеспечения выполняется в несколько итераций:
а) I итерация: специфицируется, проектируется, реализуется и тестируется интерфейс пользователя;
б) II итерация: добавляется некоторый ограниченный набор функций;
в) III … N- итерации: расширяется функционал продукта.
На каждом витке спирали проводится анализ риска. Если анализ риска показывает неопределенность требований, на помощь разработчику и заказчику приходит макетирование (используемое на этапе проектирования). Для дальнейшего определения проблемных и уточненных требований может быть использовано моделирование. Заказчик оценивает инженерную (конструкторскую) работу и вносит предложения по модификации. Следующая фаза планирования и анализа риска базируется на предложениях заказчика. В каждом цикле по спирали результаты анализа риска формируются в виде «продолжать, не продолжать». Если риск слишком велик, проект может быть остановлен.
Достоинство схемы: начиная с некоторой итерации, на которой обеспечена определенная функциональная полнота, продукт можно предоставлять пользователю, что позволяет:
1) сократить время до появления первых версий программного продукта;
2) заинтересовать большое количество пользователей, обеспечивая быстрое продвижение следующих версий продукта на рынке;
3) ускорить формирование и уточнение спецификаций за счет появления практики использования продукта;
4) уменьшить вероятность морального устаревания системы за время разработки.
Основной проблемой использования схемы является определение моментов перехода на следующие стадии, для чего ограничивают сроки прохождения каждой стадии, основываясь на экспертных оценках.
Спиральная модель является классическим примером применения эволюционной стратегии конструирования.
Развитием спиральной модели является компонентно-ориентированная модель, которая также основывается на эволюционной стратегии конструирования. В этой модели конкретизируется содержание этапа проектирования: в современных условиях новая разработка должна основываться на повторном использовании существующих программных компонентов.
Программные компоненты, созданные в реализованных программных проектах, хранятся в библиотеке. В новом программном проекте, исходя из требований заказчика, выявляются кандидаты в компоненты. Далее проверяется наличие этих кандидатов в библиотеке. Если они найдены, то компоненты извлекаются из библиотеки и используются повторно. В противном случае создаются новые компоненты, они применяются в проекте и включаются в библиотеку.
Достоинства компонентно-ориентированной модели:
1) уменьшает на 30% время разработки программного продукта;
2) уменьшает стоимость программной разработки до 70%;
3) увеличивает в 1,5 раза производительность разработки.
Альтернативой спиральной и каскадной моделям жизненного цикла является модель хаоса (Raccoon, 1995), которая предполагает, что фазы жизненного цикла распространяются на все уровни проекта: от всего проекта в целом до отдельной строки кода. Это означает, что проект, все его системы, модули, функции и строки кода должны быть определены, реализованы и интегрированы. Главное правило - всегда решать наиболее важную задачу первой [40].
2.2.3 Использование CASE-технологий при разработке.
Изменение жизненного цикла программного обеспечения стало возможным в результате использования при разработке программного обеспечения CASE-технологий.
CASE-технологии представляют собой совокупность методологий анализа, проектирования, разработки и сопровождения сложных программных систем, основанных как на структурном, так и на объектном подходах. В основу любой CASE-технологии положены методология, метод, нотация и средства [7].
Среди средств различают:
1) CASE-средства анализа требований, проектирования спецификаций и структуры, редактирования интерфейсов. Первое поколение CASE-I, в основном включают средства для поддержки графических моделей, проектирования спецификаций, экранных редакторов и словарей данных;
2) CASE-средства генерации исходных текстов и реализации интегрированного окружения поддержки полного жизненного цикла разработки программного обеспечения. Второе поколение CASE-II, существенно отличается большими возможностями, обеспечивая контроль, анализ и связывание системной информации и информации по управлению процессом проектирования, построение прототипов и моделей системы, тестирование, верификацию и анализ сгенерированных программ.
Современные CASE-средства позволяют:
- автоматизировать трудоемкие операции;
- существенно повысить производительность труда программистов;
- улучшить качество создаваемого программного обеспечения за счет обеспечения автоматизированного контроля совместимости спецификаций проекта;
- уменьшить время создания прототипа системы;
- ускорить процесс проектирования и разработки;
- автоматизировать формирование проектной документации для всех этапов жизненного цикла в соответствии с современными стандартами;
- частично генерировать коды программ для различных платформ разработки;
- применять технологии повторного использования компонентов системы;
- обеспечить возможность восстановления
проектной документации
по имеющимся исходным кодам.
Появление CASE-технологий изменило все этапы жизненного цикла программного обеспечения. При этом наибольшие изменения касаются анализа и проектирования, которые предполагают строгое и наглядное описание разрабатываемого программного обеспечения.
Однако современные CASE-средства дороги, а их использование требует более высокой квалификации разработчиков. Следовательно, имеет смысл использовать их в сложных проектах, причем, чем сложнее разрабатываемое программное обеспечение, тем больше выигрыш от использования CASE-технологий.
На сегодняшний день практически все промышленно производимое сложное программное обеспечение разрабатывается с использованием CASE-средств.
Разработка спиральной модели жизненного цикла программного обеспечения и CASE-технологии позволили сформулировать условия, выполнение которых сокращает сроки создания программного обеспечения.
2.3 Качество программного обеспечения
Для заказчика одной из важнейших характеристик программного обеспечения является качество программного продукта, поскольку именно это определяет насколько оправдаются вложенные в разработку ПО финансовые затраты. С точки же зрения разработчика немаловажно, чтобы разрабатываемый проект быстро и легко кодировался, тестировался, отлаживался и модифицировался.
Таким образом, качество проекта программного продукта, от которого зависят трудовые и материальные затраты на его реализацию и последующие модификации, называют технологичностью [16]. Высокая технологичность проекта особенно важна, если необходимо обеспечить повышенные требования к его качеству или разрабатывается программный продукт, рассчитанный на многолетнее интенсивное использование.
В настоящее время критериями качества программного обеспечения (criteria of software quality) принято считать [14]:
1) функциональность;
2) надежность;
3) легкость применения;
4) эффективность;
5) сопровождаемость;
6) мобильность.
Функциональность - это способность ПО выполнять набор функций, удовлетворяющих заданным или подразумеваемым потребностям пользователей.
Надежность – это способность программного обеспечения безотказно выполнять определенные функции при заданных условиях в течение заданного периода времени.
Легкость применения - это характеристики программного обеспечения, которые позволяют минимизировать усилия пользователя по подготовке исходных данных, использованию программы и оценке полученных результатов, а также вызывать положительные эмоции у пользователя.
Эффективность - это отношение уровня услуг, предоставляемых программным обеспечением пользователю при заданных условиях, к объему используемых ресурсов.
Сопровождаемость - это характеристика программного обеспечения, которая позволяет минимизировать усилия по внесению изменений для устранения в нем ошибок и по его модификации в соответствии с потребностями пользователей.
Мобильность - это способность программного обеспечения быть перенесенным из одной среды в другую, например, с одного компьютера на другой.
Функциональность и надежность являются обязательными критериями качества ПО. Остальные критерии используются в зависимости от потребностей пользователей в соответствии с требованиями к ПО.
Если рассматривать технологичность с позиций устройства общей структуры программного обеспечения, то в первую очередь следует обратить внимание на проработанность моделей, уровень независимости модулей, стиль программирования и степень повторного использования кодов.
2.4 Роль модулей в обеспечении технологичности
Как упоминалось ранее, при проектировании программного обеспечения выполняется разбиение сложной системы на простые части – декомпозиция. При этом в зависимости от используемого подхода к разработке применяются процедурный (структурный) или объектный способы декомпозиции.
Результатом процедурной декомпозиции является иерархия подпрограмм (процедур), где функции принятия решения реализуются подпрограммами верхних уровней, а обработка - подпрограммами нижних уровней. Результатом объектной декомпозиции является совокупность объектов, которые реализуются как переменные некоторых специально разрабатываемых типов.
При любом способе декомпозиции получают набор связанных с соответствующими данными подпрограмм, которые в процессе реализации организуют в модули - автономно компилируемые программные единицы. Каждый разработанный программный модуль может включаться в состав разных программ, если выполнены условия его использования, декларированные в документации по этому модулю. Поэтому программный модуль может рассматриваться и как средство борьбы со сложностью программ, и как средство борьбы с дублированием в программировании [25].
Первоначально, когда размер программ был невелик, и подпрограммы компилировались отдельно, под модулем понималась последовательность связанных фрагментов программы, обращение к которой выполняется по имени. Со временем, когда размер программ значительно вырос и появилась возможность создавать библиотеки ресурсов, под модулем стали понимать автономно компилируемый набор программных ресурсов. Данные модуль получает и/или возвращает через общие области памяти или параметры.
Однако не всякий программный модуль способствует упрощению программы. Выделить хороший с этой точки зрения модуль является серьезной творческой задачей. Для оценки приемлемости выделенного модуля Р. Хольтом были предложены следующие критерии:
1) хороший модуль снаружи проще, чем внутри;
2) хороший модуль проще использовать, чем построить.
Сложную проблему легче решить, разделив ее на управляемые части. Однако с увеличением количества модулей и уменьшением их размера растут и затраты времени на разработку программного обеспечения. Следовательно, должно существовать оптимальное количество модулей, которое приведет к минимальной стоимости разработки. Критерии Хольта точно отражают свойства, которыми должен обладать оптимальный модуль.
Принцип информационной закрытости (см. рисунок 2.8), предложенный Д. Парнасом в 1972 году, утверждает: «Содержание модулей должно быть скрыто друг от друга». Модуль должен определяться и проектироваться так, чтобы его содержимое (процедуры и данные) было недоступно тем модулям, которые не нуждаются в такой информации (клиентам).
Информационная закрытость означает следующее:
1) все модули независимы, обмениваются только информацией, необходимой для работы;
2) доступ к операциям и структурам данных модуля ограничен.
Информационная закрытость позволяет обеспечить возможность разработки модулей независимыми коллективами, а также легкость модификация системы.
Идеальный модуль играет роль «черного ящика», содержимое которого невидимо клиентам. Он прост в использовании, поскольку количество «ручек» и «органов управления» им невелико. Его легко развивать и корректировать в процессе сопровождения программной системы. Для обеспечения таких возможностей система внутренних и внешних связей модуля должна отвечать особым требованиям.
Рисунок 2.8 - Информационная закрытость модуля
Г. Майерс [23] предложил для оценки приемлемости программного модуля использовать более конструктивные его характеристики:
1) размер модуля;
2) прочность модуля;
3) сцепление с другими модулями;
4) рутинность модуля.
Размер модуля измеряется числом содержащихся в нем операторов или строк. Модуль не должен быть слишком маленьким или слишком большим. Маленькие модули приводят к громоздкой модульной структуре программы и могут не окупать накладных расходов, связанных с их оформлением. Большие модули неудобны для изучения и изменений, они могут существенно увеличить суммарное время повторных трансляций программы при отладке программы. Обычно рекомендуются программные модули размером от нескольких десятков до нескольких сотен операторов. Это вполне соответствует принципам Хольта.
Чем выше степень независимости модулей, тем
- легче разобраться в отдельном модуле и всей программе, тестировать, отлаживать и модифицировать ее;
- меньше вероятность появления новых ошибок при исправлении старых или внесении изменений в программу;
- проще организовать разработку программы группой программистов и легче ее сопровождать.
Степень независимости модулей оценивается двумя критериями: связностью (прочностью по Майерсу) и сцеплением.
Связность - мера прочности соединения функциональных и информационных объектов внутри одного модуля, т.е. степень взаимосвязи элементов, реализуемых одним модулем. Размещение сильно связанных элементов в одном модуле уменьшает межмодульные связи и взаимовлияние модулей. В то же время размещение сильно связанных элементов в разных модулях не только усиливает межмодульные связи, но и усложняет понимание их взаимодействия. Объединение слабо связанных элементов уменьшает технологичность модулей, так как такими элементами сложнее мысленно манипулировать. Различают следующие типы связности:
а) функциональная - все части модуля предназначены для выполнения одной функции;
б) информационная (последовательная) – выходные данные одной функции служат исходными данными для другой функции;
в) коммуникативная - функции, обрабатывают одни и те же данные;
г) процедурная - части модуля связаны порядком выполняемых ими действий, реализующих некоторый сценарий поведения;
д) временная – части модуля не связаны, но функции выполняются одновременно (параллельно);
е) логическая - базируется на объединении данных или функций в одну логическую группу;
ж) случайная (по совпадению) - связь между элементами мала или отсутствует.
Анализ таблицы 2.1 показывает, что целесообразно использовать функциональную, информационную (последовательную) и коммуникативную связности, поскольку именно они показывают наилучшие характеристики.
Таблица 2.1 - Характеристика типов связности модуля
Тип связности |
Сопровождаемость |
Роль модуля |
Функциональная |
лучшая
|
«черный ящик» |
Информационная (последовательная) |
не совсем «черный ящик» |
|
Коммуникативная |
«серый ящик» |
|
Процедурная |
худшая
|
«белый» или «просвечивающий ящик» |
Временная |
«белый ящик» |
|
Логическая |
||
Случайная (по совпадению) |
Сцепление - это мера взаимозависимости модулей, определяющая насколько хорошо модули отделены друг от друга. Модули независимы, если каждый из них не содержит никакой информации о другом модуле. Различают шесть типов сцепления модулей:
а) сцепление по данным - модули обмениваются данными в скалярных значениях. При небольшом количестве передаваемых параметров этот тип обеспечивает наилучшие технологические характеристики ПО;
б) сцепление по образцу - модули обмениваются данными, объединенными в структуры. Однако, уменьшается «прозрачность» связи между модулями, так как передаваемые данные «спрятаны» в структуры, а при изменении структуры необходимо модифицировать все использующие ее модули. Дает неплохие характеристики, но хуже, чем у предыдущего типа;
в) сцепление по управлению - один модуль посылает другому некоторый информационный объект (флаг или переключатель), предназначенный для управления внутренней логикой модуля. Такие настройки снижают наглядность взаимодействия модулей и обеспечивают худшие характеристики технологичности программ по сравнению с предыдущими типами;
г) сцепление по внешним ссылкам - модули ссылаются на один и тот же глобальный элемент данных;
д) сцепление по общей области данных - модули работают с общей областью данных. Считается недопустимым, поскольку программы, использующие данный тип сцепления, сложны для понимания при сопровождении ПО. Ошибка одного модуля, приводящая к изменению общих данных, может проявиться при выполнении другого модуля. При ссылке к данным в общей области модули используют конкретные имена, что уменьшает гибкость разрабатываемого ПО;
е) сцепление по содержимому - один модуль прямо ссылается на содержание другого модуля (не через его точку входа), что полностью противоречит блочно-иерархическому подходу. Отдельный модуль в этом случае уже не является блоком («черным ящиком»): его содержимое должно учитываться в процессе разработки другого модуля. Такой вид сцепления остается возможным для языков низкого уровня, например, Ассемблера.
Допустимыми считают первые три типа сцепления, использование остальных приводит к резкому ухудшению технологичности программ. Как правило, модули сцепляются между собой несколькими способами. Учитывая это, качество принято определять по типу сцепления с худшими характеристиками. Например, при использовании сцепления по данным и сцепления по управлению, определяющим считают сцепление по управлению.
И наконец, последняя характеристика по Майерсу - рутинность модуля, т.е. его независимость от предыстории обращений к нему.
Модуль называется рутинным, если результат обращения к нему зависит только от значений его параметров и не зависит от предыстории обращений к нему.
Модуль называется зависящим от предыстории, если результат обращения к нему зависит от внутреннего состояния этого модуля, изменяемого в результате предыдущих обращений к нему.
Майерс не рекомендует использовать зависящие от предыстории (непредсказуемые) модули, так как они провоцируют появление в программах «хитрых» (неуловимых) ошибок. Однако во многих случаях именно зависящий от предыстории модуль является лучшей реализаций информационно прочного модуля. Поэтому корректнее будет поступать согласно следующим рекомендациям [25]:
1) рутинный модуль допускается использовать, если это не приводит к плохим сцеплениям модулей;
2) зависящие от предыстории модули следует использовать только в случае, когда это необходимо для обеспечения параметрического сцепления;
3) зависимость в спецификации зависящего от предыстории модуля должна быть четко сформулирована так, чтобы поведение этого модуля было возможно прогнозировать при разных последующих обращениях к нему.
При рассмотрении модуля как библиотеки ресурсов выделяют библиотеки подпрограмм, реализующие функции, близкие по назначению, и библиотеки классов, реализующие близкие по назначению классы.
В качестве средства улучшения технологических характеристик библиотек ресурсов используют разделение тела модуля на интерфейсную часть и область реализации (в Паскале –Interface и Implementation, в C++ - h и cpp-файлы).
Интерфейсная часть содержит совокупность объявлений ресурсов (заголовков функций, имен переменных, типов, классов), предоставляемых другим модулям. Необъявленные ресурсы извне не доступны.
Область реализации содержит тела подпрограмм и внутренние ресурсы (подпрограммы, переменные, типы), используемые этими подпрограммами. При такой организации любые изменения реализации библиотеки, не затрагивающие ее интерфейс, не требуют пересмотра модулей, связанных с библиотекой, что улучшает технологичность модулей-библиотек.
2.5 Основные подходы к разработке программного обеспечения
2.5.1 Основные подходы и их особенности.
При проектировании, реализации и тестировании компонентов структуры программного обеспечения используются следующие основные подходы: восходящий, нисходящий и расширение ядра [30].
При использовании восходящего подхода сначала проектируются и реализуются компоненты нижнего уровня, затем предыдущего и т.д. По мере завершения тестирования и отладки компонентов осуществляется их сборка, причем компоненты нижнего уровня помещают в библиотеки компонентов. Для тестирования и отладки разрабатывают специальные тестирующие программы.
Однако этот подход имеет существенные недостатки:
- увеличивается вероятность несогласованности компонентов;
- появляются дополнительные расходы на проектирование и реализацию тестирующих программ, которые впоследствии будет невозможно использовать;
- интерфейс проектируется в последнюю очередь, что долго не позволяет продемонстрировать его заказчику.
При промышленном изготовлении программного обеспечения восходящий подход практически не используют.
Нисходящий подход предполагает, что проектирование и последующая реализация компонентов выполняется «сверху-вниз»: вначале проектируют компоненты верхних уровней иерархии, затем следующих и так далее до самых нижних уровней. В той же последовательности выполняют и реализацию компонентов. При программировании компоненты нижних не реализованных уровней заменяют специально разработанными отладочными модулями - «заглушками», что позволяет тестировать и отлаживать уже реализованную часть.
При использовании нисходящего подхода применяют иерархический, операционный и комбинированный методы определения последовательности проектирования и реализации компонентов, характерные особенности которых приведены в таблице 2.2.
Расширение ядра – это подход, который предполагает в первую очередь проектирование и реализацию некоторой основы – ядра программного обеспечения (например, структуры данных и связанные с ними функции), а затем – его наращивание с использованием методов нисходящего и восходящего подходов или их комбинации.
Методы восходящей и нисходящей разработок относятся к классическим. Их особенностью является требование, чтобы модульная структура программы была разработана до начала кодирования модулей, что полностью соответствует водопадному подходу к разработке программного обеспечения.
Таблица 2.2 – Методы разработки при нисходящем подходе
Метод |
Особенности метода |
Недостатки |
Иерархический |
Выполнение разработки строго по уровням. Исключения допускаются при наличии зависимости по данным. |
- большое количество достаточно сложных заглушек; - основная масса модулей разрабатывается и реализуется в конце работы над проектом, что затрудняет распределение человеческих ресурсов. |
Операционный |
Связывает последовательность разработки модулей с порядком их выполнения при запуске программы. |
- порядок выполнения модулей может зависеть от данных; - модули вывода результатов должны разрабатываться одними из первых, чтобы не проектировать сложную заглушку, обеспечивающую вывод результатов при тестировании; - при распределении человеческих ресурсов сложным является начало работ, пока не закончены все модули, находящиеся на так называемом критическом пути. |
Комбинированный |
Учитывает все факторы, влияющие на последовательность разработки: достижимость модуля, зависимость по данным, обеспечение возможности выдачи результатов, готовность вспомогательных модулей, наличие необходимых ресурсов. |
- сложные модули должны разрабатываться раньше простых, чтобы выявить в спецификациях возможные ошибки. |
Однако эти методы вызывают ряд возражений [14]: представляется сомнительным, чтобы до программирования модулей можно было разработать структуру программы достаточно точно и содержательно.
С целью устранения этого недостатка используются конструктивный и архитектурный подходы к разработке программ, в которых модульная структура формируется в процессе кодирования модулей.
Конструктивный подход представляет собой модификацию нисходящей разработки, при которой модульная структура программы формируется в процессе программирования модулей. Разработка программы при конструктивном подходе начинается с программирования головного модуля, исходя из спецификации программы в целом.
Архитектурный подход представляет собой модификацию восходящей разработки, при которой модульная структура программы также формируется в процессе программирования модуля. Но при этом цель разработки существенно изменяется: повышается уровень используемого языка программирования, а не разрабатывается конкретная программа. Для заданной предметной области выделяются типичные функции, каждая из которых может использоваться при решении разных задач в этой области. Обычно сначала выделяются и реализуются отдельными модулями более простые функции, а постепенно затем появляются модули, использующие ранее выделенные функции.
2.5.2 Парадигмы программирования.
В процессе эволюции технологии программирования в рамках традиционных подходов сформировались определенные исходные концептуальные схемы постановки проблем и их решения – парадигмы [24], определяющие стиль написания программ, а также образ мышления программиста. Каждая парадигма программирования имеет свой круг приверженцев и класс успешно решаемых задач. Кроме того, в каждой из них приняты разные приоритеты при оценке качества программирования, отличаются инструменты и методы работы
Впервые термин «парадигма программирования» применил в своих лекциях Р.Флойд - лауреат премии Тьюринга. По мнению Флойда, парадигмы программирования могут сочетаться, обогащая инструментарий программиста.
Точное определение термину дать проблематично, поскольку в литературных источниках можно встретить отличающиеся друг от друга мнения авторов. Наиболее емкое определение принадлежит Д. Спинеллису: «Понятие «парадигма» используется в программировании для определения семейства обозначений (нотаций), разделяющих общий способ (методику) реализации программ».
Общие парадигмы программирования, сложившиеся в самом начале эры компьютерного программирования, - парадигмы прикладного, теоретического и функционального программирования сохраняют свое лидерство до сих пор.
Более пятидесяти лет назад в сфере по организации вычислительных и информационных процессов получила популярность ведущая парадигма прикладного программирования на основе императивного управления и процедурно-операторного стиля построения программ.
По одной из существующих классификаций языки программирования можно разделить на следующие группы:
1) императивные (imperative), называемые также процедурными (procedural) или директивными (directive);
2) декларативные (declarative);
3) объектно-ориентированные (object-oriented).
Императивное программирование - это парадигма программирования, которая описывает процесс вычисления в виде инструкций, изменяющих состояние программы [28]. Императивная программа очень похожа на приказы, то есть это - последовательность команд, которые должен выполнить компьютер. Первыми императивными языками были машинные коды, инструкции которых были крайне просты, что снижало нагрузку на компьютеры, однако затрудняло написание крупных программ. В 1954 появился первый «человеческий» язык программирования, максимально приближенный к естественному, — FORTRAN (Дж. Бэкус, IBM), который является компилируемым и позволяет использовать именованные переменные, составные выражения, подпрограммы и многие другие элементы распространённых сейчас императивных языков. С тех пор семейство императивных языков пополнили:
- ALGOL (конец 1950-х), разработанный с целью упростить выражение математических алгоритмов и в дальнейшем послуживший базой для написания операционных систем для некоторых моделей компьютеров;
- COBOL (1960) и BASIC (1964), появившиеся в результате попыток сделать программирование более похожим на обычный английский язык;
- а также Pascal, (Н.Вирт, начало 1970-х), C (Д. Ритчи), Ada (Honeywell, 1978), С++ (Б.Страуструп, 1985), Perl (Л.Уолл, 1987), Python (Гвидо ван Россум, 1990), PHP (Р.Лердорф, 1994), Java (Sun Microsystems, 1994), C# (1998).
Прикладное программирование подчинено проблемной направленности, отражающей компьютеризацию информационных и вычислительных процессов численной обработки, исследованных задолго до появления компьютеров. Именно здесь быстро проявился явный практический результат. В практике прикладного программирования принято доверять проверенным шаблонам и библиотекам процедур, избегать рискованных экспериментов. Ценится точность и устойчивость научных расчетов [12].
Теоретическое (доказательное) программирование - технология разработки программ с доказательствами правильности - доказательствами отсутствия ошибок в программах (несоответствий между программой и реализуемым ею алгоритмом), использовавшаяся в 1980-х годах в академических кругах. Программирование пытается выразить свои формальные модели, показать их значимость и фундаментальность. Эти модели унаследовали основные черты родственных математических понятий и утвердились как алгоритмический подход в информатике [13].
Стремление к доказательности построений и оценка их эффективности, правдоподобия, правильности, корректности и других формализуемых отношений на схемах и текстах программ послужили основой структурного программирования [37] и других методик достижения надежности процесса разработки программ, например, литературное (грамотное) программирование. Стандартные подмножества Алгола и Паскаля, послужившие рабочим материалом для теории программирования, сменились более удобными для экспериментирования аппликативными языками такими, как ML, Miranda, Scheme и другие диалекты Lisp. В настоящее время к ним присоединяются подмножества C и Java.
Структурное программирование (или программирование без goto) - методология разработки программного обеспечения, в основе которой лежит представление программы в виде иерархической структуры блоков. Предложена в 70-х годах XX века Э. Дейкстрой, разработана и дополнена Н. Виртом. Методология структурной разработки программного обеспечения была признана «самой сильной формализацией 1970-х годов». Является одним из способов обеспечения высокого уровня технологичности разрабатываемого программного обеспечения. Различают три вида вычислительного процесса, реализуемого программами: линейный, разветвленный и циклический.
Линейная структура процесса вычислений предполагает, что для получения результата необходимо выполнить операции в определенной последовательности. При разветвленной структуре процесса вычислений конкретная последовательность операций зависит от значений одной или нескольких переменных. Для получения результата при циклической структуре некоторые действия необходимо выполнить несколько раз.
Декларативное (логическое) программирование - парадигма программирования, основанная на теории и аппарате математической логики [38]. Возникло как упрощение функционального программирования для математиков и лингвистов, решающих задачи символьной обработки.
Программа «декларативна», если она описывает, что представляет собой нечто, а не как его создать. Например, веб-страницы на HTML декларативны, так как они описывают, что именно должна содержать страница, а не как ее отображать на экране. Декларативные программы пишутся на исключительно функциональном, логическом языках или языке программирования с ограничениями. Самым известным языком логического программирования является Prolog. Примеры использования подобных технологий можно увидеть в Microsoft ASP.NET и Microsoft Windows Communication Foundation.
Функциональное программирование - в основу функциональной парадигмы и функционального стиля программирования положен простой принцип: функция — вполне подходящее и адекватное средство описания вычислений [36]. Функциональная программа представляет собой набор определений функций. Функции определяются через другие функции или рекурсивно через самих себя. При выполнении программы функции получают параметры, вычисляют и возвращают результат, при необходимости вычисляя значения других функций. На функциональном языке программист не должен описывать порядок вычислений. Нужно просто описать желаемый результат как систему функций [35].
Функциональное программирование нашло большое применение в теории искусственного интеллекта и её приложениях.
Продуманность и методическая обоснованность первых реализаций основного языка функционального программирования Lisp (List processor) позволила быстро накопить опыт решения новых задач, подготовить их для прикладного и теоретического программирования. В настоящее время существуют сотни функциональных языков программирования, ориентированных на разные классы задач и виды технических средств, в том числе язык-прототип ISWIM, Scheme, ML, Caml, Miranda, Haskell, Clean – диалекты Lisp [24].
Развитием функциональной парадигмы стало аппликативное программирование [36]. Аппликативный подход к написанию программы состоит в систематическом осуществлении применения одного объекта к другому. Результатом такого применения вновь является объект, который может участвовать в применениях как в роли функции, так и в роли аргумента и т. д. Это делает запись программы математически ясной. Конструкции аппликативных языков программирования, в целом отличает простота исходных посылок. Их базовыми строительными блоками являются представления о выражении и функции, а все прочие понятия являются производными и вводятся шаг за шагом, что придаёт конструктивный стиль самому процессу программирования.
Основные средства и методы программирования сформировались по мере возрастания сложности решаемых задач. Произошло расслоение парадигм программирования в зависимости от глубины и общности проработки технических деталей организации процессов компьютерной обработки информации. Выделились разные стили программирования, наиболее зрелые из которых:
- низкоуровневое (машинно-ориентированное) программирование;
- системное программирование;
- декларативно-логическое программирование;
- оптимизационно-трансформационное программирование;
- высокопроизводительное (параллельное) программирование.
Низкоуровневое программирование характеризуется аппаратным подходом к организации работы компьютера, нацеленным на доступ к любым возможностям оборудования. В центре внимания - конфигурация оборудования, состояние памяти, команды, передачи управления, очередность событий, исключения и неожиданности, время реакции устройств и успешность реагирования. Ассемблер в качестве предпочтительного средства программирования на некоторое время уступил языкам Паскаль и Си даже в области микропрограммирования, но усовершенствование пользовательского интерфейса может восстановить его позиции.
Системное (стандартное) программирование долгое время развивалось под прессом сервисных и заказных работ. Свойственный таким работам производственный подход опирается на предпочтение воспроизводимых процессов и стабильных программ, разрабатываемых для многократного использования. В этой области доминирует императивно-процедурный стиль прикладного программирования. Он допускает использование модульного программирования, но сопровождается сложными построениями, спецификациями, методами тестирования и средствами интеграции программ.
При построении трансляторов используется автоматное программирование - это парадигма программирования, при использовании которой программа или её фрагмент осмысливается как модель какого-либо формального автомата. В зависимости от конкретной задачи в автоматном программировании могут использоваться как конечные автоматы, так и автоматы более сложной структуры. Автоматное программирование [26] широко применяется при построении лексических анализаторов (классические конечные автоматы) и синтаксических анализаторов (автоматы с магазинной памятью). К языкам автоматного программирования относятся:
- язык последовательных функциональных схем SFC (Sequential Function Chart) - графический язык программирования широко используется для программирования промышленных логических контроллеров PLC;
- дракон-схемы - графический язык программирования, используется для программирования в ракетно-космической технике;
- Рефлекс - Си-подобный язык программирования, ориентированный на описание сложных алгоритмов управления в задачах промышленной автоматизации.
Оптимизационно-трансформационное программирование объединило технику оптимизации программ, макрогенерации и частичных вычислений. Парадигма базируется на эквивалентности информации, которая проявляется в определении преобразований программ и процессов, в поиске критериев применимости преобразований, в выборе стратегии их использования [36]. В качестве методов повышения эффективности информационной обработки использует смешанные вычисления, отложенные действия, «ленивое» программирование, задержанные процессы и т.п.
Высокопроизводительное (параллельное) программирование является ветвью системного программирования и нацелено на достижение предельно возможных характеристик при решении особо важных задач. Естественный резерв производительности компьютеров - параллельные процессы. Их организация требует детального учета временных характеристик и неимперативного стиля управления действиями. Суперкомпьютеры, поддерживающие высокопроизводительные вычисления, потребовали особой техники. Графово-сетевой подход к представлению систем и процессов для параллельных архитектур получил выражение в специализированных языках параллельного программирования и суперкомпиляторах.
В том или ином виде разными языками программирования поддерживается обобщённое программирование - парадигма программирования, заключающаяся в таком описании данных и алгоритмов, которое можно применять к различным типам данных, не меняя само это описание. Возможности обобщённого программирования впервые появились в 1970-х годах в языках Клу и Ада, а затем во многих объектно-ориентированных языках таких, как C++, Java, Object Pascal, D, Eiffel, языках для платформы .NET и других.
В результате эволюции объектно-ориентированной парадигмы программирования (см. п.1.2.3) появились:
- аспектно-ориентированное программирование (АОП) - парадигма программирования, основанная на идее разделения функциональности для улучшения разбиения программы на модули [24]. Методология была предложена группой инженеров исследовательского центра Xerox PARC под руководством Грегора Кичалеса (Gregor Kiczales). В 2001 г. ими же было разработано аспектно-ориентированное расширение для языка Java, получившее название AspectJ. AOП дополняет объектно-ориентированное программирование, обогащая его другим типом модульности – аспектами. Аспекты в системе могут изменяться, вставляться, удаляться на этапе компиляции и, более того, повторно использоваться;
- событийно-ориентированное программирование (СОП) - парадигма программирования, в которой выполнение программы определяется событиями — действиями пользователя (клавиатура, мышь), сообщениями других программ и потоков, событиями операционной системы (например, поступлением сетевого пакета). Как правило, в реальных задачах оказывается недопустимым длительное выполнение обработчика события, поскольку при этом программа не может реагировать на другие события. В связи с этим при написании событийно-ориентированных программ часто применяют автоматное программирование [24];
- компонентно-ориентированное программирование - парадигма программирования, ключевой фигурой которой является компонент - независимый модуль программного кода, предназначенный для повторного использования и развертывания [24]. Компонентно-ориентированное программирование включает в себя набор ограничений, налагаемых на механизм объектно-ориентированного программирования. Среди языков компонентно-ориентированного программирования можно выделить Оберон (1987, Н.Вирт), компонентный Паскаль, PHP.
- прототипное программирование - стиль объектно-ориентированного программирования, при котором отсутствует понятие класса, а повторное использование (наследование) производится путём клонирования существующего экземпляра объекта (прототипа). Примером прототип-ориентированного языка является язык Self. В дальнейшем этот стиль программирования начал обретать популярность и был положен в основу таких языков программирования, как JavaScript, Lua, Io, REBOL [17].
2.5.3 Способы описания вычислительных процессов.
Для реализации вычислительных процессов разрабатываются соответствующие алгоритмы, а непосредственно в программах используют соответствующие управляющие операторы. Для описания этих процессов применяют различные способы (нотации): псевдокоды, блок-схемы, диаграммы Насси-Шнейдермана, Flow-формы и т.д.
Для изображения схем алгоритмов каждой группе действий ставится в соответствие специальный блок. Стандарт [10] предусматривает блоки для обозначения циклов, не запрещает произвольной передачи управления и допускает использование команд условной и безусловной передачи управления при реализации алгоритма.
После того, как в 60-х годах прошлого века было доказано, что любой сложный алгоритм можно представить, используя три основные управляющие конструкции, в языках программирования высокого уровня появились управляющие операторы для их реализации [8].
К базовым относят:
а) следование - обозначает последовательное выполнение действий;
б) ветвление - выбор одного из двух вариантов действий;
в) цикл-пока - определяет повторение действий, пока не будет нарушено некоторое условие, выполнение которого проверяется в начале цикла.
Кроме базовых, процедурные языки программирования высокого уровня используют три дополнительные конструкции, реализуемые через базовые:
а) выбор - выбор одного варианта из нескольких в зависимости от значения некоторой величины;
б) цикл-до - повторение действий до выполнения заданного условия, проверка которого осуществляется после выполнения действий в цикле;
в) цикл с заданным числом повторений (счетный цикл) - повторение некоторых действий указанное количество раз.
Перечисленные конструкции (см. таблицу 2.3) были положены в основу структурного программирования. Программы, написанные с использованием только структурных операторов передачи управления, называют структурными, чтобы подчеркнуть их отличие от программ, разрабаты-ваемых с использованием низкоуровневых способов передачи управления.
Пример 2.1 – Использование блок-схемы для описания алгоритма поиска в массиве А(n) элемента, равного заданному (см. рисунок 2.9).
Рисунок 2.9 – Фрагмент блок-схемы алгоритма поиска
В приведенном примере используется структурный вариант алгоритма (цикл-пока). Элементы массива перебираются и поочередно сравниваются с заданным значением Y. В результате выводится соответствующее сообщение.
К недостаткам блок-схем можно отнести следующие:
а) низкий уровень детализации, что скрывает суть сложных алгоритмов;
б) использование неструктурных способов передачи управления, которые на схеме выглядят проще, чем эквивалентные структурные.
Кроме схем, для описания алгоритмов можно использовать псевдокоды, Flow-формы и диаграммы Насси-Шнейдермана, которые базируются на тех же основных структурах, допускают разные уровни детализации и делают невозможным описание неструктурных алгоритмов.
Таблица 2.3 – Соответствие различных способов описания алгоритмов
Структура |
Псевдокоды |
Flow-формы |
Диаграммы Насси-Шнейдермана |
Следование |
<действие 1> <действие 2> |
|
|
Ветвление |
Если <условие> то <действие 1> иначе <действие 2> Все-если |
|
|
Цикл-пока |
Цикл-пока <условие> <действие> Все-цикл |
|
|
Выбор |
Выбор <код> <код 1>: <действие 1> <код 2>: <действие 2> иначе <действие 3> Все-выбор |
|
|
Цикл с парамет-ром |
Для <индекс> = <n>,<m>,<h> <действие > Все-цикл |
|
|
Цикл-до |
Выполнять <действие> До <условие> |
|
|
Псевдокод - формализованное текстовое описание алгоритма (см. таблицу 2.3), т.е. текстовая нотация. Описать с помощью псевдокодов неструктурный алгоритм невозможно. Псевдокод изначально ориентирует проектировщика только на структурные способы передачи управления и требует тщательного анализа разрабатываемого алгоритма.
Псевдокоды не ограничивают степень детализации проектируемых операций, позволяют соизмерять степень детализации действия с рассматриваемым уровнем абстракции и хорошо согласуются с методом пошаговой детализации.
Пример 2.2 – Использование псевдокода для описания алгоритма поиска в массиве А(n) элемента, равного заданному (фрагмент).
i :=1
Цикл-пока i £ n и A(i) ¹ Y
i := i + 1
Все-цикл
Если i £ n
то Вывести «Элемент найден»
иначе Вывести «Элемент не найден»
Все-если
Flow-формы - графическая нотация описания структурных алгоритмов, иллюстрирующая вложенность структур.
Каждому символу Flow-формы соответствует управляющая структура, изображаемая в виде прямоугольника и содержащая текст в математической нотации или на естественном языке.
Для демонстрации вложенности структур символ Flow-формы вписывается в соответствующую область прямоугольника любого другого символа. Размер прямоугольника определяется длиной вписанного в него текста и размерами вложенных прямоугольников. В таблице 2.3 приведены символы Flow-форм, соответствующие основным и дополнительным управляющим конструкциям.
Диаграммы Насси-Шнейдермана являются развитием Flow-форм лишь с той разницей, что область обозначения условий и вариантов ветвления изображают в виде треугольников (см. таблицу 2.3), обеспечивающих большую наглядность представления алгоритма.
Пример 2.3 – Использование Flow-форм для описания алгоритма поиска в массиве А(n) элемента, равного заданному (см. рисунок 2.10).
Рисунок 2.10 – Flow-форма алгоритма поиска (фрагмент)
Пример 2.4 – Использование диаграмм Насси-Шнейдермана для описания алгоритма поиска в массиве А(n) элемента, равного заданному (см. рисунок 2.11).
Рисунок 2.11 – Фрагмент диаграммы Насси-Шнейдермана
Так же, как при использовании псевдокодов, описать неструктурный алгоритм, применяя Flow-формы или диаграммы Насси-Шнейдермана, невозможно (для неструктурных передач управления в этих нотациях просто отсутствуют условные обозначения). В то же время, являясь графическими, эти нотации лучше отображают вложенность конструкций, чем псевдокоды.
Общим недостатком Flow-форм и диаграмм Насси-Шнейдермана является сложность построения изображений символов, что усложняет практическое применение этих нотаций для описания больших алгоритмов.
2.6 Стили оформления программы
Исходя из того, что любой модуль программы, написанной при реализации проекта, неоднократно придется просматривать, следует придерживаться хорошего стиля написания программ. С точки зрения технологичности хорошим считают стиль оформления программы, облегчающий ее восприятие как самим автором, так и другими программистами, которым придется ее проверять или модифицировать. «Помните, программы читаются людьми» - призывал Д. Ван Тассел, автор одной из известных монографий [5], посвященной проблемам программирования. Стиль оформления программы включает:
а) правила именования объектов (переменных, функций, типов и т. п.);
б) правила оформления модулей;
в) стиль оформления текстов модулей.
2.6.1 Имена объектов программы.
При выборе имен программных объектов следует придерживаться следующих правил:
а) имя объекта должно соответствовать его содержанию, например:
Maxltem - максимальный элемент; Nextltem - следующий элемент;
б) если позволяет язык программирования, можно использовать символ «_» для визуального разделения имен, состоящих из нескольких слов, например: Max_Item, Next_Item;
в) необходимо избегать близких по написанию имен, например: Index и InDec.
Кроме того, полезно использовать осмысленные имена для глобальных переменных и короткие имена — для локальных [42].
Поскольку глобальные переменные по определению могут проявиться в любом месте программы, их имена должны быть достаточно длинными и информативными, отражающие их назначение.
Для локальных переменных, наоборот, лучше подходят короткие имена. Обычно используемые локальные переменные по соглашению могут иметь очень короткие имена.
Так, употребление i и j для обозначения счетчиков цикла, р и q для указателей, s и t для строк стало настолько привычным, что применение более длинных имен не принесет никакой пользы, а наоборот, может даже навредить.
Существует множество соглашений и традиций именования. К наиболее распространенным правилам относятся:
- использование для указателей имен, начинающихся или заканчивающихся на р (от pointer, указатель);
- заглавных букв в начале имен глобальных переменных (например, Row, Col) и всех заглавных — в именах констант (например, ROW, COL);
- отображение в имени переменной информации об ее типе и способе использования (например, strTo — строки вывода);
- имя функции должно базироваться на активном глаголе, за которым может следовать существительное (например, getTime).
Использование соглашений облегчает понимание как собственного кода, так и кода, написанного другими программистами.
Чем больше размер кода, тем важнее использовать информативные и систематизированные имена.
2.6.2 Правила оформления модулей.
Каждый модуль должен предваряться заголовком, который содержит:
а) название модуля;
б) краткое описание его назначения;
в) краткое описание входных и выходных параметров с указанием единиц измерения;
г) список используемых (вызываемых) модулей;
д) краткое описание алгоритма (метода) и/или ограничений;
е) ФИО автора программы;
ж) идентифицирующую информацию (номер версии и/или дату последней корректировки).
Пример 2.5 – Оформление модуля программы (см. рисунок 2.12).
Рисунок 2.12 – Оформление модуля программы
2.6.3 Стиль оформления текстов модулей.
Стиль оформления текстов модулей определяет использование отступов, пропусков строк и комментариев, облегчающих понимание программы. Пропуски строк и комментарии используют для визуального разделения частей модуля.
Пример 2.6 – Использование комментариев в С++
void main ()
{
// инициализация переменных
// вычисление выражения
cout<<”Result=”<<y;
// операция над результирующей переменной
cout<<”Result operation”<<y;
}
Для таких языков, как Pascal, C++ и Java использование отступов позволяет прояснить структуру программы: обычно дополнительный отступ обозначает вложение операторов языка.
Пример 2.7 – Использование дополнительных отступов в С++
void main ()
{ // начало функции
int k, y;
for (k=1;k<=10;k++)
{ // начало тела цикла
if (y*y-5>60) break;
cout<<y*y-5<<endl;
} // конец тела цикла
} // конец функции
Несколько сложнее дело обстоит с комментариями. Переводить с английского языка каждый оператор программы не нужно: любой программист, знающий язык, на котором написана программа, без труда прочитает тот или иной оператор. Комментировать следует цели выполнения тех или иных действий, а также группы операторов, связанные общим действием, т. е. комментарии должны содержать дополнительную (неочевидную) информацию.
Пример 2.8 – Использование комментариев с неочевидной информацией
// проверка условия и выход, если условие не выполняется
if (y*y-5>60)
{
cout<<”Значение не попадает в указанный диапазон”<<endl;
break;
}
Для языков низкого уровня, например, Ассемблера, стиль, облегчающий понимание, предложить труднее. В этом случае может оказаться целесообразным комментировать и блоки операторов, и каждый оператор.
2.7 Программирование без ошибок
2.7.1 Классификация ошибок программирования.
Любая из ошибок программирования, которая не обнаруживается на этапах компиляции и компоновки программы, в итоге может проявиться тремя способами: привести к выдаче системного сообщения об ошибке, «зависанию» компьютера и получению неверных результатов.
Однако до того как результат работы программы становится фатальным, ошибки много раз проявляются в виде неверных типах данных, неверных промежуточных результатах, неверных управляющих переменных, индексах структур данных и т. п. (см. рисунок 2.13).
Часть ошибок можно обнаружить и нейтрализовать, пока они не привели к тяжелым последствиям. Программирование, при котором применяют специальные приемы раннего обнаружения и нейтрализации ошибок, названо защитным или программированием «с защитой от ошибок».
Детальный анализ ошибок и их возможных ранних проявлений показывает, что целесообразно проверять правильность выполнения операций ввода-вывода, а также допустимость промежуточных результатов (значений управляющих переменных, индексов, типов данных, числовых аргументов).
Причинами неверного определения исходных данных могут являться, как внутренние ошибки (ошибки устройств ввода-вывода или программного обеспечения), так и внешние ошибки (ошибки пользователя). Различают:
а) ошибки передачи - аппаратные средства искажают данные;
Рисунок 2.13 – Способы проявления ошибок
б) ошибки преобразования - программа неверно преобразует исходные данные из входного формата во внутренний;
в) ошибки перезаписи - пользователь ошибается при вводе данных;
ошибки данных — пользователь вводит неверные данные.
2.7.2 Способы устранения ошибок.
Ошибки передачи обычно контролируются аппаратно.
Для защиты от ошибок преобразования данные после ввода сразу демонстрируют пользователю («эхо»), выполняя преобразование сначала во внутренний формат и обратно. Предотвратить все ошибки преобразования на этом этапе крайне сложно, поэтому фрагменты программы тестируют [19], используя методы эквивалентного разбиения и граничных значений.
Обнаружить и устранить ошибки перезаписи можно только при вводе избыточных данных, например, контрольных сумм. Если ввод избыточных данных нежелателен, то по возможности проверяют входные данные и контролируют интервалы возможных значений, определенных в техническом задании, а также выводят введенные данные для проверки пользователю.
Неверные данные обычно может обнаружить только пользователь.
Проверки промежуточных результатов позволяют снизить вероятность позднего проявления не только ошибок неверного определения данных, но и некоторых ошибок кодирования и проектирования. Для этого необходимо, чтобы в программе использовались переменные с ограничениями любого происхождения, например, связанные с сущностью моделируемых процессов.
Любые дополнительные операции в программе требуют использования дополнительных ресурсов (времени, памяти) и могут содержать ошибки. Имеет смысл проверять только те промежуточные результаты, проверка которых целесообразна и не сложна, например, допустимость индекса.
Для снижения погрешности результатов вычислений следует:
а) избегать вычитания близких чисел (машинный ноль);
б) избегать деления больших чисел на малые;
в) сложение длинной последовательности чисел начинать с меньших по абсолютной величине;
г) стремиться по возможности уменьшать количество операций;
д) использовать методы с известными оценками погрешностей;
е) не использовать условие равенства вещественных чисел;
ж) вычислять с двойной точностью, а результат выдавать - с одинарной.
Поскольку полный контроль данных на входе и в процессе вычислений невозможен, следует предусматривать перехват и обработку аварийных ситуаций. Для перехвата и обработки аппаратно и программно фиксируемых ошибок в некоторых языках программирования (Delphi Pascal, C++ и Java) предусмотрены средства обработки исключений. Использование этих средств позволяет не допустить выдачи пользователю сообщения об аварийном завершении программы, а программист получает возможность предусмотреть действия, позволяющие исправить эту ошибку или выдать пользователю сообщение с точным описанием ситуации и продолжить работу.
2.7.3. Контроль структуры программы.
С целью устранения ошибок программирования необходимо организовать контроль структуры программы. Г.Майерс предлагает использовать следующие методы [23]: статический, смежный и сквозной контроль.
Статический контроль состоит в оценке структуры программы: насколько хорошо программа разбита на модули с учетом значений рассмотренных выше основных характеристик модуля.
Смежный контроль - это контроль со стороны разработчиков архитектуры, внешнего описания программной системы или спецификации модулей со стороны разработчиков этих модулей.
Сквозной контроль - это проверка структуры программы при выполнении заранее разработанных тестов.
Контроль структуры программы производится в рамках классического подхода. При конструктивном и архитектурном подходах контроль структуры программы осуществляется в процессе кодирования модулей в подходящие моменты времени.
3 глава. Требования и исходные данные к разработке программного обеспечения
Одним из важнейших и требующих особого внимания считается этап постановки задачи, в процессе которого формулируется назначение и определяются требования к программному обеспечению. Каждое требование представляет собой описание необходимого или желаемого свойства программного обеспечения. Различают функциональные требования, определяющие функции, которые должно выполнять разрабатываемое программное обеспечение, и эксплуатационные требования, определяющие особенности его функционирования.
Требования к программному обеспечению, имеющему прототипы, обычно определяют по аналогии, учитывая структуру и характеристики уже существующего программного обеспечения.
Для формулирования требований к программному обеспечению, не имеющему аналогов, иногда необходимо провести специальные исследования, называемые предпроектными. В процессе таких исследований определяют разрешимость задачи, возможно, разрабатывают методы ее решения (если они новые) и устанавливают наиболее существенные характеристики разрабатываемого программного обеспечения. Для их выполнения, как правило, используют все доступные источники информации, в том числе результаты научно-исследовательских работ, привлекают консультантов-специалистов. В любом случае этап постановки задачи заканчивается разработкой технического задания, фиксирующего принципиальные требования, и принятием основных проектных решений. Рассмотрим более подробно эти процессы.
3.1 Классификация программного обеспечения по функциональному признаку
Каждый программный продукт предназначен для выполнения определенных функций. По функциональному признаку все программные продукты можно разделить на три группы [32]: системные, прикладные и гибридные (см. рисунок 3.1).
К системным относят программные продукты, обеспечивающие функционирование вычислительных систем (операционные системы, оболочки, утилиты).
Прикладные программы и системы ориентированы на решение конкретных пользовательских задач. Среди их пользователей различают разработчиков программ и непрограммистов, использующих компьютерные системы для достижения своих целей.
Разработчики программ используют специальные инструментальные средства (компиляторы, компоновщики, отладчики), которые интегрируют в системы программирования и среды разработки.
Рисунок 3.1 – Классификация программных продуктов по их назначению
Современные среды программирования (Delphi, Visual C++) реализуют визуальную технологию разработки программных продуктов и предоставляют программистам огромные библиотеки компонентов. К этой же группе относят инструментальные комплексы создания баз данных (Access, FoxPro, Oracle), средства создания интеллектуальных систем (экспертных, обучающих, систем контроля знаний). Последнее достижение в этом направлении - CASE-средства разработки программного обеспечения (ERwin, BPwin, Paradigm Plus, Rational Rose и другие).
В соответствии с современными требованиями непрограммисты не должны быть профессионалами в проблемах создания программных продуктов и специфике их взаимодействия с операционной системой. Для них разрабатывают специальные программные продукты, ориентированные на определенную предметную область. Такие продукты условно разделяют на:
а) продукты общего назначения:
- текстовые редакторы;
- электронные таблицы;
- графические редакторы;
- информационные системы общего назначения;
- программы-переводчики;
б) профессиональные среды:
- системы автоматизации проектирования;
- системы-тренажеры;
- бухгалтерские системы;
- издательские системы;
- профессиональные графические системы;
- экспертные системы;
в) обучающие системы;
г) развлекающие программы:
- информационные системы с тестами развлекающего характера;
- музыкальные программы;
- игровые программы.
Гибридные системы – это большие, узкоспециализированные системы для управления технологическими процессами различных типов в режиме реального времени, сочетающие признаки системного и прикладного ПО. Для повышения надежности и снижения времени обработки в них включают программы, обеспечивающие выполнение функций операционных систем.
3.2 Эксплуатационные требования к программному обеспечению
К каждому из перечисленных типов программного обеспечения при разработке обычно предъявляют еще и эксплуатационные требования, определяющие некоторые характеристики разрабатываемого программного продукта, которые проявятся в процессе его функционирования. К таким характеристикам относят:
а) правильность - функционирование в соответствии с техническим заданием;
б) универсальность - обеспечение правильной работы при любых допустимых данных и защиты от неправильных данных;
в) надежность (помехозащищенность) - обеспечение полной повторяемости результатов (правильности при наличии различного рода сбоев);
г) проверяемость - возможность проверки получаемых результатов;
д) точность - обеспечение погрешности результатов не выше заданной;
е) защищенность - обеспечение конфиденциальности информации;
ж) программная совместимость - возможность совместного функционирования с другим программным обеспечением;
з) аппаратная совместимость - возможность совместного функциони-рования с некоторым оборудованием (указывается минимально возможная конфигурация оборудования, на котором будет работать ПО);
и) эффективность - использование минимально возможного количества ресурсов технических средств (время ответа системы, объем оперативной и внешней памяти, количество обслуживаемых внешних устройств);
к) адаптируемость - возможность быстрой модификации с целью приспособления к изменяющимся условиям функционирования;
л) повторная входимость - возможность повторного выполнения без перезагрузки с диска;
м) реентерабельность - возможность «параллельного» использования несколькими процессами (все данные, изменяемые программой в процессе выполнения, должны быть выделены в специальный блок, копия которого создается для каждого процесса при вызове программы).
3.3 Постановка задачи
3.3.1 Предпроектные исследования.
Сложность многих программных систем не позволяет сразу сформулировать четкие требования к ним. Обычно для перехода от идеи создания программного обеспечения к четкой формулировке требований, которые могут быть занесены в техническое задание, необходимо выполнить предпроектные исследования в области разработки. Их целью является преобразование общих нечетких знаний о предназначении будущего программного обеспечения в сравнительно точные требования к нему.
Существуют два варианта неопределенности:
а) неизвестны методы решения формулируемой задачи - такого типа неопределенности обычно возникают при решении научно-технических задач, поэтому во время предпроектных исследований определяют возможность решения поставленной задачи и методы, позволяющие получить требуемый результат, что может потребовать соответствующих научных исследований как фундаментального, так и прикладного характера, разработки и исследования новых моделей объектов реального мира;
б) неизвестна структура автоматизируемых информационных процессов - обычно встречается при построении автоматизированных систем управления предприятиями, поэтому в этом случае определяют:
1) структуру и взаимосвязи информационных процессов;
2) распределение функций между человеком и системой, аппаратурой и программным обеспечением;
3) функции программного обеспечения, условия его функционирования, особенности аппаратных и пользовательских интерфейсов;
4) требования к программным и информационным компонентам, необходимые аппаратные ресурсы, требования к базам данных и физические характеристики программных компонент.
На практике для проведения предпроектных исследований привлекают консультантов - специалистов в автоматизируемой области, используют результаты научных исследований, научного прогнозирования, а также новейших разработок в области техники и технологий.
3.3.2 Разработка технического задания.
Результаты предпроектных исследований предметной области используются в процессе разработки технического задания.
Техническое задание представляет собой документ, в котором сформулированы основные цели разработки, требования к программному продукту, определены сроки и этапы разработки и регламентирован процесс приемно-сдаточных испытаний.
В разработке технического задания участвуют как представители заказчика, так и представители исполнителя. В основе этого документа лежат исходные требования заказчика, результаты выполнения предпроектных исследований, научного прогнозирования и т. п. Основными факторами, определяющими характеристики разрабатываемого программного обеспечения являются:
а) исходные данные и требуемые результаты, определяющие функции программы или системы;
б) среда функционирования (программная и аппаратная) - задается или выбирается для обеспечения параметров, указанных в техническом задании;
в) возможное взаимодействие с другим программным обеспечением и/или специальными техническими средствами - задается или выбирается, исходя из набора выполняемых функций.
Разработка технического задания - процесс трудоемкий, требующий определенных навыков, выполняется в следующей последовательности:
1) прежде всего, устанавливают набор выполняемых функций, а также перечень и характеристики исходных данных;
2) определяют перечень результатов, их характеристики и способы представления;
3) уточняют среду функционирования программного обеспечения: конкретную комплектацию и параметры технических средств, версию используемой операционной системы, версии и параметры другого установленного программного обеспечения, с которым предстоит взаимодействовать будущему программному продукту;
4) если разрабатываемое программное обеспечение собирает и хранит некоторую информацию или включается в управление каким-либо техническим процессом, то регламентируют действия программы в случае сбоев оборудования и энергоснабжения.
На техническое задание при разработке программного обеспечения существует стандарт ГОСТ 19.201-78 «Техническое задание. Требования к содержанию и оформлению». В соответствии с этим стандартом техническое задание должно содержать следующие разделы:
1) Введение - демонстрирует актуальность разработки и показывает, какое место эта разработка занимает в ряду подобных; включает наименование и краткую характеристику области применения программы или программного продукта, а также объекта, в котором предполагается их использовать;
2) Основания для разработки - содержит наименование документа, на основании которого ведется разработка, организации, утвердившей данный документ, и наименование или условное обозначение темы разработки (например, документом может служить план, приказ, договор и т.п.);
3) Назначение разработки - содержит описание функционального и эксплуатационного назначения программного продукта с указанием категорий пользователей;
4) Требования к программе или программному изделию включает подразделы:
- Требования к функциональным характеристикам, в котором перечислены выполняемые функции, описаны состав, характеристики и формы представления исходных данных и результатов; при необходимости указывают критерии эффективности (максимально допустимое время ответа системы, максимальный объем используемой оперативной и/или внешней памяти и др.);
- Требования к надежности, в котором указывают уровень надежности, обеспечиваемый разрабатываемой системой и время восстановления системы после сбоя, регламентируют действия разрабатываемого продукта по увеличению надежности результатов (контроль входной и выходной информации, создание резервных копий промежуточных результатов и т. п.);
- Условия эксплуатации, в котором указывают особые требования к условиям эксплуатации в нестандартных условиях (температура окружающей среды, относительная влажность воздуха и т. п.) или при использовании специальных внешних устройств (вид обслуживания, необходимое количество и квалификация персонала);
- Требования к составу и параметрам технических средств, в котором указывают необходимый состав технических средств с указанием основных технических характеристик (тип микропроцессора, объем памяти, наличие внешних устройств и т. п.) и варианта конфигурации (минимальная и рекомендуемая);
- Требования к информационной и программной совместимости, в котором задают методы решения, определяют язык или среду программирования для разработки, степень защиты информации, используемую операционную систему и другие системные и пользовательские программные средства, взаимодействующие с разрабатываемым программным обеспечением;
- Требования к маркировке и упаковке;
- Требования к транспортированию и хранению;
- Специальные требования;
5) Требования к программной документации – содержит перечень необходимой сопроводительной документации (руководство программиста, руководство пользователя, руководство системного программиста, пояснительная записка и т. п.);
6) Технико-экономические показатели – содержит сведения об ориентировочной экономической эффективности, предполагаемой годовой потребности и экономических преимуществах по сравнению с существующими аналогами;
7) Стадии и этапы разработки – содержит перечень стадий разработки и этапов, а также содержание работ с указанием сроков разработки и исполнителей;
8) Порядок контроля и приемки - содержит перечень видов испытаний и общие требования к приемке работы.
При необходимости допускается в техническое задание включать приложения, в которых при необходимости приводят перечень научно-исследовательских работ, обосновывающих разработку; схемы алгоритмов, таблицы, описания, обоснования, расчеты и другие документы, которые следует использовать при разработке.
В зависимости от особенностей разрабатываемого продукта разрешается использовать подразделы, вводить новые разделы или объединять их.
Если какие-либо требования, предусмотренные техническим заданием, заказчик не предъявляет, следует в соответствующем месте указать «Требования не предъявляются».
Образец выполнения технического задания на создание системы «Учет успеваемости студентов» и пример оформления титульного листа приведены в Приложении А.
Система предназначена для оперативного учета успеваемости студентов в сессию деканом, заместителями декана по курсам и сотрудниками деканата. Сведения об успеваемости студентов должны храниться в течение всего срока обучения и использоваться при составлении справок о прослушанных курсах и приложений к диплому. Данный пример составлен по сокращенной схеме, несущественные для данной разработки разделы пропущены.
3.3.3 Принятие принципиальных решений.
После утверждения технического задания разработчик непосредственно приступает к созданию программного обеспечения. Однако переход к этапу уточнения спецификаций требует принятия некоторых принципиальных решений, от которых во многом зависят характеристики, возможности разрабатываемого программного обеспечения, особенности разработки. Решения, которые определяют, что проектируется, с какими потребительскими характеристиками, как и какими средствами. К таким решениям относят:
- выбор архитектуры программного обеспечения;
- типа пользовательского интерфейса;
- технологии работы с документами;
- выбор подхода к разработке;
- выбор языка и среды программирования.
Часть решений может быть определена в техническом задании, образовав группу технологических требований, остальные должны быть приняты как можно раньше, так как представляют собой исходные данные для процесса проектирования. Рассмотрим их более подробно.
Архитектура программного обеспечения – это совокупность базовых принципов его построения. Она определяется сложностью решаемых задач, степенью универсальности разрабатываемого программного обеспечения и числом пользователей, одновременно работающих с одной его копией.
Различают однопользовательскую архитектуру, при которой программное обеспечение рассчитано на одного пользователя, и многопользовательскую архитектуру, которая рассчитана на работу в локальной или глобальной сети.
В рамках однопользовательской архитектуры различают:
а) программы - самый простой вид архитектуры, используется при решении небольших задач. Представляют собой адресованный компьютеру набор инструкций, точно описывающий последовательность действий, которые необходимо выполнить для решения конкретной задачи. Например, при структурном подходе программы представляют собой иерархию подпрограмм, вызывающих друг друга в процессе решения поставленной задачи;
б) пакеты программ - совокупность программ, решающих задачи некоторой прикладной области. Пакет программ реализуют в виде набора отдельных программ (библиотеки), каждая из которых сама вводит необходимые данные и выводит результаты;
в) программные комплексы - совокупность программ, обеспечивающих совместное решение небольшого класса сложных задач одной прикладной области. Для решения может потребоваться решить несколько подзадач, последовательно вызывая программы комплекса с помощью специальной программы - диспетчера, который обеспечивает интерфейс с пользователем и выдачу некоторой справочной информации. Несколько программ комплекса могут последовательно или циклически вызываться для решения одной задачи, поэтому желательно хранить исходные данные и результаты вызовов в пределах одного пользовательского проекта;
г) программные системы - организованная совокупность программ (подсистем), позволяющая решать широкий класс задач из некоторой прикладной области. Программы, входящие в программную систему, взаимодействуют через общие данные. Программные системы обычно имеют развитые пользовательский и внутренние интерфейсы.
Многопользовательскую архитектуру реализуют системы, построенные по принципу «клиент-сервер». Многопользовательские программные системы должны организовывать сетевое взаимодействие отдельных компонентов ПО, что усложняет процесс его разработки, поэтому для разработки используют специальные технологии или платформы (технологии CORBA, COM, Java).
Тип пользовательского интерфейса во многом определяет сложность и трудоемкость разработки. По последним данным до 80 % программного кода может реализовывать именно пользовательский интерфейс [22]. Различают четыре типа пользовательских интерфейсов:
а) примитивные - реализуют единственный сценарий работы, используя операции ввода данных, их обработки и вывода результатов;
б) меню - реализуют множество сценариев работы, операции которых организованы в иерархические структуры;
в) со свободной навигацией - реализуют множество сценариев, операции которых не привязаны к уровням иерархии, и предполагают определение множества возможных операций на конкретном шаге работы; интерфейсы данной формы в основном используют Windows-приложения;
г) прямого манипулирования - реализуют множество сценариев, представленных в операциях над объектами, инициируемых перемещением пиктограмм объектов мышью; данная форма реализована в интерфейсе операционной системы Windows.
Появление объектно-ориентированных визуальных сред разработки программного обеспечения, использующих событийный подход к программированию, существенно снизило трудоемкость разработки интерфейсов и упростило реализацию интерфейсов прямого манипулирования.
Выбор типа интерфейса включает выбор технологии работы с документами. Различают две основные технологии:
а) однодокументная, которая предполагает однодокументный интерфейс (SDI - Single Document Interface) и используется, если одновременная работа с несколькими документами не обязательна;
б) многодокументная, которая предполагает многодокументный интерфейс (MDI - Multiple Document Interface) и используется, если программное обеспечение должно работать с несколькими документами одновременно, например, с несколькими текстами или несколькими изображениями.
Трудоемкость реализации многодокументных интерфейсов с использованием современных библиотек примерно на 3...5 % выше, чем однодокументных, однако тип влияет на трудоемкость более существенно.
При выборе интерфейса прямого манипулирования или со свободной навигацией практически однозначно предполагается использование объектного подхода и событийного программирования, так как современные среды визуального программирования, такие как Visual C++, Delphi, Builder C++, предоставляют интерфейсные компоненты именно в виде объектов библиотечных классов. При этом в зависимости от сложности предметной области программное обеспечение может реализовываться как с использованием объектов и, соответственно, классов, так и чисто процедурно. Исключение составляют случаи использования специализированных языков разработки Интернет-приложений (Perl), построенных по совершенно другому принципу.
Примитивный интерфейс и интерфейс типа меню совместимы как со структурным, так и с объектным подходами к разработке. Поэтому выбор подхода осуществляют с использованием дополнительной информации.
Объектный подход эффективен для разработки очень больших программных систем (более 100000 операторов) и в случаях, когда объектная структура предметной области ярко выражена. Следует осторожно использовать объектный подход при жестких ограничениях на эффективность программного обеспечения, например, при разработке систем реального времени. Во всех прочих случаях выбор подхода остается за разработчиком.
В большинстве случаев, проблемы выбора языка программирования реально не существует. Язык может быть определен:
- организацией, ведущей разработку;
- программистом, который по возможности всегда будет использовать хорошо знакомый язык;
- устоявшимся мнением.
В общем случае все существующие языки программирования модно разделить на четыре группы [1]:
а) универсальные языки высокого уровня;
б) специализированные языки разработчика программного обеспечения;
в) специализированные языки пользователя;
г) языки низкого уровня.
В группе универсальных языков высокого уровня безусловным лидером сегодня является язык С (вместе с C++). Действительно различные версии С и C++ имеют целый ряд очень существенных достоинств [3]:
а) многоплатформенность - для всех используемых в настоящее время платформ существуют компиляторы с языка С и C++;
б) наличие операторов, реализующих основные структурные алгоритмические конструкции (условную обработку, все виды циклов);
в) возможность программирования на низком (системном) уровне с использованием адресов оперативной памяти;
г) огромные библиотеки подпрограмм и классов.
Все это сделало С и C++ основными языками, используемыми для создания операционных систем, и, в свою очередь, служит для них дополнительной рекламой. Однако они имеют и серьезные недостатки:
а) отсутствие полноценных встроенных структурных типов данных;
б) наличие синтаксических неоднозначностей, которые также не позволяют компилятору контролировать правильность программы;
в) ограниченный контроль параметров, передаваемых в подпрограмму, что также обнаруживается только в процессе отладки программы.
Альтернативой С и C++ среди универсальных языков программирования, используемых для создания прикладного программного обеспечения, на сегодня является Pascal, компиляторы которого в силу четкого синтаксиса обнаруживают помимо синтаксических и большое количество семантических ошибок. Версия Object Pascal, использованная в среде Delphi, сопровождается профессиональными библиотеками классов, упрощающими ведение больших разработок, в том числе и требующих использования баз данных, что делает Delphi достаточно эффективной средой для создания приложений Windows.
Кроме этих языков, к группе универсальных принадлежат также Basic, Modula, Ada и некоторые другие. Каждый из указанных языков так же, как C++ и Pascal, имеет свои особенности и, соответственно, свою область применения.
Специализированные языки разработчика используют для создания конкретных типов программного обеспечения. К ним относят:
а) языки баз данных;
б) языки создания сетевых приложений;
в) языки создания систем искусственного интеллекта и т. д.
Специализированные языки пользователя обычно являются частью профессиональных сред, характеризуются узкой направленностью и разработчиками программного обеспечения не используются.
Языки низкого уровня позволяют осуществлять программирование практически на уровне машинных команд. При этом получают самые оптимальные как с точки зрения времени выполнения, так и с точки зрения объема необходимой памяти программы. Но эти языки совершенно не годятся для создания больших программ и, тем более, программных систем. Основная причина - низкий уровень абстракций, которыми должен оперировать разработчик, откуда недопустимо большое время разработки.
Существенно и то, что сами языки низкого уровня не поддерживают принципов структурного программирования, что значительно ухудшает технологичность разрабатываемых программ. В настоящее время языки типа Ассемблера обычно используют:
а) при написании сравнительно простых программ, взаимодействующих непосредственно с техническими средствами (например, драйверов);
б) в виде вставок в программы на языках высокого уровня.
Таким образом, при выборе языка программирования следует руководствоваться следующими соображениями:
а) язык должен быть удобен для программиста;
б) язык должен быть пригоден для данного компьютера;
в) язык должен быть пригоден для решения данной задачи.
Среда программирования - программный комплекс, включающий текстовый редактор, встроенные компилятор, компоновщик, отладчик, справочную систему и другие программы, использование которых упрощает процесс написания и отладки программ.
Последнее время широкое распространение получили среды визуального программирования, позволяющие визуально подключать к программе коды из специальных библиотек компонентов.
Наиболее часто используют визуальные среды Delphi, C++ Builder фирмы Borland (Inprise Corporation), Visual C++, Visual Basic фирмы Microsoft, Visual Ada фирмы IBM.
Причем, среды фирмы Microsoft обеспечивают более низкий уровень программирования «под Windows». Это является их достоинством (уменьшается вероятность возникновения «нестандартной» ситуации) и недостатком (существенно загружает программиста «рутинной» работой, от которой избавлен программист, работающий с Delphi или C++ Builder).
В общем случае, выбор среды в значительной степени должен определяться характером разработки.
Описанные принципиальные решения существенно влияют на трудоемкость и сложность разработки. Только после их принятия переходят к анализу требований и разработке спецификаций проектируемого программного обеспечения.
3.4 Анализ требований и определение спецификаций
Разработка любого программного обеспечения начинается с анализа требований к будущему программному продукту. В результате анализа получают спецификации разрабатываемого программного обеспечения.
Спецификации – это полное и точное описание функций и ограничений разрабатываемого программного обеспечения. Различают:
- функциональные спецификации, которые описывают функции разрабатываемого программного продукта и состав обрабатываемых данных;
- эксплуатационные, которые определяют требования к техническим средствам, надежности, информационной безопасности и т. д.
Естественный язык для описания спецификаций не подходит, поскольку не обеспечивает необходимой точности.
Точные спецификации можно определить, лишь разработав некоторую формальную модель. Формальные модели можно разделить на две группы: модели, зависящие от подхода к разработке, и модели, не зависящие от него.
При любом подходе к разработке используются диаграммы переходов состояний и математические модели предметной области.
Поскольку разные модели описывают проектируемое программное обеспечение с разных сторон, используют сразу несколько моделей, которые сопровождают текстами. В состав обобщенной модели, как правило, входят следующие элементы:
- спецификации процессов;
- словарь терминов;
- диаграммы переходов состояний;
- функциональные диаграммы;
- диаграммы потоков данных.
Спецификации процессов обычно представляют в виде краткого текстового описания, схем алгоритмов, псевдокодов, Flow-форм или диаграмм Насси-Шнейдермана. Для краткости и понятности описания не только разработчику, но и заказчику, чаще всего используют псевдокоды.
Словарь терминов – краткое описание основных понятий, используемых при составлении спецификаций, который включает определение основных понятий предметной области, описание структур элементов данных, их типов и форматов, а также всех сокращений и условных обозначений. Словарь предназначен для однозначного понимания предметной области и исключения риска возникновения разногласий при обсуждении моделей между заказчиками и разработчиками. Описание термина в словаре выполняется по схеме: «термин – категория– краткое описание».
Диаграмма переходов состояний демонстрирует поведение разрабатываемой программной системы при получении управляющих воздействий (управляющей информации, поступающей извне). Для ее построения в соответствии с теорией конечных автоматов необходимо определить: основные состояния, управляющие воздействия (или условия перехода), выполняемые действия и возможные варианты переходов из одного состояния в другое.
Если программная система в процессе функционирования активно не взаимодействует с окружающей средой (пользователем или датчиками), например, использует примитивный интерфейс и выполняет некоторые вычисления по заданным исходным данным, то диаграмма переходов состояний обычно интереса не представляет (см. рисунок 3.2).
Рисунок 3.2 - Пример диаграммы переходов состояний программного обеспечения, не взаимодействующего с окружающей средой
Представленная диаграмма демонстрирует только последовательно выполняемые переходы: из исходного состояния в состояние ввода данных, после выполнения вычислений - в состояние вывода и, наконец, в состояние завершения работы.
Для интерактивного программного обеспечения с развитым пользовательским интерфейсом характерно получение команд различных типов (см. рисунок 3.3), а для программного обеспечения реального времени - однотипных сигналов (либо от многих датчиков, либо требующих продолжительной обработки).
Рисунок 3.3 - Пример диаграммы переходов состояний программного обеспечения, активно взаимодействующего с окружающей средой
Общим для них является наличие состояния ожидания, когда программное обеспечение приостанавливает работу до получения очередного управляющего воздействия.
В отличие от интерактивных систем для систем реального времени обычно установлено более жесткое ограничение на время обработки полученного сигнала программного обеспечения. Такое ограничение часто требует выполнения дополнительных исследований поведения системы во времени. В любом случае полученную диаграмму переходов состояний обязательно согласовывают с заказчиком.
Функциональными называют диаграммы, отражающие взаимосвязи функций разрабатываемого программного обеспечения. Для отображения взаимосвязи функций строится иерархии функциональных диаграмм, схематически представляющих взаимосвязи нескольких функций. Каждый блок такой диаграммы соответствует некоторой функции (см. рисунок 3.4), для которой должны быть определены: исходные данные, результаты, управляющая информация и механизмы ее осуществления - человек или технические средства.
Все связи функции представляются дугами. Дуги, изображающие каждый тип связей, должны подходить к блоку с определенной стороны, а направление связи должно указываться стрелкой в конце дуги.
Рисунок 3.4 – Функциональный блок и интерфейсные дуги
Физически дуги исходных данных, результатов и управления представляют собой наборы данных, передаваемые между функциями. Дуги, определяющие механизм выполнения функции, используются при описании сложных информационных систем.
Блоки и дуги сопровождаются текстами на естественном языке.
Блоки на диаграмме размещают по «ступенчатой» схеме в соответствии с последовательностью их работы или доминированием - влиянием, которое оказывает один блок на другие.
Дуги могут разветвляться и соединяться различными способами. Разветвление означает, что часть или вся информация может использоваться в каждом ответвлении дуги.
В процессе построения иерархии диаграмм фиксируют всю уточняющую информацию и строят словарь данных, в котором определяют структуры и элементы данных, показанных на диаграммах. В результате получают спецификацию, которая состоит из иерархии функциональных диаграмм, спецификаций функций нижнего уровня и словаря, имеющих ссылки друг на друга.
Функциональную модель имеет смысл применять для определения спецификаций программного обеспечения, которое не предусматривает работу со сложными структурами данных.
Диаграммы потоков данных позволяют специфицировать функции разрабатываемого программного обеспечения и обрабатываемые им данные. При использовании этой модели систему представляют в виде иерархии диаграмм потоков данных, описывающих асинхронный процесс преобразования информации с момента ввода в систему до выдачи пользователю. На каждом следующем уровне иерархии происходит уточнение процессов, пока очередной процесс не будет признан элементарным. В основе модели лежат понятия:
- внешняя сущность - объект или физической лицо, которое является источником или приемником информации (банк, персонал, клиент и т.д.);
- процесс – преобразование входных данных в выходные в соответствии с алгоритмом;
- хранилище (накопителя) данных – абстрактное устройство для хранения информации (картотека, база данных, файл и т.д.);
- поток данных – процесс передачи информации от источника к приемнику (автоматически ил вручную).
Для отображения связей, существующих между отдельными элементами данных, используют совокупности правил и ограничений - структуры данных (см. рисунок 3.5).
Рисунок 3.5 – Классификация структур данных
Различают:
- абстрактные структуры данных, используемые для уточнения связей между элементами;
- конкретные структуры, используемые для представления данных в программах.
Для задач, алгоритм решения которых не очевиден, используют разного рода математические модели. Процесс построения такой модели включает:
а) анализ условия задачи;
б) выбор математических абстракций, адекватно (с требуемой точностью и полнотой) представляющих исходные данные и результаты;
в) формальную постановку задачи;
г) определение метода преобразования исходных данных в результат (метода решения задачи).
Для многих задач, которые часто встречаются на практике, в математике определены как модели, так и методы решения. В ряде случаев формальная постановка задачи однозначно определяет метод ее решения, но, как правило, методов решения существует несколько, и тогда для выбора метода решения может потребоваться специальное исследование.
При выборе метода учитывают:
- особенности данных конкретной задачи, связанные с предметной областью (погрешность, возможные особые случаи и т. п.);
- требования к результатам (допустимую погрешность);
- характеристики метода (точный или приближенный, погрешности результатов, вычислительную сложность, сложность реализации).
Определив методы решения, целесообразно вручную подсчитать ожидаемые результаты для некоторых вариантов исходных данных. Эти данные позже могут быть использованы при тестировании программного обеспечения. Выполнение операций вручную позволяет точно уяснить последовательность действий, что упростит разработку алгоритмов. Имеет смысл продумать, для каких сочетаний исходных данных результат не существует или не может быть получен данным методом, что тоже необходимо учесть при разработке программного обеспечения.
4 глава. Особенности проектирования программного обеспечения при различных подходах
4.1 Структурный подход
Для того чтобы иметь четкое представление о компонентах сложного программного обеспечения и их взаимосвязях, необходимо уточнить его структуру. Результат уточнения может быть представлен в виде структурной и/или функциональной схем и описания (спецификаций) компонентов.
Схему, отражающую состав и взаимодействие по управлению частей разрабатываемого программного обеспечения, называют структурной.
Поскольку организация программ в пакеты не предусматривает передачи управления между ними, структурные схемы пакетов программ не информативны. Поэтому структурные схемы разрабатывают для каждой программы пакета, а список программ пакета определяют, анализируя функции, указанные в техническом задании. Разработку структурной схемы программы, включающей в качестве структурных компонентов только подпрограммы и библиотеки ресурсов, выполняют методом пошаговой детализации.
Структурными компонентами программной системы/комплекса служат программы, библиотеки ресурсов, подсистемы, базы данных. Структурная схема программного комплекса демонстрирует передачу управления от программы-диспетчера соответствующей программе (см. рисунок 4.1а).
Структурная схема программной системы показывает наличие подсистем или других структурных компонентов. В отличие от программного комплекса отдельные части (подсистемы) программной системы интенсивно обмениваются данными между собой и с основной программой. Структурная схема программной системы этого не показывает (см. рисунок 4.2а).
С точки зрения взаимодействия его компонентов между собой и с внешней более полное представление о проектируемом программном обеспечении средой дает функциональная схема. Функциональная схема (схема данных, ГОСТ 19.701-90) - схема взаимодействия компонентов программного обеспечения с описанием информационных потоков, состава данных в потоках и указанием используемых файлов и устройств.
Функциональные схемы более информативны, чем структурные. На рисунках 4.1б и 4.2б приведены функциональные схемы программных комплексов и систем. Все компоненты структурных и функциональных схем должны быть описаны. Следует тщательно прорабатывать спецификации межпрограммных интерфейсов, так как от качества их описания зависит количество самых дорогостоящих ошибок, к которым относятся ошибки, обнаруживаемые при комплексном тестировании.
Рисунок 4.1 - Пример структурной и функциональной схем программного комплекса
Рисунок 4.2 – Пример структурной и функциональной схем программной системы
Для изображения функциональных схем используют специальные обозначения, установленные стандартом. Основные обозначения схем данных приведены в таблице 4.1.
Таким образом, структурная схема программы – это результат декомпозиции программы методом пошаговой детализации, т.е. многоуровневая иерархическая схема взаимодействия подпрограмм по управлению. В простейшем случае такая схема показывает общую структуру программы, т.е. отображает два уровня иерархии. Тот же метод позволяет получить структурные схемы с большим количеством уровней.
Таблица 4.1 – Основные обозначения схем данных
Название блока |
Обозначение |
Назначение блока |
Запоминаемые данные |
|
Обозначение таблиц и других структур данных, которые должны быть сохранены без уточнения типа устройства |
Оперативное запоминающее устройство |
|
Для обозначения таблиц и других структур данных, хранящихся в оперативной памяти |
Запоминающее устройство с последовательной выборкой |
|
Для обозначения таблиц и других структур данных, хранящихся на устройствах с последовательной выборкой (магнитной ленте и т.п.) |
Запоминающее устройство с прямым доступом |
|
Для обозначения таблиц и других структур данных, хранящихся на устройствах с прямым доступом (дисках) |
Документ |
|
Для обозначения таблиц и других структур данных, выводимых на печатающее устройство |
Ручной ввод |
|
Для обозначения ручного ввода данных с клавиатуры |
Карта |
|
Для обозначения данных на магнитных или перфорированных картах |
Дисплей |
|
Для обозначения данных, выводимых на дисплей |
Разбиение на модули выполняется эвристически, исходя из рекомендуемых размеров модулей (20-60 строк) и сложности структуры (2-3 вложенных управляющих конструкции). Для анализа технологичности иерархии модулей используют методики Константайна или Джексона [32].
Практически одновременно появились методики проектирования программного обеспечения Джексона и Варнье-Орра, также основанные на декомпозиции данных. Обе методики предназначены для создания «простых» программ, работающих со сложными, но иерархически организованными структурами данных. При разработке программных систем предлагается вначале разбить систему на отдельные программы, а затем использовать эти методики. Они могут использоваться только в том случае, если данные разрабатываемых программ могут быть представлены в виде иерархии или совокупности иерархий.
Методика Джексона основана на поиске соответствий структур исходных данных и результатов. Однако при ее применении возможны ситуации, когда на каких-то уровнях соответствия отсутствуют. Например, записи исходного файла сортированы не в том порядке, в котором соответствующие строки должны появляться в отчете. Такие ситуации были названы «столкновениями».
Методика Варнье-Орра базируется на том же положении, что и методика Джексона, но основными при построении программы считаются структуры выходных данных и, если структуры входных данных не соответствуют структурам выходных, то их допускается менять. Таким образом, ликвидируется основная причина столкновений. Однако на практике не всегда существует возможность пересмотра структур входных данных: эти структуры уже могут быть строго заданы, например, если данные получены при выполнении других программ, поэтому эту методику применяют реже.
4.2 Объектный подход
Как показывает практика, традиционные методы процедурного программирования не способны справиться ни с нарастающей сложностью программ и их разработки, ни с необходимостью повышения их надежности.
Когда в середине 80-х годов ХХ века для разработки программного обеспечения большого объема было предложено использовать объектный подход, в качестве основной технологии выбрано объектно-ориентированное программирование (ООП) - методика разработки программ, в основе которой лежит понятие объекта [18].
Объект - это некоторая структура, соответствующая объекту реального мира, его поведению. Каждый объект имеет состояние, обладает четко определенным поведением и уникальной идентичностью. Совокупность атрибутов (свойств) и их значений характеризует объект.
Объекты, описываемые одинаковыми наборами атрибутов, объединяются в классы. Данные класса называются полями, процедуры и функции — методами.
Все экземпляры одного класса (объекты, порожденные от одного класса) имеют один и тот же набор свойств и общее поведение, то есть одинаково реагируют на одинаковые сообщения. Каждый объект имеет определенное время жизни. В процессе выполнения программы или функционирования реальной системы, могут создаваться новые объекты и уничтожаться уже существующие.
Поскольку объект - это динамическая структура, переменная-объект содержит не данные, а ссылку на данные объекта. Поэтому программист должен позаботиться о выделении памяти для этих данных. Выделение памяти при создании объекта осуществляется при помощи специального метода класса – конструктора (constructor), а освобождение памяти при его уничтожении - при помощи деструктора (destructor).
Важнейшими понятиями ООП являются инкапсуляция, наследование, полиморфизм, которые позволяют конструировать сложные объекты из сравнительно простых. Программа, написанная с использованием ООП, состоит из множества объектов, взаимодействующих между собой путем передачи сообщений.
В основе объектного подхода к разработке программного обеспечения лежит объектная декомпозиция, т. е. представление разрабатываемого программного продукта в виде совокупности объектов, в процессе взаимодействия которых через передачу сообщений и происходит выполнение требуемых функций. Объектно-ориентированный подход имеет следующие преимущества:
а) уменьшение сложности программного обеспечения;
б) повышение надежности программного обеспечения;
в) обеспечение возможности модификации отдельных компонентов программного обеспечения без изменения остальных его компонентов;
г) обеспечение возможности повторного использования отдельных компонентов программного обеспечения.
Систематическое применение объектного подхода позволяет разрабатывать хорошо структурированные, надежные в эксплуатации, достаточно просто модифицируемые программные системы, поэтому ООП является одним из наиболее интенсивно развивающихся направлений теоретического и прикладного программирования. Однако при объектном подходе сразу можно выполнить декомпозицию только очень простого программного обеспечения.
На заре эпохи ООП были предложены методы анализа и проектирования в рамках объектного подхода, использующие различные модели и нотации. Спорить о достоинствах и недостатках этих методов и моделей можно было бесконечно. Эта ситуация получила название «войны методов». Конец «войне методов» положило появление в 1995 г. первой версии языка UML (Unified Modeling Language - унифицированный язык моделирования), который был создан ведущими специалистами в этой области (Гради Бучем, Иваром Якобсоном и Джеймсом Рамбо) и в настоящее время фактически признан стандартным средством описания проектов, создаваемых с использованием объектно-ориентированного подхода [2, 33, 34].
UML объединил лучшие современные технические приемы моделирования и разработки программного обеспечения. По сути, язык UML был задуман так, чтобы его можно было реализовать посредством его же инструментальных средств. Фактически это признание того, что большие современные программные системы, как правило, нуждаются в инструментальной поддержке. UML-диаграммы легко воспринимаются и при этом без труда генерируются компьютерами. UML объединил лучшие идеи «доисторических» методов, отказываясь от их наиболее специфических деталей.
Спецификация разрабатываемого программного обеспечения при использовании UML объединяет несколько моделей [6]: использования, логическую, реализации, процессов и развертывания (см. рисунок 4.3).
Рисунок 4.3 - Полная спецификация разрабатываемого программного обеспечения при объектном подходе (UML)
Логическая модель описывает ключевые абстракции ПО (классы, интерфейсы), т. е. средства, обеспечивающие требуемую функциональность.
Модель реализации определяет реальную организацию программных модулей в среде разработки.
Модель использования представляет собой описание функциональности программного продукта с точки зрения пользователя.
Модель процессов отображает организацию вычислений и оперирует понятиями «процессы» и «нити». Она позволяет оценить производительность, масштабируемость и надежность программного обеспечения.
Модель развертывания показывает особенности размещения программных компонентов на конкретном оборудовании.
Каждая из указанных моделей характеризует определенный аспект проектируемой системы, а все вместе они составляют относительно полную модель разрабатываемого программного продукта.
В процессе анализа требований необходимо понять, что именно ожидают от системы пользователи программного обеспечения. Для этого в распоряжении имеется множество приемов UML. В общей сложности UML2 предлагает тринадцать дополняющих друг друга диаграмм [2, 34], входящих в различные модели (см. рисунок 4.4). Все диаграммы используют единую графическую нотацию, что существенно облегчает их понимание.
В общем случае можно выделить два вида диаграмм UML: диаграмма структуры и диаграмма поведения.
Каждый из этих видов включает набор диаграмм, которые более детально с разных точек зрения описывают модели. Рассмотрим более подробно эти диаграммы.
В состав диаграммы структуры входят шесть диаграмм:
1) диаграмма классов описывает типы объектов системы и различного рода статические отношения, которые существуют между ними. Диаграмма классов строится с точки зрения концептуальной перспективы и может служить хорошим инструментом для построения точного словаря предметной области. На диаграммах классов отображаются также свойства классов, операции классов и ограничения, которые накладываются на связи между объектами;
Рисунок 4.4 – Классификация диаграмм UML
2) диаграмма пакетов демонстрирует взаимосвязи наборов классов, объединенных в пакеты (логические блоки системы, представляющие группы времени компиляции), между собой и помогает держать их под контролем. Фактически - это хорошая логическая маршрутная карта системы. Диаграммы пакетов исключительно удобны в больших по размерам системах для представления картины зависимостей между основными элементами системы;
3) диаграмма объектов - это снимок объектов системы в какой-то момент времени. Поскольку она показывает экземпляры, а не классы, то диаграмму объектов часто называют диаграммой экземпляров. Диаграмму объектов можно использовать для отображения одного из вариантов конфигурации объектов;
4) диаграмма компонентов показывает, из каких программных компонентов (элементов, которые можно независимо друг от друга купить и обновить) состоит программное обеспечение и как эти компоненты связаны между собой;
5) диаграмма развертывания (или диаграмма размещения) отражает физическое расположение системы, показывая, на каком физическом оборудовании запускается та или иная составляющая программного обеспечения;
6) диаграмма составных структур – новый вид диаграмм, появившийся в языке UML2. Одной из наиболее значимых новых черт языка UML2 является возможность превращать класс в иерархию внутренних структур. Это позволяет разбить сложный объект на составляющие - составные структуры, которые представляют группы времени выполнения.
В состав диаграммы поведения входят четыре основные диаграммы:
1) диаграмма прецедентов описывает типичные взаимодействия между пользователями системы и самой системой. В первой версии UML позиционировалась как диаграмма вариантов использования, которая демонстрировала основные функции системы для каждого типа пользователей. Фактически прецеденты – это способ записи требований или вариант использования системы одним из актеров (пользователей). Пример диаграммы прецедентов показан на рисунке 4.5;
2) диаграмма деятельности представляет собой схему потоков управления для решения некоторой задачи по отдельным действиям, допускают наличие параллельных и/или альтернативных действий. Это - технология, позволяющая описывать логику поведения системы, бизнес-процессы и потоки работ. Во многих случаях они напоминают блок-схемы, но в отличие от них поддерживают параллельное процессы;
3) диаграмма конечных автоматов (или диаграмма состояний) демонстрирует состояния одного объекта и условия переходов из одного состояния в другое. Средством моделирования динамического поведения объекта является конечный автомат;
4) диаграмма взаимодействия служит для уточнения основных аналитических диаграмм взаимодействий с дополнением деталей реализации, а также для иллюстрации технических вопросов, возникших при проектировании. К диаграммам взаимодействия относятся:
а) диаграмма последовательностей отображает упорядоченное по времени взаимодействие объектов в процессе выполнения варианта использования, акцент делается именно на последовательность взаимодействия;
б) коммуникационная диаграмма (в UML1 называлась диаграммой кооперации) - особый вид диаграмм взаимодействия, в которых внимание акцентируется на обмене данными между различными участниками взаимодействия;
в) диаграмма обзора взаимодействий - комбинация диаграмм деятельности и диаграмм последовательности, впервые появилась в UML2;
г) временная диаграмма - разновидность диаграммы взаимодействий, основное внимание в которой направлено на моделирование временных ограничений. Временная диаграмма идеально подходит для моделирования систем реального времени, а также полезна для обозначения временных интервалов между изменениями состояний различных объектов.
Рисунок 4.5 – Пример диаграммы прецедентов
Решение о том, какие именно диаграммы следует построить при анализе требований и в процессе проектирования программного обеспечения принимается непосредственно разработчиками применительно к конкретному проекту.
Дополнениями к диаграммам служат формализованные и неформализованные текстовые описания, комментарии и словари. При построении этих и других диаграмм используют унифицированную систему обозначений. UML и предлагаемая теми же авторами методика Rational Unified Process поддерживаются пакетом Rational Rose фирмы Rational Software Corporation. Ряд диаграмм UML можно построить также средствами программы Microsoft Visual Modeler и других CASE-средств.
5 глава. Пользовательские интерфейсы
Еще не так давно программисты использовали весьма ограниченный арсенал средств взаимодействия пользователей с создаваемыми программами. Как правило, такое взаимодействие заключалось в обмене текстовыми сообщениями либо псевдографическими изображениями. Пользовательский интерфейс рассматривался как средство общения человека с операционной системой и был достаточно примитивным. При этом «промышленное» программное изделие было ориентировано на людей, если не профессионалов, то достаточно хорошо знакомых с вычислительной техникой.
Однако в последние годы ситуация коренным образом изменилась.
С распространением персональных компьютеров невероятно возросло число их пользователей, в том числе не имеющих даже начальных знаний в области вычислительной техники. Значительно увеличилось и число программирующих пользователей ЭВМ, как имеющих соответствующую базовую подготовку, так и «самоучек», в распоряжении которых теперь имеются мощные средства разработки, позволяющие создавать программы с практически неограниченными интерактивными возможностями. Наконец наличие такого уникального средства общения, как Интернет, позволяет всем желающим выставлять на всеобщее обозрение плоды своего творчества, вне зависимости от их качества и предназначения.
В результате на свет стало появляться все больше программных продуктов-однодневок, которые снабжены ярким и впечатляющим интерфейсом в виде многочисленных и разнообразных кнопок, пиктограмм, переключателей и т.п., однако никакой пользы не приносят. С другой стороны, действительно полезные программы, снабженные неудачным интерфейсом, остаются невостребованными.
Известны случаи, когда достаточно крупные проекты были отклонены заказчиком только из-за того, что не были своевременно и качественно решены вопросы, связанные с пользовательским интерфейсом.
Кроме того, полнота использования потенциальных возможностей программного продукта зависит от качества пользовательского интерфейса.
Важность грамотной разработки пользовательского интерфейса давно осознана ведущими производителями программного обеспечения, а его качество регламентируются целым рядом соответствующих стандартов. Те программные продукты, которые им не удовлетворяют, практически не имеют шансов на «выживание».
В настоящее время основной проблемой является разработка интерактивных интерфейсов к сложным программным продуктам для непрофессиональных пользователей.
5.1 Основные понятия
Сложность понятия «пользовательский интерфейс» породила множество определений, которые менялись в процессе развития самого пользовательского интерфейса.
Пользовательский интерфейс часто понимают только как внешний вид программы, однако такое понимание является слишком узким. В действительности он объединяет в себе все элементы и компоненты программы, которые способны оказывать влияние на взаимодействие пользователя с программным обеспечением, а это уже не только экран, который видит пользователь. К элементам пользовательского интерфейса относятся:
- набор задач пользователя, которые он решает при помощи системы;
- используемая системой метафора (например, рабочий стол в Windows);
- элементы управления системой;
- навигация между блоками системы;
- визуальный (и не только) дизайн экранов программы;
- средства отображения информации, отображаемая информация и форматы;
- устройства и технологии ввода данных;
- диалоги, взаимодействие и транзакции между пользователем и компьютером;
- обратная связь с пользователем;
- поддержка принятия решений в конкретной предметной области;
- порядок использования программы и документация на нее.
Пользовательский интерфейс представляет собой совокупность программных и аппаратных средств, обеспечивающих взаимодействие пользователя с компьютером. Основу такого взаимодействия составляют диалоги.
Под диалогом понимают регламентированный обмен информацией между человеком и компьютером, осуществляемый в реальном масштабе времени и направленный на совместное решение конкретной задачи: обмен информацией и координация действий.
Каждый диалог состоит из отдельных процессов ввода-вывода, которые физически обеспечивают связь пользователя и компьютера. Обмен информацией осуществляется передачей сообщений и управляющих сигналов.
Сообщение - порция информации, участвующая в диалоговом обмене. Различают:
а) входные сообщения, которые генерируются человеком с помощью средств ввода: клавиатуры, манипуляторов, например мыши;
б) выходные сообщения, которые генерируются компьютером в виде текстов, звуковых сигналов и/или изображений и выводятся пользователю на экран монитора или другие устройства вывода информации (см. рисунок 5.1).
Рисунок 5.1 - Организация взаимодействия компьютера и пользователя
В основном пользователь генерирует сообщения следующих типов:
- запрос информации;
- запрос помощи;
- запрос операции или функции;
- ввод или изменение информации;
- выбор поля кадра и т. д.
В ответ пользователь получает от компьютера:
- подсказки или справки;
- информационные сообщения, не требующие ответа;
- приказы, требующие действий;
- сообщения об ошибках, нуждающиеся в ответных действиях;
- изменение формата кадра и т. д.
5.2 Виды пользовательских интерфейсов
Интерфейс - это, прежде всего, набор правил, которые можно обобщить, сгруппировать по общему признаку. Тогда вид интерфейса - это объединение по схожести способов взаимодействия человека и компьютеров. Среди различных интерфейсов общения человека и компьютера можно выделить:
1) командный интерфейс;
2) графический интерфейс;
3) речевой интерфейс;
4) мимический интерфейс;
5) семантический интерфейс.
5.2.1 Командный интерфейс.
Командный интерфейс получил свое название благодаря тому, что в этом виде интерфейса пользователь подает команды компьютеру, а компьютер их выполняет и выдает результат.
Командный интерфейс реализован в виде комбинации пакетной технологии и технологии командной строки.
Исторически пакетная технология появилась первой (Германия, 1937). Идея ее проста: на вход компьютера подается последовательность символов, в которых по определенным правилам указывается последовательность запущенных на выполнение программ. После выполнения программы запускается следующая по очередности и т.д. Машина по определенным правилам находит для себя команды и данные. В качестве последовательности может выступать перфолента, стопка перфокарт, последовательность нажатия клавиш электрической пишущей машинки. Машина также выдает свои сообщения на перфоратор, алфавитно-цифровое печатающее устройство, ленту пишущей машинки. Такая машина представляет собой «белый шкаф», в который постоянно подается информация и которая также постоянно информирует о своем состоянии. Пользователь практически не оказывает влияния на работу машины, поскольку он может лишь приостановить работу машины, сменить программу и вновь запустить компьютер.
С появлением алфавитно-цифровых дисплеев и увеличением мощности компьютеров началась эра новой пользовательской технологии – технологии командной строки.
При этой технологии в качестве единственного способа ввода информации от человека к компьютеру служит клавиатура, а компьютер выводит информацию человеку с помощью алфавитно-цифрового дисплея (монитора). Комбинация «монитор + клавиатура» получила название терминала, или консоли.
Команды набираются в командной строке, которая включает символ приглашения и мигающий прямоугольник - курсор. Команда заканчивается нажатием клавиши Enter, после чего осуществляется переход в начало следующей строки. Именно с этой позиции компьютер выдает на монитор результаты своей работы. Затем процесс повторяется.
Преобладающим видом файлов при работе с командным интерфейсом стали текстовые файлы - только их можно было создать при помощи клавиатуры. Интерфейс командной строки активно использовался в UNIX.
5.2.2 Графический интерфейс.
Идея появления графического интерфейса зародилась в середине 70-х годов ХХ века, когда в исследовательском центре Xerox Palo Alto Research Center (PARC) была разработана концепция визуального интерфейса. Его реализация стала возможной благодаря развитию технической базы компьютеров, уменьшению времени реакции компьютера на команду, а также увеличению объема оперативной памяти.
Первая система с графическим интерфейсом 8010 Star Information System группы PARC появилась в 1981 году. Первоначально визуальный интерфейс использовался только в программах. Постепенно он стал переходить и на операционные системы, используемых сначала на компьютерах Atari и Apple Macintosh, а затем и на IBM-совместимых компьютерах.
Характерной особенностью графических интерфейсов является то, что диалог с пользователем ведется не явно с помощью команд, а через графические образы. Этот вид интерфейса реализован на технологиях простого графического интерфейса и «чистого» WIMP - интерфейса.
Простой графический интерфейс первоначально был очень похож на технологию командной строки. Отличия от технологии командной строки заключались в следующем:
- при отображении символов допускалось выделение части символов цветом, инверсным изображением, подчеркиванием и мерцанием, благодаря чему повысилась выразительность изображения;
- в зависимости от конкретной реализации графического интерфейса курсор мог представляться не только мерцающим прямоугольником, но и некоторой областью другого цвета, охватывающей часть экрана;
- реакция на нажатие любой клавиши во многом зависела от того, в какой части экрана находился курсор;
- на клавиатуре стали использоваться «серые» клавиши управления курсором;
- стали использоваться манипуляторы (мышь, трекбол и т.п.), которые позволяли быстро выделять нужную часть экрана и перемещать курсор.
Появление этого типа интерфейса совпало с широким распространением операционной системы MS DOS. Простой графический интерфейс использовался в файловой оболочке Nortron Commander, редакторах Multi-Edit, Лексикон, ChiWriter и текстовый процессор Microsoft Word for Dos.
Вторым этапом в развитии графического интерфейса стал «чистый» интерфейс WIMP (Window - окно, Image - образ, Menu - меню, Pointer – указатель), который обладает следующими особенностями:
- работа с программами, файлами и документами ведется в окнах;
- программы, файлы, документы, устройства и другие объекты представляются в виде значков – иконок, которые при открытии превращаются в окна;
- действия с объектами осуществляются с помощью меню, которое становится основным элементом управления;
- манипулятор становится основным элементом управления. С его помощью указывают на любую область экрана, окна или иконки, выделяют ее, а уже потом осуществляют управление ими.
WIMP-интерфейс требует для своей реализации цветной растровый дисплей с высоким разрешением и манипулятор, а программы, ориентированные на этот вид интерфейса, предъявляют повышенные требования к производительности компьютера, объему его памяти, пропускной способности шины и т.п.
Этот вид интерфейса наиболее прост в усвоении и интуитивно понятен. Ярким примером программ с графическим интерфейсом является операционная система Microsoft Windows.
5.2.3 Речевой интерфейс.
В середине 90-х годов ХХ века, после появления недорогих звуковых карт и широкого распространения технологий распознавания речи, была разработана так называемая «речевая технология» - простейшая реализация SILK - интерфейса.
SILK - интерфейс (Speech - речь, Image - образ, Language - язык, Knowlege - знание) наиболее приближен к обычной, человеческой форме общения. Согласно технологии команды подаются голосом путем произнесения специальных зарезервированных слов – команд, т.е. ведется обычный «разговор» пользователя и компьютера. При этом компьютер находит для себя команды, анализируя человеческую речь и находя в ней ключевые фразы. Результат выполнения команд он также преобразует в понятную пользователю форму.
Этот вид интерфейса наиболее требователен к аппаратным ресурсам компьютера, и поэтому его применяют в основном для военных целей. Слова должны выговариваться четко, в одном темпе. Между словами обязательна пауза. Из-за неразвитости алгоритма распознавания речи такие системы требует индивидуальной предварительной настройки на каждого конкретного пользователя.
5.2.4 Мимический интерфейс.
В основу мимического интерфейса положена биометрическая технология, которая возникла в конце 90-х годов XX века.
Для управления компьютером используется выражение лица человека, направление его взгляда, размер зрачка и другие признаки. Для идентификации пользователя используется рисунок радужной оболочки его глаз, отпечатки пальцев и другая уникальная информация. Изображения считываются с цифровой видеокамеры, а затем с помощью специальных программ распознавания образов из этого изображения выделяются команды.
Эта технология актуальна для программных продуктов и приложений, где важно точно идентифицировать пользователя компьютера.
5.2.5 Семантический (общественный) интерфейс.
В конце 70-х годов XX века, с развитием искусственного интеллекта возник семантический (общественный) интерфейс. Его трудно назвать самостоятельным видом интерфейса, поскольку он включает и интерфейс командной строки, и графический, и речевой, и мимический интерфейс.
Его основная отличительная черта - это отсутствие команд при общении с компьютером. Запрос формируется на естественном языке, в виде связанного текста и образов. Фактически - это моделирование «общения» пользователя с компьютером.
С середины 90-х годов XX века в связи с важным военным значением этих разработок это направление было засекречены.
5.3 Типы пользовательских интерфейсов
Различают два основных подхода к разработке интерфейсов: процедурно-ориентированный и объектно-ориентированный подходы (см. рисунок 5.2).
Процедурно-ориентированные модели интерфейсов используют традиционную модель взаимодействия с пользователем, основанную на понятиях «процедура» и «операция». В рамках этой модели программное обеспечение предоставляет пользователю возможность выполнения некоторых действий, для которых пользователь определяет соответствующие данные и следствием выполнения которых является получение желаемых результатов.
Реализация современного процедурно-ориентированного пользователь-ского интерфейса на базе структурного подхода является очень сложной и трудоемкой задачей.
Объектно-ориентированные модели интерфейсов используют несколько иную модель взаимодействия с пользователем, ориентированную на манипулирование объектами предметной области. В рамках этой модели пользователю предоставляется возможность напрямую взаимодействовать с каждым объектом и инициировать выполнение операций, в процессе которых взаимодействуют несколько объектов. Пользователю предоставляется возможность создавать объекты, изменять их параметры и связи с другими объектами, а также инициировать взаимодействие этих объектов.
Элементы интерфейсов данного типа включены в пользовательский интерфейс Windows.
Рисунок 5.2 - Типы интерфейсов
В таблице 5.1 перечислены основные отличия пользовательских моделей интерфейсов процедурного и объектно-ориентированного типов.
Среди процедурно-ориентированных интерфейсов различают три типа: примитивные, меню и со свободной навигацией [22].
Примитивным называют интерфейс, который организует взаимодействие с пользователем в консольном режиме. Обычно такой интерфейс реализует конкретный сценарий работы программного обеспечения (ввод данных - решение задачи - вывод результата). Единственное отклонение от последовательного процесса, которое обеспечивается данным интерфейсом, заключается в организации цикла для обработки нескольких наборов данных. Подобные интерфейсы в настоящее время используют только в процессе обучения программированию или в тех случаях, когда вся программа реализует одну функцию, например, в некоторых системных утилитах.
Таблица 5.1 – Основные отличия пользовательских моделей интерфейсов
Процедурно-ориентированные пользовательские интерфейсы |
Объектно-ориентированные пользовательские интерфейсы |
Обеспечивают пользователей функциями, необходимыми для выполнения задач |
Обеспечивают пользователям возможность взаимодействия с объектами |
Акцент делается на задачи |
Акцент делается на входные данные и результаты |
Пиктограммы представляют приложения, окна или операции |
Пиктограммы представляют объекты |
Содержание папок и справочников отображается с помощью таблиц и списков |
Папки и справочники являются визуальными контейнерами объектов |
Интерфейс-меню позволяет пользователю выбирать необходимые операции из специального списка, выводимого ему программой. Эти интерфейсы предполагают реализацию множества сценариев работы, последовательность действий в которых определяется пользователем. Различают одноуровневые и иерархические меню. Интерфейсы данного типа несложно реализовать в рамках структурного подхода к программированию. Интерфейсы-меню в настоящее время используют редко и только для сравнительно простого программного обеспечения или в разработках, которые должны быть выполнены по структурной технологии и без использования специальных библиотек.
Интерфейсы со свободной навигацией также называют графическими пользовательскими интерфейсами (GUI - Graphic User Interface) или интерфейсами WYSIWYG (What You See Is What You Get - что видишь, то и получишь, т. е. что пользователь видит на экране, то он и получит при печати). Эти названия подчеркивают, что интерфейсы данного типа ориентированы на использование экрана в графическом режиме с высокой разрешающей способностью.
Графические интерфейсы поддерживают концепцию интерактивного взаимодействия с программным обеспечением, осуществляя визуальную обратную связь с пользователем и возможность прямого манипулирования объектами и информацией на экране. Кроме того, интерфейсы данного типа поддерживают концепцию совместимости программ, позволяя перемещать между ними информацию.
Интерфейс со свободной навигацией обеспечивает возможность осуществления любых допустимых в конкретном состоянии операций, доступ к которым возможен через различные интерфейсные компоненты. Например, окна программ, реализующих интерфейс Windows, обычно содержат меню различных типов (ниспадающее, кнопочное, контекстное), разного рода компоненты ввода данных. Причем выбор следующей операции в меню осуществляется как мышью, так и с помощью клавиатуры. Существенной особенностью интерфейсов данного типа является способность изменяться в процессе взаимодействия с пользователем, предлагая выбор только тех операций, которые имеют смысл в конкретной ситуации. Реализуют интерфейсы со свободной навигацией, используя событийное программирование и объектно-ориентированные библиотеки, что предполагает применение визуальных сред разработки программного обеспечения.
Объектно-ориентированные интерфейсы пока представлены только интерфейсом прямого манипулирования. Этот тип интерфейса предполагает, что взаимодействие пользователя с программным обеспечением осуществляется посредством выбора и перемещения пиктограмм, соответствующих объектам предметной области. Для его реализации используют событийное программирование и объектно-ориентированные библиотеки.
5.4 Особенности разработки пользовательских интерфейсов
При проектировании пользовательских интерфейсов необходимо учитывать психофизические особенности человека, связанные с восприятием, запоминанием и обработкой информации. Исследованием принципов работы мозга человека занимается когнитивная психология [16].
Информация о внешнем мире поступает в мозг в огромных количествах. При этом краткосрочная память является своего рода оперативной памятью мозга, невостребованная информация хранится в ней не более 30 секунд. Ее емкость приблизительно равна 7 ± 2 несвязанных объектов. Чтобы не забыть важную информацию, мы обычно повторяем ее «про себя», «обновляя» информацию в краткосрочной памяти. Поэтому при проектировании интерфейсов следует иметь в виду, что большинству людей сложно, например, запомнить и ввести на другом экране число, содержащее более 5 цифр (7 - 2), или некоторое сочетание букв.
Каждый человек вносит в деятельность свое понимание того, как она должна выполняться. Это понимание - модель деятельности - базируется на его прошлом опыте. Множество таких моделей хранится в долговременной памяти человека - хранилище информации с неограниченной емкостью и временем хранения. В нее записываются постоянно повторяемые сведения или информация, связанная с сильными эмоциями. Однако механизмы извлечения информации из памяти имеют ассоциативный характер. Специальная методика запоминания информации (мнемоника) использует именно это свойство памяти: для запоминания информации ее «привязывают» к тем данным, которые память уже хранит и позволяет легко получить. Поскольку доступ к долговременной памяти затруднен, целесообразно рассчитывать не на то, что пользователь вспомнит нужную информацию, а на то, что он ее узнает.
Кроме того, важную роль при разработке дизайна интерфейсов играют цвет, звук, восприятие времени, использование анимации.
Цвет является для человека сильным раздражителем, поэтому применять цвета в интерфейсе необходимо крайне осторожно. Следует иметь в виду, что обилие оттенков привлекает внимание, но быстро утомляет. Не стоит ярко раскрашивать окна, с которыми пользователь будет долго работать. Необходимо учитывать и индивидуальные особенности восприятия цветов человеком: примерно каждый десятый плохо различает какие-либо цвета, поэтому в ответственных случаях необходимо предоставить пользователю возможность их настройки.
В интерфейсах звук используют с разными целями:
- для привлечения внимания;
- как фон, обеспечивающий некоторое состояние пользователя;
- как источник дополнительной информации.
Применяя звук, следует учитывать, что большинство людей очень чувствительны к звуковым сигналам, особенно, если они указывают на наличие ошибки. Поэтому при создании звукового сопровождения целесообразно предусматривать возможность его отключения.
Человеку свойственно субъективное восприятие времени. Считают, что внутреннее время связано со скоростью и количеством воспринимаемой и обрабатываемой информации. Занятый человек времени не замечает. Зато в состоянии ожидания время тянется бесконечно: в это время мозг оказывается в состоянии информационного вакуума. Доказано, что при ожидании более 1-2 секунд пользователь может отвлечься, «потерять мысль», что увеличивает усталость и неблагоприятно сказывается на результатах работы. Сократить время ожидания можно, заняв пользователя, но не отвлекая его от работы. Например, предоставить ему какую-либо информацию для обдумывания или выводить промежуточные результаты.
Известны попытки использования для «развлечения» пользователя анимации. Однако интересно смотреть анимацию первый раз, многократный просмотр одного и того же начинает раздражать. Поэтому необходимо соблюдать основное правило: информировать пользователя, что заказанные операции потребуют некоторого времени выполнения, используя индикаторы оставшегося времени, анимацию или изменение формы курсора мыши на песочные часы. Важно точно обозначить момент, когда система готова продолжать работу, для чего значительно изменяют внешний вид экрана.
В итоге взаимодействие пользователя с интерфейсом определяется не только его физическими возможностями и особенностями по восприятию информации, но и пользовательской моделью интерфейса.
Существуют три модели пользовательского интерфейса: модель программиста, модель пользователя, программная модель.
Программист при разработке интерфейса исходит из того, управление какими операциями нужно реализовать в нем, и как это осуществить, не затрачивая существенных ресурсов компьютера, своих сил и времени. Его интересуют эффективность, функциональность, технологичность, внутренняя стройность и другие не связанные с удобством пользователя характеристики программного обеспечения. Именно поэтому большинство интерфейсов существующих программ вызывают серьезные нарекания пользователей.
С точки зрения здравого смысла хорошим считается интерфейс, при работе с которым пользователь получает именно то, что он ожидал. Представление пользователя о функциях интерфейса можно описать в виде пользовательской модели интерфейса - совокупности обобщенных представлений конкретного пользователя или группы пользователей о процессах, происходящих во время работы программной системы. Модель базируется на особенностях опыта конкретных пользователей, который характеризуется уровнем подготовки в предметной области разрабатываемого программного обеспечения, интуитивными моделями выполнения операций в этой области, уровнем подготовки в области владения компьютером, а также устоявшимися стереотипами работы с компьютером. Для ее построения необходимо изучить особенности опыта предполагаемых пользователей, для чего используют опросы, тесты и фиксируют на пленку последовательность выполнения операций в реальном процессе.
Приведение в соответствие моделей пользователя и программиста, а также построение на их базе программной модели интерфейса (см. рисунок 5.3) - задача не простая.
Рисунок 5.3 - Процесс разработки пользовательского интерфейса
Чем сложнее автоматизируемая предметная область, тем сложнее строить программную модель интерфейса, учитывающую особенности модели программиста и пользовательской модели. С этой точки зрения наиболее перспективны объектные интерфейсы, так как в их основе лежит отображение объектов предметной области, которыми оперируют пользователи.
Основой для разработки интерфейса должны стать интуитивные модели выполнения операций в предметной области. Нежелание или невозможность следования интуитивным моделям приводит к созданию искусственных надуманных интерфейсов, которые негативно воспринимаются пользователями.
Основное достоинство хорошего интерфейса пользователя заключается в том, что пользователь всегда чувствует, что он управляет программным обеспечением, а не программное обеспечение управляет им. Для создания у пользователя такого ощущения «внутренней свободы» при разработке интерфейсов следует придерживаться целого ряда «заповедей»:
1) следует помнить, что обязанность интерфейса – обеспечить взаимодействие пользователя и компьютера;
2) интерфейс должен быть понятным: для его эффективного использования пользователь должен понимать, что именно представляет интерфейс, какие задачи можно выполнять с его помощью, к чему приведет то или иное действие;
3) для обеспечения использования продукта жизненно важный фактором является внимание пользователей, которое необходимо удерживать любой ценой, поэтому не следует засорять интерфейс элементами, отвлекающими внимание от главного назначения того или иного созданного вами экрана;
4) пользователь должен чувствовать, что ситуация под его контролем; для этого следует периодически отображать состояние системы, описывать причинно-следственные связи («если вы сделаете …, то случится …») и давать понять пользователю, чего можно ожидать от каждой конкретной операции;
5) лучшее управление - прямое управление: интерфейс должен быть максимально незаметным и способным распознавать естественные человеческие жесты, тогда у пользователя появится ощущение, будто он управляет объектом напрямую;
6) каждый отдельный экран приложения должен служить для выполнения какой-либо одной задачи, стоящей перед пользователем;
7) главные и второстепенные задачи необходимо разделять, т.е. второстепенные задачи не должны выходить на первый план: они могут быть оформлены менее заметным образом или отображаться только после того, как была выполнена ключевая задача;
8) пользователь должен понимать, как поведет себя тот или иной элемент интерфейса, едва взглянув на него, следовательно, несхожие в поведении элементы должны оформляться по-разному;
9) следует обращать внимание на четкость визуальной иерархии: элементы на экране должны каждый раз располагаться в определенном порядке;
10) грамотная организация контента может значительно снизить когнитивную нагрузку пользователей;
11) цветом можно выделять объекты, привлекая к ним внимание пользователей, но при этом элементы нельзя разделять только по цвету: если предполагается работать с каким-либо элементом продолжительное время или элемент содержит объемный текст, рекомендуется использовать для оформления бледные или приглушенные тона, а яркие оттенки - для расстановки акцентов;
12) по возможности рабочий процесс следует распределить на несколько экранов, раскрывая информацию постепенно: на каждом экране должно отображаться только самое необходимое;
13) подсказки должны быть контекстно-зависимыми и появляться только тогда и там, где они нужны, в остальное время оставаясь скрытыми;
14) первый экран, который видит пользователь, не должен быть пустым - на нем должны содержаться указания и подсказки для быстрого начала работы;
15) интерфейс, ориентированный на решение потенциальных проблем, никому не нужен: следует разрабатывать интерфейс в соответствии с актуальными проблемами.
Кроме того, необходимо:
- проектировать и разрабатывать интерфейс пользователя как отдельный компонент создаваемого приложения;
- учитывать возможности и особенности аппаратно-программных средств, на базе которых реализуется интерфейс;
- учитывать особенности и традиции той предметной области, к которой относится создаваемое приложение.
6 глава. Тестирование и отладка программных продуктов
6.1 Основы тестирования программного обеспечения
Недостаточно выполнить проектирование и кодирование программного продукта, также необходимо обеспечить его соответствие требованиям и спецификациям. Многократно проводимые исследования показали, что чем раньше обнаруживаются те или иные несоответствия или ошибки, тем больше вероятность их исправления и ниже его стоимость [32].
Современные технологии разработки программного обеспечения предусматривают раннее обнаружение ошибок за счет выполнения контроля результатов всех этапов и стадий разработки. На начальных этапах контроль осуществляют вручную или с использованием CASE-средств, на последних - он принимает форму тестирования.
Тестирование - это процесс выполнения программы, целью которого является выявление ошибок. Никакое тестирование не может доказать отсутствие ошибок в сложном программном обеспечении, поскольку выполнение полного тестирования становится невозможным и имеется вероятность, что остались невыявленные ошибки. Соблюдение основных правил тестирования и научно обоснованный подбор тестов может уменьшить их количество.
6.1.1 Основные принципы организации процесса тестирования.
Процесс разработки согласно современной модели жизненного цикла программного обеспечения предполагает три стадии тестирования:
- автономное тестирование компонентов программного обеспечения;
- комплексное тестирование программного обеспечения;
- системное или оценочное тестирование на соответствие основным критериям качества.
Доля стоимости тестирования в общей стоимости разработки возрастает при увеличении сложности программного обеспечения и повышении требований к его качеству. Для повышения качества тестирования рекомендуется соблюдать следующие принципы:
а) предполагаемые результаты должны быть известны до тестирования;
б) следует избегать тестирования программы автором;
в) необходимо досконально изучать результаты каждого теста;
г) необходимо проверять действия программы на неверных данных;
д) необходимо проверять программу на неожиданные побочные эффекты на неверных данных.
Вероятность наличия необнаруженных ошибок в части программы пропорциональна количеству ошибок уже найденных в этой части. Удачным считают тест, который обнаруживает хотя бы одну ошибку. Формирование набора тестов имеет большое значение, поскольку тестирование является одним из наиболее трудоемких этапов создания программного обеспечения.
6.1.2 Основные подходы и методы тестирования.
Существуют два принципиально различных подхода к формированию тестовых наборов: структурный и функциональный.
Структурный подход базируется на том, что известна структура тестируемого программного обеспечения, в том числе его алгоритмы («стеклянный ящик»). Тесты строятся для проверки правильности реализации заданной логики в коде программы.
В основе структурного тестирования лежит концепция максимально полного тестирования всех маршрутов, предусмотренных алгоритмом (последовательности операторов программы, выполняемых при конкретном варианте исходных данных). Недостатки: построенные тестовые наборы не обнаруживают пропущенных маршрутов и ошибок, зависящих от заложенных данных; не дают гарантии, что программа правильна.
Функциональный подход основывается на том, что структура программного обеспечения неизвестна. В этом случае тесты строят, опираясь на функциональные спецификации. Этот подход называют также подходом, управляемым данными, так как при его использовании тесты строят на базе различных способов декомпозиции множества данных. Наборы тестов, полученные в соответствии с методами этих подходов, объединяют, обеспечивая всестороннее тестирование программного обеспечения.
При функциональном тестировании программа рассматривается как «черный ящик», а целью тестирования является выяснение обстоятельств, когда поведение программы не соответствует спецификации. Для обнаружения всех ошибок необходимо выполнить исчерпывающее тестирование (при всех возможных наборах данных), что для большинства случаев невозможно. Поэтому обычно выполняют «разумное» или «приемлемое» тестирование, ограничивающееся прогонами программы на небольшом подмножестве всех возможных входных данных. При функциональном тестировании различают следующие методы формирования тестовых наборов: эквивалентное разбиение; анализ граничных значений; анализ причинно-следственных связей; предположение об ошибке.
На ранних этапах разработки используют ручной контроль. Все проектные решения анализируются с точки зрения их правильности и целесообразности как можно раньше, пока их можно легко пересмотреть.
Различают статический и динамический подходы к ручному контролю. При статическом подходе анализируют структуру, управляющие и информационные связи программы, ее входные и выходные данные. При динамическом - выполняют ручное тестирование (вручную моделируют процесс выполнения программы на заданных исходных данных).
Исходными данными для таких проверок являются: техническое задание, спецификации, структурная и функциональная схемы программного продукта, схемы отдельных компонентов, а для более поздних этапов - алгоритмы и тексты программ, а также тестовые наборы. Доказано, что ручной контроль способствует существенному увеличению производительности и повышению надежности программ и с его помощью можно находить от 30 до 70 % ошибок логического проектирования и кодирования.
Основными методами ручного контроля являются: инспекции исходного текста, сквозные просмотры, проверка за столом, оценки программ.
При комплексном тестировании используют тесты, построенные по методам эквивалентных классов, граничных условий и предположении об ошибках, поскольку структурное тестирование для него не применимо.
Одним из самых сложных является вопрос о завершении тестирования, так как невозможно гарантировать, что в программе не осталось ошибок. Часто тестирование завершают потому, что закончилось время, отведенное на его выполнение. Его сворачивают, обходясь минимальным тестированием [19], которое предполагает: тестирование граничных значений, тщательную проверку руководства, тестирование минимальных конфигураций технических средств, возможности редактирования команд и повторения их в любой последовательности, устойчивости к ошибкам пользователя.
После завершения комплексного тестирования приступают к оценочному тестированию, целью которого является поиск несоответствий техническому заданию. Оценочное тестирование включает:
- тестирование удобства использования;
- тестирование на предельных объемах;
- тестирование на предельных нагрузках;
- тестирование удобства эксплуатации;
- тестирование защиты;
- тестирование производительности;
- тестирование требований к памяти;
- тестирование конфигурации оборудования;
- тестирование совместимости;
- тестирование удобства установки и обслуживания;
- тестирование надежности;
- тестирование восстановления;
- тестирование документации.
Таким образом, при разработке программного обеспечения нужно придерживаться следующих принципов:
1) главное правило тестирования - не избегайте тестирования;
2) практически доказано: чем лучше изначально написан код, тем меньше ошибок он будет содержать;
3) тестирование граничных условий непосредственно при написании кода - эффективный способ удалить множество мелких глупых ошибок;
4) необходимо активно использовать автоматизированное тестирование, поскольку машины не делают ошибок, не устают и не занимаются самообманом;
5) проведение тестирования после внесения каждого, даже небольшого, изменения - это верный способ локализации источника проблем, поскольку новые ошибки появляются, как правило, именно в новом коде.
6.2 Отладка программного обеспечения
Отладка - это процесс локализации и исправления ошибок, обнаруженных при тестировании программного обеспечения.
Под локализацией ошибки понимают определение оператора программы, выполнение которого вызвало нарушение вычислительного процесса. Для исправления ошибки необходимо определить ее причину.
Отладка требует от программиста глубоких знаний специфики управления используемыми техническими средствами, операционной системы, среды и языка программирования, реализуемых процессов, природы и специфики ошибок, методик отладки и соответствующих программных средств. По своей сути, отладка психологически дискомфортна, поскольку нужно искать собственные ошибки в условиях ограниченного времени. Кроме того, отладка оставляет возможность взаимовлияния ошибок в разных частях программы. Четко сформулированные методики отладки отсутствуют.
6.2.1 Классификация ошибок.
В зависимости от этапа обработки, на котором могут проявляться ошибки, различают:
а) синтаксические ошибки – сопровождаются комментарием с указанием их местоположения, фиксируются компилятором (транслятором) при выполнении синтаксического и частично семантического анализа;
б) ошибки компоновки - обнаруживаются компоновщиком (редактором связей) при объединении модулей программы;
в) ошибки выполнения - обнаруживаются аппаратными средствами, операционной системой или пользователем при выполнении программы, проявляются разными способами и в свою очередь делятся на группы:
1) ошибки определения исходных данных (ошибки передачи, ошибки преобразования, ошибки перезаписи и ошибки данных);
2) логические ошибки проектирования (неприменимый метод, неверный алгоритм, неверная структура данных, другие) и кодирования (ошибки некорректного использования переменных, вычислений, межмодульного интерфейса, реализации алгоритма, другие);
3) ошибки накопления погрешностей результатов вычислений (игнорирование ограничений разрядной сетки и способов уменьшения погрешности).
6.2.2 Методы обнаружения ошибок.
Отладка программы в любом случае предполагает обдумывание и логическое осмысление всей имеющейся информации об ошибке. При правильном подходе отладка может превратиться в удовольствие типа разгадывания головоломки. Хорошо написанный код сразу содержит меньше ошибок, а те, что все же имеются, гораздо легче обнаружить. Большинство ошибок можно обнаружить по косвенным признакам посредством тщательного анализа текстов программ и результатов тестирования без получения дополнительной информации с помощью следующих методов:
а) ручного тестирования (при обнаружении ошибки нужно выполнить тестируемую программу вручную, используя тестовый набор, при работе с которым была обнаружена ошибка);
б) индукции (метод основан на тщательном анализе симптомов ошибки, которые могут проявляться как неверные результаты вычислений или как сообщение об ошибке);
в) дедукции (вначале формируют множество причин, которые могли бы вызвать данное проявление ошибки, а затем, анализируя причины, исключают те, которые противоречат имеющимся данным);
г) обратного прослеживания (для точки вывода неверного результата строится гипотеза о значениях основных переменных, которые могли бы привести к получению данного результата, а затем, исходя из этой гипотезы, делают предположения о значениях переменных в предыдущей точке).
Для получения дополнительной информации об ошибке выполняют добавочные тесты и используют специальные методы и средства:
- отладочный вывод;
- интегрированные средства отладки;
- независимые отладчики.
Общая методика отладки программных продуктов, написанных для выполнения в операционных системах MS DOS и Win32, предполагает:
1 этап - изучение проявления ошибки;
2 этап – определение локализации ошибки;
3 этап - определение причины ошибки;
4 этап — исправление ошибки;
5 этап - повторное тестирование.
Процесс отладки можно существенно упростить, если следовать основным рекомендациям структурного подхода к программированию:
а) программу наращивать «сверху-вниз», от интерфейса к обрабатывающим подпрограммам, тестируя ее по ходу добавления подпрограмм;
б) выводить пользователю вводимые им данные для контроля и проверять их на допустимость сразу после ввода;
в) предусматривать вывод основных данных во всех узловых точках алгоритма (ветвлениях, вызовах подпрограмм).
7 глава. Составление программной документации
Одним из главных отличий программы от программного продукта является наличие разнообразной, хорошо подготовленной документации.
Составление программной документации - важный процесс. На каждый программный продукт должна разрабатываться документация двух типов [16]: для пользователей различных групп и для разработчиков. Отсутствие документации любого типа для конкретного программного обеспечения недопустимо.
К программным относят документы, содержащие сведения, необходимые для разработки, сопровождения и эксплуатации программного обеспечения.
Документирование программного обеспечения осуществляется в соответствии с Единой системой программной документации (ГОСТ 19.ХХХ).
В Республике Казахстан с этой целью разработаны и используются стандарты: СТ РК ИСО/МЭК 6592 «Руководство по документированию компьютерных прикладных систем» и СТ РК 34.010-2002 «Информационная технология. Порядок проведения экспертизы программной документации».
Оба стандарта базируются на документе ГОСТ 19.101-77, который устанавливает виды программных документов для программного обеспечения различных типов.
К основным программным документам по этому стандарту относятся: спецификация, ведомость держателей подлинников, текст программы, описание программы, ведомость эксплуатационных документов, формуляр, описание применения, руководство системного программиста, руководство программиста, руководство оператора, описание языка, руководство по техническому обслуживанию, программа и методика испытаний, пояснительная записка.
Допускается объединять отдельные виды эксплуатационных документов. Необходимость объединения указывается в техническом задании, а имя берут у одного из объединяемых документов. При оформлении текстовых и графических материалов, входящих в программную документацию, также следует придерживаться действующих стандартов. Рассмотрим подробнее некоторые из перечисленных документов.
Самым главным документом для разработчиков является техническое задание (ТЗ), в котором описываются цели и задачи работы, заказчик и исполнители, технические требования, сроки и этапы, требования секретности, форс-мажорные обстоятельства и правила предъявления результатов. Техническое задание должно быть составлено таким образом, чтобы исключить возможные разночтения, все требования должны быть сформулированы так, чтобы их можно было проверить однозначным образом.
Следующим по важности документом является программа и методика испытаний (ПМИ). Структурно она подобна ТЗ: практически для каждого пункта ТЗ в ПМИ говорится, как этот пункт будет проверяться. Способы проверки могут быть самыми разными – от пропуска специального теста до изучения исходных текстов программы, но они должны быть предусмотрены заранее, а не придумываться в момент испытаний. Новички приступают к составлению ПМИ непосредственно перед завершением работ, а опытные руководители составляют и согласовывают с заказчиками одновременно с ТЗ. Хорошо составленная ПМИ является гарантией успешной сдачи работ.
Руководство системного программиста, на современном языке называется руководством по инсталляции. В нем описывается порядок установки системы, как проверить корректность поставленной системы, как вносить изменения и т.п. Обычно это простой короткий документ.
Руководство оператора (пользователя) – это основной документ, описывающий, как пользоваться системой [11]. В хорошем руководстве сначала описывается идея системы, основные функции и как ими пользоваться, а уже потом идет описание всех клавиш и меню.
Руководство программиста - это самый объемный документ, описывающий внутреннюю организацию программы. Обычно этот документ идет в паре с документом «Текст программы» – одностраничным документом с оглавлением дискеты или CD. Руководство программиста дает заказчику возможность дописать новые фрагменты программы или переделать старые. В современной литературе этот документ называется SDK (Software Development Kit). Продукт, снабженный SDK, может стоить на порядок дороже, чем такой же продукт без него.
Сейчас не принято продавать исходные тексты программ – проблемы с интеллектуальной собственностью. Даже при наличии SDK трудно «влезть» в чужую программу – как говорится, себе дороже. Поэтому большое распространение получили API (Application Program Interface). Программа передается только в виде DLL (библиотека двоичных кодов), при этом известно, как обратиться к каждой функции из других программ, т.е. известно имя точки входа, количество, типы и значения параметров. Наличие множества API, конечно, хуже, чем наличие исходных текстов (например, нельзя переделать что-то в середине функции), зато много проще в использовании.
С другой стороны, все большую популярность приобретает FSF (Free Software Foundation). Основателем этого движения был Ричард Столман [32], который забил тревогу по поводу попыток крупных фирм запатентовать многие основные алгоритмы и программы: «Дойдет до того, что они запатентуют понятия цикл и подпрограмма, что мы будем тогда делать?».
FSF представляет собой собрание программ в исходных текстах. Любой программист может свободно использовать их в своих целях, но все добавления и улучшения, которые он сделал, тоже следует положить в FSF. Таким образом, FSF представляет собой одно из самых больших доступных хранилищ программ.
В любом случае, при подготовке документации не следует забывать, что она разрабатывается для того, чтобы ее использовали, и потому она должна содержать все необходимые сведения.
Заключение
Большинство современных систем объективно очень сложны, что обусловлено логической сложностью решаемых ими задач. Причем, в процесс компьютеризации вовлекаются все новые и новые области человеческой деятельности, а для уже освоенных областей еще больше усложняются постановки задач. Компьютерная техника из средства решения отдельных задач стремительно превращается в средство информационного моделирования реального мира, что позволяет человеку получать исчерпывающие ответы на интересующие его вопросы. Это существенно изменяет направленность технологии программирования.
Решающую роль теперь играет человеческий фактор и поэтому в настоящее время большое внимание уделяется понятиям качества и надежности программных продуктов. Предпочтение отдается не столько эффективности, сколько удобству работы с программным обеспечением для пользователей. Кажущиеся на первый взгляд простота и удобство пользовательского интерфейса на самом деле – результат кропотливого труда профессионалов, использующих сложные современные технологии разработки программного обеспечения.
Создание современной программной системы – задача весьма трудоемкая, особенно когда обычный объем программ превышает сотни тысяч операторов. Специалист в области разработки системного программного обеспечения должен иметь представление о методах анализа, проектирования, реализации и тестирования программных систем, а также свободно ориентироваться в существующих подходах и технологиях.
Каждый из этапов разработки программного обеспечения нуждается в детальном изучении. Небрежности и ошибки, допущенные на начальных этапах, могут привести к катастрофическим последствиям в процессе реализации. В этой связи большое внимание уделяется вопросам тестирования, отладки и своевременного документирования программного обеспечения.
Кроме того, в настоящее время уже невозможно представить процесс разработки систем без использования средств автоматизации. С этой целью практически на всех этапах успешно используются CASE-технологии, которые поддерживают различные подходы к программированию.
Грамотное использование опыта разработки программных продуктов позволит будущим специалистам в области автоматизации разрабатывать и внедрять в производство сложные автоматизированные системы и комплексы управления.
Приложение А
Образец выполнения технического задания
ТЕХНИЧЕСКОЕ ЗАДАНИЕ НА РАЗРАБОТКУ СИСТЕМЫ УЧЕТА УСПЕВАЕМОСТИ СТУДЕНТОВ
1 Введение
Настоящее техническое задание распространяется на разработку системы учета успеваемости студентов, предназначенной для сбора и хранения информации о ходе сдачи экзаменационной сессии. Предполагается, что использовать данную систему будут сотрудники деканата, декан и его заместители. Во время сессии необходимо получение оперативной информации о ходе ее сдачи студентами, однако выполнение такого контроля вручную требует значительного времени. Автоматизированная система учета успеваемости позволит улучшить качество контроля сдачи сессии со стороны куратора и деканата и обеспечит получение сведений о динамике работы каждого студента, группы и курса в целом. Кроме того, хранение информации о сдаче сессий в течение всего времени обучения позволит осуществлять автоматическую генерацию справок о прослушанных курсах и приложений к диплому выпускника.
2 Основание для разработки
Система разрабатывается на основании приказа декана теплоэнергетического факультета № 15 от 24 сентября 2011 г. и в соответствии с планом мероприятий по совершенствованию учебного процесса на 20112012 учебный год.
3 Назначение
Система предназначена для хранения и обработки сведений об успеваемости студентов учебных групп факультета в течение всего срока обучения. Обработанные сведения об успеваемости студентов могут быть использованы для оценки успеваемости каждого студента, группы, курса и факультета в целом.
4 Требования к программе или программному изделию
4.1 Требования к функциональным характеристикам
4.1.1 Система должна обеспечивать возможность выполнения следующих функций:
- инициализацию системы (ввод списков групп, перечней дисциплин и т. п.);
- ввод и коррекцию текущей информации о ходе сдачи сессии конкретными студентами;
- хранение информации об успеваемости в течение времени обучения студента;
- получение сведений о текущем состоянии сдачи сессии студентами.
4.1.2 Исходные данные:
- списки студентов учебных групп;
- учебные планы кафедр;
- расписания сессий;
- текущие сведения о сдаче сессии каждым студентом.
4.1.3 Результаты:
- итоги сдачи сессии конкретным студентом;
- итоги сдачи сессии студентами конкретной группы;
- процент успеваемости по всем студентам группы при сдаче конкретного предмета в целом на текущий момент;
- проценты успеваемости по всем группам специальности на текущий момент;
- проценты успеваемости по всем группам курса на текущий момент;
- проценты успеваемости по всем курсам и по факультету на текущий момент;
- список задолжников группы на текущий момент;
- список задолжников курса на текущий момент.
4.2 Требования к надежности
4.2.1. Предусмотреть контроль вводимой информации.
4.2.2. Предусмотреть блокировку некорректных действий пользователя.
4.2.3. Обеспечить целостность хранимой информации.
4.3 Требования к составу и параметрам технических средств
4.3.1. Система должна работать на IBM совместимых персональных компьютерах.
4.3.2. Минимальная конфигурация: тип процессора - Pentium и выше; объем оперативного запоминающего устройства - 32 Мб и более.
4.4 Требования к информационной и программной совместимости
Система должна работать под управлением семейства ОС Windows.
5 Требования к программной документации
5.1 Разрабатываемые программные модули должны быть самодокументированы, т.е. тексты программ должны содержать все необходимые комментарии.
5.2 Программная система должна включать справочную информацию о работе и подсказки пользователю.
5.3 В состав сопровождающей документации должны входить:
5.3.1 Пояснительная записка, содержащая описание разработки.
5.3.2 Руководство системного программиста.
5.3.3 Руководство пользователя.
5.3.4 Графическая часть на трех листах формата А3 (блок-схемы алгоритмов): структурная схема; диаграмма компонентов данных; формы интерфейса пользователя.
6 Этапы разработки
№ |
Название этапа |
Срок |
Отчетность |
1 |
Проектирование программного продукта |
01.10.2011-01.11.2011 |
Разработка технического задания и уточнение спецификаций. Принятие принципиальных решений. Алгоритмов решения задачи. Проек-тирование структурной и функциональной схем системы учета успеваемости. |
2 |
Реализация |
01.12.2011-29.02.2012 |
Описание внутренних форматов, интерфейса и форматов данных базы. Реализация системы на уровне интерфейса. Реализация программных модулей задачи. |
3 |
Тестирование и составление документации |
01.03.2012-30.04.2012 |
Результаты тестов. Программная документация. |
Список литературы
1. Аляев Ю.А., Козлов О.А. Алгоритмизация и языки программ-мирования Pascal, C++, Visual Basic. – М.: Финансы и статистика, 2004.
2. Арлоу Д., Нейштадт И. UML2 и Унифицированный процесс. Практический объектно-ориентированный анализ и проектирование. – СПб.: Символ-Плюс, 2007.
3. Ашарина И.В. Основы программирования на языках С и С++.- М.: Горячая линия - Телеком, 2002.
4. Бахман П., Френцель М., Ханцшманн К и др. Программные системы. – М.: Мир, 1988.
5. Бек Кент. Экстремальное программирование — СПб: Питер, 2002.
6. Буч Г., Рамбо Д., Джекобсон А. Язык UML. Руководство пользователя. – М.: ДМК Пресс, 2001.
7. Вендров А.М. CASE-технологии. Современные методы и средства проектирования информационных систем. - М.: Финансы и статистика, 1998.
8. Вирт Н. Алгоритмы и структуры данных. – М.: Мир, 1989.
9. Гома Х. UML-проектирование систем реального времени параллельных и распределенных приложений. – М.: ДМК Пресс, 2011.
10. ГОСТ 19.701-90 ЕСПД. Схемы алгоритмов, программ, данных и систем. Условные обозначения и правила выполнения. – М.: Изд-во стандартов, 1990.
11. Гримм С.Дж. Как писать руководства для пользователей. – М.: Радио и связь, 1985.
12. Евстигнеев В.А., Городняя Л.В., Густокашина Ю.В. Язык функционального программирования SISAL. Интеллектуализация и качество программного обеспечения. - Новосибирск, 1994.
13. Ершов А.П. Научные основы доказательного программирования. Избранные труды. - Новосибирск, Наука, 1994.
14. Жоголев Е.А. Технологические основы модульного программирования. - М.: Программирование, 1980.
15. Иванов Д., Новиков Ф. Моделирование на UML. Учебно-методическое пособие. – СПб.: СПбГУ ИТМО, 2010.
16. Иванова Г.С. Технология программирования. - М.: Изд-во МГТУ им. Н.Э.Баумана, 2002.
17. Иванова Г.С. Основы программирования. - М.: Изд-во МГТУ им. Н.Э.Баумана, 2001.
18. Иванова Г.С., Ничушкина Т.Н., Пугачев Е.К. Объектно-ориентированное программирование: учебник для вузов. – М.: Изд-во МГТУ им. Н.Э.Баумана, 2001.
19. Канер С., Фолк Д., Нгуен Е.К. Тестирование программного обеспечения. – Киев, ДиаСофт, 2000.
20. Кантор М. Управление программными проектами. Практическое руководство по разработке успешного программного обеспечения. - М.: Вильямс, 2002.
21. Кватрани Т. Rational Rose 2000 и UML. Визуальное моделирование. - М.: ДМК Пресс, 2001.
22. Мандел Т. Разработка пользовательского интерфейса. – М.: ДМК Пресс, 2001.
23. Майерс Г. Надежность программного обеспечения. - М.: Мир, 1980.
24. Непейвода Н.Н. Стили и методы программирования. Курс лекций. - М.: Интернет-университет информационных технологий, 2005.
25. Орлов С. Технологии разработки программного обеспечения: Учебник - СПб.: Питер, 2002.
26. Поликарпова Н.И., Шалыто А.А. Автоматное программирование. — СПб.: Питер, 2009.
27. Попов В.Б. Основы информационных и телекоммуникационных технологий. Программные средства информационных технологий. – М.: Финансы и статистика, 2005.
28. Роберт В. Себеста. Основные концепции языков программирования = Concepts of Programming Languages. — М.: Вильямс, 2001.
29. Сик Джереми, Ли Лай-Кван, Ламсдэйн Эндрю. C++ Boost Graph Library. - СПб.: Питер, 2006.
30. Соммервиль И. Инженерия программного обеспечения. - М.: Изд-во Вильямс, 2002.
31. Тассел Д. Ван. Стиль, разработка, эффективность, отладка и испытание программ. – М.: Мир, 1985.
32. Терехов А.Н. Технология программирования. – М.: БИНОМ, Интернет-университет информационных технологий, 2006.
33. Фаулер М., Скотт К. UML в кратком изложении. Применение стандартного языка объектного моделирования. – М.: Мир, 1999.
34. Фаулер М. UML. Основы. – СПб: Символ-Плюс, 2005.
35. Филд А., Харрисон П. Функциональное программирование. - М.: Мир, 1993.
36. Хендерсон П. Функциональное программирование. Применение и реализация. - М.: Мир, 1983.
37. Хьюз Дж., Мичтом Дж. Структурный подход к программированию. - М.: Мир, 1985.
38. Шалыто А.А. Switch-технология. Алгоритмизация и программирование задач логического управления. — СПб.: Наука, 1998.
39. Henning M. The Rise and Fall of CORBA. - ACM Queue, Volume 4, Number 5, 2006.
40. Raccoon L. The Chaos Model and the Chaos Life Cycle. - ACM Press: ACM Software Engineering Notes, Volume 20, Number 1, 1995.
41. http://citforum.ru/operating_systems/windows/complus