Автор работы: Пользователь скрыл имя, 12 Июня 2012 в 11:59, курс лекций
1. Программное обеспечение. Классификация. Системное и прикладное ПО. 2
2. Вспомогательные средства и методы управления проектом. 3
3. Типы ПО: автономное, встроенное, реального времени, сетевое. 5
4. Распределённые команды, экстремальное программирование. Метод отбраковки. 5
5. Исторический и современный взгляд на разработку ПО. Влияние структурного и объектно-ориентированного программирования. 6
6. Анализ требований. С- и D-требования. Описание требований. Приоритет и контроль требований. 8
7. Роли и артефакты. Требования к процессу, проекту, продукту и персоналу. 8
8. Архитектура программного обеспечения. Выбор архитектуры. Классификация архитектур. 10
9. Жизненный цикл ПО. Разновидности процесса разработки. 11
Клиент-серверные архитектуры были широко распространены в 80-х и 90-х годах прошлого века. Многие из них пришли на смену архитектурам «центральная машина — терминалы». Клиент-серверные архитектуры усложнились, стали более разнообразными. Некоторые из них являются трехуровневыми, в отличие от классических двухуровневых (клиент и сервер). Третий уровень находится между клиентом и сервером и отвечает за перенаправление данных и их преобразование. Обычно распределение по уровням таково: пользовательский интерфейс разрабатывается для клиентского уровня; управление процедурами — для среднего уровня; сами базы данных — для третьего. Средний уровень может быть общей шиной данных, примером которой является стандарт CORBA (Common Object Request Broker — Общая архитектура посредника запросов к объектам). Возможен альтернативный вариант, когда средний уровень функционирует на основе бинарного стандарта, например СОМ. Наконец, World Wide Web можно рассматривать как целое поколение клиент-серверных архитектур, в котором архитектуру один сервер — десятки клиентов заменила архитектура один сервер — миллионы клиентов.
Архитектура параллельных взаимодействующих процессоров
Еще один тип архитектур независимых компонентов был определен Шоу и Гарланом как архитектура параллельных взаимодействующих процессов. Такая архитектура характеризуется тем, что в ней одновременно запускаются несколько процессов (в разных потоках, выражаясь в терминах Java). Элементы этой архитектуры используются в игре Встреча: внешний персонаж Фредди перемещается независимо из одной зоны в другую параллельно с выполнением программы самой игры. Его поток «общается» с другими потоками, когда бы Фредди ни оказался в одной зоне с персонажем игрока.
Нотация UML, выражающая параллелизм, была рассмотрена в главе 4. С помощью этой нотации мы представили архитектуру банковского приложения (рис. 5.20), которое предназначено для обработки множественных транзакций, появляющихся последовательно на банкомате.
Когда клиент п пользуется банкоматом, создается объект клиент п (1 на рис. 5.20). Этот объект создает поток или параллельный процесс сессия т (2), что на диаграмме отмечается половинной стрелкой. Процесс сессия т извлекает объект класса Счет, например проверка клиента п (3). Затем клиент выполняет депозитную транзакцию над проверяющим объектом (4). Параллельно с этим создаются другие объекты Клиент, такие как клиент п+1} и исполняются в других потоках, например в сессии k.
Если в приложении необходимы параллельные процессы, наилучшим выбором является архитектура параллельных взаимодействующих процессов. Эта архитектура может быть использована для схем, координирующих концептуально независимые задачи. В классической книге Дийкстра показал, что рассмотрение процесса как комбинации параллельных составляющих может зачастую упростить разработку. Примером тому является имитация клиентов банка. Традиционно такие имитации разрабатывались без параллелизма — они просто сохраняли и обрабатывали события. Однако проектирование в подобных случаях можно упростить, если рассматривать действия каждого клиента независимо. Такая архитектура параллельно взаимодействующих процессов имеет существенное преимущество — она более всего соответствует действиям, которые имитируются.
Архитектуры событийно-управляемых систем
Рассмотрим событийно-управляемые системы — третий тип архитектуры независимых компонентов, предложенной Шоу и Гарланом. В данной архитектуре приложения представляются состоящими из набора компонентов, каждый из которых находится в состоянии ожидания, пока не произойдет воздействующее на него событие. К таким системам относятся многие современные приложения. Например, текстовый редактор Word ждет, пока пользователь не щелкнет на значке или на пункте меню. Далее происходит соответствующая реакция: сохранение файла, изменение шрифта и т. п. Системы, управляемые событиями, часто строятся на основе модели переходов состояний.
Риск —
это нечто, что может появиться по ходу
проекта, и это нечто в худшем случае может
негативно повлиять на проект. Промышленные
данные демонстрируют огромное количество
сорванных программных проектов. Например,
Rational Corporation приводит следующий факт: «более
70 % всех программных проектов находятся
под угрозой или испытывают серьезные
трудности». Факторы, приводящие проект
к срыву, на ранних стадиях проекта проявляются
в виде рисков.
Таким
образом, своевременое выявление того
или иного риска, а также принятие соответствующих
мер позволяют предотвратить срыв проекта.
Существуют два типа рисков.
1. Риски, которых можно избежать
или которые можно предотвратить
(устранимые).
2. Риски, которых невозможно избежать.
Примером первого типа рисков является следующий: «Что если руководитель проекта в команде из 15 человек уходит из компании?» (риск устраняется подготовкой заместителя руководителя проекта). Пример риска второго типа: «Необходимо собрать данные о 2100 полетах путем опроса персонала эропорта, прежде чем мы сможем поставить продукт».
Если риск первого рода выявлен достаточно рано, то меры по предотвращению риска позволяют успешно продолжать проект. Очень полезно выявлять и риски второго рода. Можно либо сразу прекратить проект и избежать дальнейших потерь, либо изменить область применения или иным образом изменить сам проект, чтобы минимизировать риск.
Эффективные команды принимают наличие рисков как данность и постоянно о них думают.
Управление риском состоит из нескольких действий.
1. Идентификация. Старайтесь постоянно обнаруживать риски.
2. Планирование устранения.
3. Выбор приоритетов.
4. Устранение или уменьшение.
Эти шаги требуется осуществлять с самого начала проекта и упорно продолжать в течение первой четверти проекта. Некоторые команды назначают одного из своих коллег на роль координатора рисков, ответственного за поиск рисков, а также информирующего об их устранении.
Факторы риска:
1. Недостаточная вовлеченность в проект высшего руководства.
2. Невозможность привлечения пользователей.
3. Непонимание требований.
4. Привлечение неадекватных пользователей.
5. Невозможность управления ожиданиями конечных пользователей.
6. Изменение области применения или целей проекта.
7. Нехватка знаний или навыков у персонала.
Предупреждение рисков — это процесс, в ходе которого степень рисков снижается или риски полностью устраняются. Имеются два способа предупреждения рисков. Первый заключается во внесении изменений в требования проекта, благодаря чему устраняется причина возникновения риска (избежание риска). Другой способ — разработка неких технологий и архитектуры, решающих проблему (преодоление риска или, проще говоря, его устранение).
В хорошем проекте риски
постоянно идентифицируются и обычно
имеется список рисков, ждущих своей очереди
для обработки. В этом списке риски должны быть упорядочены
по приоритетам, поскольку обычно
нет времени проводить мероприятия по
устранению для всех рисков. В хорошо управляемом
проекте те риски, которые не были предупреждены
заранее, являются наименее опасными и
даже если случаются, то не создают серьезных
проблем. Схема расстановки приоритетов
объясняется в табл. 2.2. Для каждого
риска определяются три величины: вероятность
осуществления риска; ущерб, наносимый
проекту данным риском в случае осуществления;
оценка стоимости устранения риска.
Для всех величин используется одна шкала,
например от 1 до 10. Первые два числа вычитаются
из И, третье берется как есть и все полученные
числа перемножаются, а результат считается
приоритетом риска.
ОДИН ИЗ СПОСОБОВ ОПРЕДЕЛЕНИЯ И ПРЕДУПРЕЖДЕНИЯ РИСКОВ
Описываемый процесс нацелен на наиболее продуктивное использование времени совещаний за счет автономного выполнения работы, которая не требует присутствия всей команды. Первые три пункта выполняются заранее, до первого совещания.
1. Каждый член команды затрачивает 10 минут на выявление основных опасений по поводу успешного окончания проекта.
2. Каждый участник специфицирует эти риски в конкретных терминах, оценивает их, предлагает планы устранения (формат см. выше) и отсылает все это лидеру команды по электронной почте.
3. Лидер команды суммирует результаты и расставляет приоритеты.
4. Команда затрачивает 10 минут на поиск дополнительных рисков (на совещании).
5. Команда затрачивает 10 минут на окончательное формирование таблицы рисков (на совещании).
♦ Назначаются разработчики, ответственные за устранение рисков.
6. Разработчики устраняют риски (между совещаниями).
7. Команда на еженедельных совещаниях в течение 10 минут делает обзор рисков:
♦ ответственные за устранение рисков разработчики докладывают о прогрессе;
♦ команда обсуждает новые обнаруженные риски и добавляет их в таблицу рисков.
Виртуальные машины.
Архитектура виртуальных машин рассматривает приложение как программу, написанную на специальном языке. Из-за того, что должен быть реализован интерпретатор этого языка, эта архитектура окупается, только если будут написаны несколько программ, генерирующих приложения.
В качестве примера архитектуры виртуальных машин рассмотрим приложение, обрабатывающее заказы определенных компьютерных систем одной сети. Обработка заказов выражается на специальном языке со следующей грамматикой:
Program ::= 'assemble' Program | 'price' Program | System
System ::= Computer | '{' System 'and' System '}'
Computer :: = '{' CPU '&' RAM '}'
CPU :: = '260MHz' | '300MHz' | '400MHz'
RAM :: = '32MB' | '64MB' | '12MB'
Например, заказ на рис. 5.25 состоит из системы 260 МГц с оперативной памятью 64 Мбайт, которая соединена с системой, содержащей два компьютера: 400 МГц, 128 Мбайт RAM и 260 МГц, 32 Мбайт RAM.
Этот заказ выражается с помощью описанной грамматики следующим образом:
Assemble { {
{ 260MHz & 64MB } }
and
{ { 400MHz & 128MB }
and
{ 260MHz & 32MB }
}
}
Это выражение корректно с точки зрения описанной грамматики, как показано ниже.
Program
assemble Program
assemble System
assemble { System & System }
assemble { Computer & { System & System } }
assemble { { CPU & RAM } & { Computer & Computer} }
assemble { { 260MHz & 64MB } } & { { CPU & RAM } & { CPU & RAM } }
assemble { { 260MHz & 64MB } } & { { 400MHz & 128MB } & { 260MHz & 32MB } }
Вывод, выдаваемый виртуальной машиной, будет иметь вид:
1 Construct system 1 as follows:
2 Computer with 260MHz CPU and 64MB RAM
3 Construct system 2 as follows:
Construct system 3 as follows:
Computer with 400MHz CPU and 128MB RAM
Construct system 4 as follows:
Computer with 260MHz CPU and 32MB RAM
Connect System 3 and System 4
Connect System 1 and System 2
Мы могли бы сделать
вывод более удобным для
Преимущество использования архитектуры виртуальных машин в том, что вы можете свободно генерировать приложения, выражая их специальным языком. Например, следующий код мог бы быть еще одной программой, выдающей цену на основе обработанных инструкций:
price assemble { ... }
Очевидно, что можно сделать этот язык более мощным, а также заменить текстовое представление на графическое. Но и в этом случае применялась бы та же архитектура виртуальных машин.
Реализация полной виртуальной машины требует построения интерпретатора. В общем случае интерпретация вызывается операцией — назовем ее interpret() — над программой на нашем языке. Интерпретация простейшего одиночного элемента (например, CPU) в общем проста (например, это может означать требование вывести take CPU in the example). Проблема состоит в запуске interpret() при применении к более сложной программе.
Один из путей решения — использовать образец проектирования Interpreter. Гамма указывает, что целесообразно использовать этот образец проектирования, когда грамматика мала и скорость не является важным фактором. Это справедливо для рассматриваемого нами примера. Образец проектирования Interpreter показан на рис. 5.26.
Объекты AbstractExpression являются либо объектами TerminalExpression, для которых функция интерпретации проста, либо объектами NonTerminalExpression. Последние агрегируют один или более объектов AbstractExpression. Функция interpret(), вызываемая для объектов NonTerminalExpression, выполняется, вызывая для каждого агрегированного объекта AbstractExpression свою версию interpret().
В качестве примера рассмотрим архитектуру интерпретатора нашей грамматики, для простоты игнорируя расчет стоимости. Применяя образец проектирования Interpreter, мы получим диаграмму (рис. 5.27). Ограничимся сборкой только двух компонентов, то есть пусть класс System агрегирует только два объекта Component. Этот метод легко может быть расширен и для большего количества компонентов.
Информация о работе Лекции по "Технологии разработки программного обеспечения"