- •Кризис программирования и способ выхода из него
- •Модель cmm-sei
- •Управление качеством разработки программного продукта с помощью системы стандартов iso 9001
- •Примерная структура процесса и организации, занимающейся разработкой программных продуктов
- •Контрольные вопросы
- •Оценка технических, нетехнических и финансовых ресурсов для выполнения программного проекта
- •Оценка возможных рисков при выполнении программного проекта
- •6.5. Составление временного графика выполнения программного проекта
- •Контрольные вопросы
- •Собираемые метрики, используемые методы, стандарты и шаблоны
- •Конструирование прототипа
- •Составление спецификаций по требованиям заказчика
- •Собираемые метрики, используемые методы, стандарты и шаблоны
- •Контрольные вопросы
- •Эволюция разработки программного продукта
- •Структурное программирование
- •Объектно-ориентированное проектирование
- •Собираемые метрики, используемые методы, стандарты и шаблоны
- •Контрольные вопросы
- •Тестирование
- •Разработка справочной системы программного продукта. Создание документации пользователя
- •Создание версии и инсталляции программного продукта
- •Собираемые метрики, используемые методы, стандарты и шаблоны
- •Контрольные вопросы
- •Виды тестирования
- •Программные ошибки
- •Тестирование документации
- •Разработка и выполнение тестов
- •Требования к хорошему тесту
- •Классы эквивалентности и граничные условия
- •Тестирование переходов между состояниями
- •Условия гонок и другие временные зависимости
- •Нагрузочные испытания
- •Прогнозирование ошибок
- •Тестирование функциональной эквивалентности
- •Регрессионное тестирование
- •Собираемые метрики, используемые методы, стандарты и шаблоны
- •Контрольные вопросы
- •1. Подготовительная работа, предусматривающая:
- •Контрольные вопросы
- •Классификация поставляемых программных продуктов
- •Действия, выполняемые при поставке программного продукта
- •Контрольные вопросы
- •Основные понятия о надежности программных продуктов и методах ее обеспечения
- •Методы обеспечения надежности на различных этапах жизненного цикла разработки программного продукта
- •Прогнозирование ошибок
- •Шаблон для учета итоговых сведений об ошибках
- •Предотвращение ошибок
- •Шаблон для учета действий по предотвращению ошибок на этапах составления требований, проектирования и разработки
- •Устранение ошибок
- •Обеспечение отказоустойчивости
- •Инструменты, обеспечивающие надежность программных продуктов. План обеспечения надежности
- •Контрольные вопросы
Контрольные вопросы
1. Каково назначение этапа управления требованиями к программному продукту в жизненном цикле разработки программного продукта?
2. Какие действия включает в себя работа по управлению требованиями?
3. Какие цели преследует работа по управлению требованиями?
4. На какие категории можно разделить все требования при определении их приоритетов?
5. В какой очередности следует реализовывать требования к программному продукту?
6. Какие требования относятся к функциональным и нефункциональным?
7. Какие действия включает в себя цикл формирования требований к программному продукту?
8. Какие цели преследует анализ первичных требований заказчика?
9. Какие действия выполняются при структурировании требований заказчика?
10. Какова роль прототипа при формировании требований к программному продукту?
11. Какие преимущества обеспечивает прототип?
12. Почему требования в спецификации требований должны быть однозначными?
13. Какие метрики собирают на этапе управления требованиями?
14. Какие методы, стандарты и шаблоны используют на этапе управления требованиями?
ПРОЕКТИРОВАНИЕ ПРОГРАММНОГО ПРОДУКТА
Общая характеристика и компоненты проектирования
Этап проектирования предназначен для выработки и детализации модели разрабатываемой программной системы. Такая модель определяет структуру программной системы, организацию модулей, интерфейсов и данных, описание которых необходимо для последующего этапа реализации. Указанный этап может быть представлен совокупностью компонент проектирования, для каждой из которых определены набор свойств и связи с другими компонентами.
Компонентой проектирования является элемент проектирования, полученный в результате декомпозиции требований заказчика к ПП. Компоненты проектирования могут быть системами, подсистемами, модулями, элементами данных, процессами и т.п. Все они обладают общими характеристиками, называемыми атрибутами компонент. Для компонент проектирования могут быть определены следующие атрибуты:
название компоненты — ее уникальное имя;
тип компоненты — ее сущность (подсистема, процедура, процесс, элемент данных и т.д.);
функция — выполняемые компонентой действия;
зависимости — описание взаимосвязей с другими компонентами;
интерфейсы — описание методов взаимодействия с другими
компонентами;
ресурсы — описание необходимой аппаратной, библиотечной
или другой поддержки;
обработка — описание алгоритма выполнения функции;
данные — описание внутренних структур данных.
Перечень необходимых компонент, их названия и назначения определяются в зависимости от выбранного способа построения модели ПП и, в первую очередь, от выбранной методики программирования (например, структурное программирование или объектно-ориентированное). Каждая из этих методик имеет свои способы построения модели ПП.
Результаты проектирования представляются в виде описания компонент проектирования по определенному набору атрибутов.
Эволюция разработки программного продукта
С момента появления первых электронно-вычислительных машин разработка программного обеспечения прошла большой путь. Восхищения возможностью написания хоть какой-нибудь программы сменилось осознанием того, что именно технология разработки программного обеспечения определяет прогресс в вычислительной технике.
На первых этапах развитие вычислительной техники было ориентировано на решение технических проблем. Предметом забот была прежде всего аппаратура, вычислительная машина как таковая. Казалось вполне естественным, что программы для таких машин разрабатывают в двоичных кодах. Программирование было уделом энтузиастов.
По мере того как вычислительные машины становились все мощнее и надежнее, значение программного обеспечения осознавалось- все большим числом ученых и практиков. Важнейший прорыв произошел в конце 1950-х годов, когда появились языки программирования высокого уровня — Fortran, Algol и др. Их появление было обусловлено прежде всего тем, что написание программ без таких языков становилось все более сложной задачей. Решив текущие проблемы, эти языки создали новые. Ускорив и упростив программирование, они существенно расширили круг задач, решаемых с помощью ЭВМ. Появление новых задач, более сложных, чем решавшиеся раньше, привело к тому, что имеющихся средств снова стало недостаточно для успешного их решения.
Такое развитие характерно для всей истории применения компьютеров, вплоть до настоящего времени. Вычислительная техника все время используется на пределе своих возможностей. Каждое новое достижение в аппаратном либо программном обеспечении приводит к попыткам расширить сферу применения ЭВМ и тем самым ставит новые задачи, для решения которых нужны новые возможности.
В сложившейся ситуации усилия программистов были сосредоточены прежде всего на создании новых языков программирования. Появился язык Cobol, дающий возможность решать задачи обработки экономической информации. Он создавался таким образом, чтобы программа на нем выглядела почти как текст на английском языке. Появился язык PL/I, объединивший в себе все возможности, которые только могут иметь языки программирования.
Языки Fortran, Algol, PL/I поддерживают процедурный стиль программирования. Программа разрабатывается в терминах тех действий, которые она выполняет. Основной единицей программы является процедура. Процедуры вызывают другие процедуры, все вместе они работают по определенному алгоритму, который ведет к решению задачи. Алгоритм — это точная последовательность действий для получения необходимого результата.
Появление перечисленных языков стало следствием круга задач, которые решались с помощью вычислительной техники. Прежде всего это были вычислительные задачи. Основными пользователями ЭВМ являлись ученые и инженеры, которых привлекала возможность быстро получить необходимый результат.
Применение ЭВМ для решения задач искусственного интеллекта и обработки текстов привело к созданию функциональных языков, в частности языка Lisp. Эти языки имеют также хорошо проработанное математическое основание — лямбда-исчисление. В отличие от языков типа Algol, в которых действия в основном выражаются в виде итерации (повторения какого-либо фрагмента программы несколько раз), в языке Lisp вычисления производятся с помощью рекурсии — вызова функцией самой себя, а основной структурой данных является список.
В 1960-е годы многие теоретики и практики осознали, что одно лишь создание новых, более совершенных языков программирования не может решить все проблемы разработки программ. Начались интенсивные исследования в области тестирования программ, организации процесса разработки программного обеспечения и др.
Усилия преобразовать программирование из эмпирического процесса в более упорядоченный, придать ему более «инженерный» характер привели к созданию методик программирования. Это был очень существенный шаг. Разработка методов построения программ, с одной стороны, создавала основу для массового промышленного программирования, а с другой стороны, обобщая и анализируя текущее состояние программного обеспечения, давала мощный импульс созданию новых языков программирования, операционных систем, сред программирования.
Одной из наиболее широко применяемых методик программирования стал структурный подход к программированию. Создателем его считается Э. Дейкстра (Е. Dijkstra). Фактически структурный подход к программированию — это первая законченная методика программирования. Законченной ее можно назвать потому, что структурное программирование предлагает путь от задачи до ее воплощения в программе. Структурное программирование оказало огромное влияние на развитие программирования. Этот метод, который применялся очень широко в практическом программировании, и по сей день не потерял своего значения для определенного класса задач.
Структурный подход базируется на двух основополагающих принципах:
использование процедурного стиля программирования;
последовательная декомпозиция (разложение) задачи сверху вниз.
Задача решается путем выполнения некоторой последовательности действий. Первоначально она формулируется в терминах входа—выхода (на вход программы подаются исходные данные, а после выполнения программы не выход выдается ответ). Далее начинается последовательное разложение всей задачи на более простые действия. Например, если нам необходимо написать программу проверки правильности адреса, то вначале мы ее запишем следующим образом.
1. Прочитать адрес.
2. Сверить адрес с базой имеющихся адресов.
3. Если результат проверки положителен, напечатать «Да», в противном случае напечатать «Нет».
Такая запись один к одному отображается в программе на языке высокого уровня, например на Pascal или С.
Чрезвычайно важно то, что на любом этапе программу можно проверить, достаточно лишь написать заглушки — процедуры, имитирующие вход и выход процедур нижнего уровня. В приведенной выше программе можно использовать процедуру чтения адреса, которая вместо ввода с терминала просто подставляет какой-нибудь фиксированный адрес, и процедуру сверки с базой данных, которая ничего не делает, а просто всегда возвращает код корректного завершения.
Программа компонуется с заглушками и может работать. Иными словами, заглушки позволяют проверить логику верхнего уровня до реализации следующего уровня. Последовательно применяя метод заглушек, можно на каждом шаге разработки программы иметь работающий скелет, который постепенно обрастает деталями.
Структурное программирование поддерживалось языками программирования, появившимися в конце 1960-х годов (Pascal, Algol-68, Fortran и др.). Именно к тому времени было осознано значение программного обеспечения при решении задач с помощью вычислительной техники. Эти языки поддерживали разнообразные вложенные процедуры, разные способы передачи параметров.
Несмотря на то что структурное программирование ясно определило значение модульного построения программ при разработке больших проектов, языки программирования еще слабо поддерживали модульность. Единственным способом структуризации программ являлось составление ее из подпрограмм или функций. Контроль за правильностью вызова функций, в том числе за соответствием количества и типов фактических аргументов ожидаемым формальным параметрам, осуществлялся только на стадии выполнения (понятие прототипа функции появилось позже).Объектно-ориентированное программирование родилось и получило широкое распространение ввиду осознания трех важнейших проблем программирования.
Первая проблема состояла в том, что развитие языков и методов программирования, хотя и существенно облегчило и ускорило разработку программных систем, не успевало за растущими с еще большей скоростью потребностями в программах. Единственным реальным способом резко ускорить разработки был метод многократного использования разработанного программного обеспечения. Иными словами, требовалось не строить каждый раз систему с нуля, а использовать разработанные ранее модули, которые уже прошли цикл отладки и тестирования и успешно работали.
Разумеется, процедурное программирование предоставляло способ разработки функций, которые могли служить блоками для построения программ. Однако ни гибкость этого метода, ни масштабы использования не позволяли существенно ускорить массовое программирование.
Второй проблемой, фактически связанной с первой, являлась необходимость упрощения сопровождения и модификации разработанных систем. Факт постоянного изменения требований к системе был осознан как нормальное условие развития системы, а не как неумение или недостаточно четкая организация работы разработчиков. Сопровождение и модификация систем требуют не меньших усилий, чем собственно разработка. Требовалось радикально изменить способ построения программных систем, чтобы, во-первых, локальные модификации не могли нарушить работоспособность всей системы и, во-вторых, было легче производить изменения поведения системы.
Третья проблема, возможно наиболее существенная, которую ; требовалось решить, — это облегчение проектирования систем. Далеко не все задачи поддаются алгоритмическому описанию и, тем более, алгоритмической декомпозиции, как того требует структурное программирование. Было необходимо приблизить структуру программ к структуре решаемых задач, сократить так называемый семантический разрыв между ними. О семантическом разрыве говорят в том случае, когда понятия, лежащие в основе языка задачи и средств ее решения, различны. Поэтому наряду с необходимостью записи самого решения требуется еще перевести одни понятия в другие. Сравните это с переводом с одного естественного языка на другой. Именно потому, что таких понятий в русском языке раньше не было, появляются слова типа «брокер», «оффшор» или «инвестор». К сожалению, в программировании заимствование слов невозможно.
Итак, упрощение проектирования, ускорение разработки за счет многократного использования готовых модулей и легкость модификации — вот три основных достоинства объектно-ориентированного программирования, которые пропагандировались его сторонниками.
Объектно-ориентированный подход к программированию связывают прежде всего с языками программирования, такими как Smalltalk, C++, Java и т.д. Эта позиция имеет существенные основания. Поскольку языки являются главными инструментами объектно-ориентированного программирования, именно при их разработке появилось большинство тех идей, которые и составляют основу объектно-ориентированного метода в настоящее время.
Накопление новых идей шло в течение примерно 10 лет, начиная с конца 1960-х годов. К концу 1970-х годов переход на новый уровень абстракции стал свершившимся фактом в академических кругах. Потребовалось еще около 10 лет, чтобы новые идеи проникли в промышленность. Пожалуй, первым шагом на пути создания собственно объектной модели следует считать появление абстрактных типов данных.
Первым на необходимость структуризации систем по уровням абстракции указал Э.Дейкстра. Идея инкапсуляции (скрытия информации) была высказана Д. Парнасом. Позднее был разработан механизм абстрактных типов данных, который был дополнен С.Хоором в его теории типов и подтипов.
Считается, что первой полной реализацией абстрактных типов данных в языках программирования является язык Simula, который, в свою очередь, опирается на языки Modula, CLU, Euclid и др. Первым «настоящим» объектно-ориентированным языком программирования принято считать Smalltalk, разработанный в лаборатории компании «Ксерокс» в Паоло-Альто. (Многие по-прежнему считают его единственным настоящим объектным языком программирования.) Затем появились (и продолжают появляться) другие объектно-ориентированные языки, которые определяют современное состояние программирования. Наиболее распространенными из них стали C++, CLOS, Eiffel, Java.
Однако только языками программирования объектно-ориентированный подход не исчерпывается. Языки лишь предоставляют инструментарий, которым можно воспользоваться или не воспользоваться. На языке C++ можно писать в процедурном стиле. Объектно-ориентированное программирование предполагает единый подход к проектированию, построению и развитию системы.
Появление объектно-ориентированного метода произошло на основе всего предыдущего развития методов разработки программного обеспечения, а также многих других отраслей науки. Американский эксперт в области программирования Гради Буч (Grady Booch) помимо развития языков программирования отмечает следующие достижения, которые способствовали возникновению объектно-ориентированного подхода к проектированию систем.
1. Развитие вычислительной техники, в частности аппаратная поддержка основных концепций операционных систем и построение функционально-ориентированных систем. При проектировании вычислительных машин использование понятия объекта началось с исследований по нефоннеймановской архитектуре. Попытки сократить семантический разрыв между низкоуровневой архитектурой традиционных процессоров и высокоуровневыми понятиями операционных систем предпринимались при построении таких систем, как Барроус, Intel i432, IBM/38 и др. Тесно связанные с ними разработки объектно-ориентированных операционных систем начались, пожалуй, с проекта THE под руководством Э. Дейкстры, были продолжены в системах iMAX для Intel i432 и др. Сравнительно недавние проекты Cairo Microsoft и Taligent Pink (хотя и остановившиеся на исследовательском этапе) — это также проекты объектно-ориентированных операционных систем.
2. Достижения в методологии программирования, в частности модульное построение систем и инкапсуляция информации.
3. Создание теории построения и моделирования систем управления базами данных, которая внесла в объектное программирование идеи построения отношений между объектами. Моделирование данных с помощью отношений между объектами было впер- ; вые предложено П. Ченом (P. Chen) в методе ER-моделирования.
В этом методе модель данных строится в виде объектов (сущностей), их атрибутов и отношений между ними.
4. Исследования в области искусственного интеллекта, позволившие лучше осознать механизмы абстракции. Теория фреймов, предложенная М. Минским для представления реальных объектов «в системах распознавания образов, дала мощный импульс для развития не только систем искусственного интеллекта, но и механизмов абстракции в языках программирования.
5. Развитие философии и теории познания. Объектно-ориентированное построение систем — это определенный взгляд на моделируемый реальный мир. Именно в этом аспекте философия и теория познания оказали сильное влияние на объектную модель. Еще древние греки рассматривали мир в виде объектов или процессов. Декарт выдвинул предположение, что для человека естественным представляется объектно-ориентированное рассмотрение окружающего мира. М. Минский предположил, что разум проявляется как взаимодействие агентов, не умеющих по отдельности мыслить.
Теория архитектуры и строительства, выдвинувшая концепцию образцов или шаблонов, активно используется в последние годы в области объектно-ориентированного анализа (ООА) и объектно-ориентированного проектирования (ООП).
Следствием интенсивных исследований в области методов программирования явилось появление большого числа средств автоматизации разработки программ, или CASE-средств (Computer Aided Software Engineering). Предполагалось, что после записи задачи на каком-либо высокоуровневом языке эти системы автоматически (или хотя бы с минимальным участием человека) сгенерируют готовую, правильно работающую программу, которая адекватно решит поставленную задачу.
В целом CASE-средства не смогли достичь желаемого: либо описание задачи по сложности оказывалось сравнимым с результирующей программой, либо решался крайне ограниченный круг сравнительно простых задач, либо качество генерируемой программы оказывалось слишком низким.
Несмотря на провал при попытке достичь основной цели, опыт разработки CASE-средств дал очень много для развития методов программирования. Небольшая часть систем используется напрямую (например, генераторы компиляторов lex и уасс), часть идей была использована при создании современных средств быстрой разработки программ (RAD — Rapid Application Development), таких как JBuilder, Delphi, Powerbuilder и др.
Приведенный исторический экскурс развития методологии программирования, совершенно не претендующий на полноту, иллюстрирует то, что все время программирование «боролось» за возможность решать все более сложные задачи, создавать все более сложные программные системы и делать это как можно быстрее. Периодически то или иное достижение объявлялось панацеей (будь то структурное программирование, CASE-средства или что-либо еще). Однако всегда оказывалось, что широко разрекламированное средство не способно решить все проблемы.
