Lecture04

advertisement
Технологии программирования. Компонентный подход
В. В. Кулямин
Лекция 4. Архитектура ПО. Образцы проектирования.
Архитектура ПО
Под архитектурой ПО обычно понимают набор внутренних структур ПО, состоящих
из компонентов, связей и возможных взаимодействий между ними, а также видимых
извне свойств этих компонентов.
Под компонентом в этом определении имеется в виду достаточно произвольный
структурный элемент ПО, который можно выделить путем определения интерфейса
взаимодействия между этим компонентом и всем, что его окружает. Термин «компонент»
в разработке ПО чаще всего (далее, при обсуждении UML и технологии EJB) имеет
несколько другой, более узкий смысл — это единица сборки системы, ее развертывания и
конфигурационного управления, то, что не может быть разделено на более мелкие
элементы при развертывании или поставке системы. Там, где возможны недоразумения,
будет указано, в первом, широком или во втором, узком смысле употребляется этот
термин.
Архитектура ПО похожа на набор карт некоторой территории — карты имеют разные
масштабы, на них показаны разные элементы (административно-политическое деление,
рельеф и тип местности — лес, степь, пустыня, болотистая местность и пр.,
экономическая деятельность и связи), но они объединяются тем, что все сведения,
представленные на них, соотносятся с географическим положением.
Точно так же архитектура ПО представляет собой набор структур или представлений,
имеющих различные уровни абстракции (аналог масштаба географических карт) и
показывающих разные аспекты (структуру классов ПО, структуру развертывания, т.е.
привязки компонентов ПО к физическим машинам, возможные сценарии взаимодействий
компонентов и пр.), объединяемых привязкой всех представленных данных к
структурным элементам ПО.
Архитектура важна прежде всего потому, что именно она определяет большинство
характеристик качества ПО в целом. Архитектура служит также основным средством
общения между разработчиками, а также и между всеми лицами, заинтересованными в
данном ПО.
Выбор архитектуры определяет способ реализации требований на высоком уровне
абстракции. Именно архитектура почти полностью определяет такие характеристики ПО
как надежность, переносимость и удобство сопровождения. Архитектура значительно
влияет и на удобство использования и эффективность ПО, которые определяются также и
реализацией отдельных компонентов. Значительно меньше влияние архитектуры на
функциональность — обычно для реализации заданной функциональности можно
использовать различные архитектуры.
Поэтому выбор между той или иной архитектурой определяется прежде всего именно
нефункциональными требованиями и необходимыми свойствами ПО в аспектах удобства
сопровождения и переносимости. При этом для построения хорошей архитектуры надо
учитывать возможные противоречия между требованиями к различным характеристикам
и уметь выбирать компромиссные решения, дающие приемлемые значения по всем
показателям.
Так, для повышения эффективности в общем случае выгоднее использовать
монолитные архитектуры, в которых выделено небольшое число компонентов (в пределе
— единственный компонент) — этим обеспечивается экономия как памяти, поскольку
каждый компонент обычно имеет свои данные, а здесь число компонентов минимально,
так и времени работы, поскольку возможность оптимизировать работу алгоритмов
обработки данных имеется также, обычно, только в рамках одного компонента.
С другой стороны, для повышения удобства сопровождения, наоборот, лучше
разбивать систему на большое число отдельных компонентов, с тем, чтобы каждый из них
решал свою небольшую, но четко определенную часть общей задачи. При этом, если
возникают изменения в требованиях или проекте, их обычно можно свести к изменению
одной-нескольких таких подзадач, и, соответственно, изменять только отвечающие за
решение этих подзадач компоненты.
С третьей стороны, для повышения надежности лучше использовать дублирование
функций, т.е. сделать несколько компонентов ответственными за решение одной
подзадачи. Причем, поскольку ошибки в ПО чаще всего носят неслучайный характер (т.е.
они повторяемы, в отличии от аппаратного обеспечения, где ошибки связаны прежде
всего со случайными изменениями характеристик среды и могут быть преодолены
простым дублированием компонентов, без изменения их внутренней реализации), лучше
использовать достаточно сильно различающиеся способы решения одной и той же задачи
в разных компонентах.
Список стандартов, регламентирующих описание архитектуры и проектную
документацию вообще, выглядит так.
 IEEE 1016-1998 Recommended Practice for Software Design Descriptions
 IEEE 1471-2000 Recommended Practice for Architectural Description of Software-Intensive
Systems
Разработка и оценка архитектуры
При проектировании архитектуры системы на основе требований, зафиксированных в
виде вариантов использования, первые возможные шаги состоят в следующем.
 Выбирается набор «основных» сценариев использования — наиболее существенных и
часто используемых
 Определяются, исходя из опыта проектировщиков, выбранного архитектурного стиля
(см. далее) и требований к переносимости и гибкости, компоненты отвечающие за
определенные действия — решение определенных подзадач — в рамках этих сценариев
 Сценарии разбиваются на последовательности обмена сообщениями между полученным
компонентами
 При возникновении дополнительных хорошо выделенных подзадач, добавляются новые
компоненты, и сценарии уточняются
 Для каждого компонента в результате выделяется его интерфейс — набор сообщений,
которые он принимает от других компонентов и посылает им
 Рассматриваются «неосновные» сценарии, которые так же разбиваются на
последовательности обмена сообщениями с использованием, по возможности, уже
определенных интерфейсов
 Если интерфейсы недостаточны — они расширяются
 Если интерфейс компонента слишком велик или компонент отвечает за слишком
многое — он разбивается на более мелкие
 Там, где это необходимо в силу требований эффективности или удобства
сопровождения, несколько компонентов могут быть объединены в один
 Все это делается до тех пор, пока не выполнятся следующие условия
o Все сценарии использования реализуются в виде последовательностей обмена
сообщениями между компонентами в рамках их интерфейсов
o Набор компонентов достаточен для обеспечения всей нужной
функциональности, достаточно удобен для сопровождения и сточки зрения
переносимости и не вызывает заметных проблем с эффективностью
o Каждый компонент имеет небольшой, четко определеный круг решаемых задач
и четко определенный, сбалансированный по размеру интерфейс
На основе возможных сценариев использования или модификации системы возможен
также анализ характеристик архитектуры и оценка ее пригодности или сравнительный
анализ нескольких архитектур. Это так называемый метод анализа архитектуры ПО
(Software Architecture Analysis Method, SAAM). Основные его шаги следующие.
1. Определить набор сценариев действий пользователей или внешних систем, или
сценариев использования некоторых возможностей, которые могут уже иметься в
вистеме или быть новыми. Сценарии должны быть значимы для конкретных
заинтересованных лиц, будь то пользователь, разработчик, ответственный за
сопровождение, представитель контролирующей организации и пр. Чем полнее набор
сценариев, тем выше будет качество анализа. Можно оценить частоту появления,
важность сценариев.
2. Определить архитектуру (или несколько сравниваемых архитектур). Это должно быть
сделано в понятной всем участникам оценки форме.
3. Классифицировать сценарии. Для каждого сценария из набора должно быть
определено, поддерживается ли он данной архитектурой или нужно вносить в нее
изменения, чтобы этот сценарий стал выполним. Сценарий может поддерживаться, т.е.
его выполнение не потребует внесения изменений ни в один из компонентов, или же
не поддерживаться, если его выполнение требует изменений в описании поведения
одного или несольких компонентов или изменений в их интерфейсах. Поддержка
сценария означает, что лицо, заинтересованное в его выполнение оценивает степень
поддержки как достаточную, а необходимые при этом действия как достаточно
удобные.
4. Оценить сценарии. Для каждого неподдерживаемого сценария надо определить
необходимые изменения в архитектуре — внесение новых компонентов, изменения в
существующих, изменения связей и способов взаимодействия. Если есть возможность,
стоит оценить трудоемкость внесения таких изменений.
5. Выявить взаимодействие сценариев. Определить какие компоненты требуется
изменять для неподдерживаемых сценариев, компоненты, которые требуется изменять
для поддержки нескольких сценариев — такие сценарии называют
взаимодействующими, оценить степень смысловой связанности взаимодействующих
сценариев.
Малая связанность по смыслу между взаимодействующими сценариями означает, что
компоненты, в которых они взаимодействуют, выполняют слабо связанные между
собой задачи и их стоит декомпозировать.
Компоненты, в которых взаимодействуют много сценариев также являются
возможными проблемными местами.
6. Оценить архитектуру в целом (или сравнить несколько заданных архитектур). Для
этого надо использовать оценки важности сценариев и степень их поддержки
архитектурой.
UML. Виды диаграмм UML
Для представления архитектуры (точнее различных входящих в нее структур) удобно
использовать графические языки. На настоящий момент наиболее проработанным и
наиболее широко используемым из них является унифицированный язык моделирования
(Unified Modeling Language, UML), хотя на высоком уровне абстракции архитектуру
системы обычно описывают просто набором именованных прямоугольников,
соединенных линиями и стрелками, представляющими возможные связи.
Некоторые такие языки закреплены в виде стандартов, например
 IEEE 1320.1-1998 (R2004) Standard for Functional Modeling Language — Syntax and
Semantics for IDEF0
Этот стандарт описывает язык иерархических диаграмм потоков данных.
 IEEE 1320.2-1998 (R2004) Standard for Conceptual Modeling Language — Syntax and
Semantics for IDEF1X97 (IDEFobject)
Этот стандарт описывает язык описания струтурированных данных на основе понятий
сущности, связи и атрибута сущности, используемый, в частности, для моделирования
баз данных.
UML предлагает использовать для описания архитектуры 8 видов диаграмм. Не всякая
диаграмма на UML описывает архитектуру — 9-й вид диаграмм, диаграммы вариантов
использования, не относятся к архитектурным представлениям, кроме того, и другие виды
диаграмм можно использовать для описания внутренней структуры компонентов или
сценариев действий пользователей и прочих элементов, к архитектуре не относящихся.
 Статические структуры, отражающие постоянно присутствующие в системе сущности и
связи между ними, либо суммарную информацию о сущностях и связях, либо сущности
и связи, существующие в какой-то момент времени
o Диаграммы классов. Показывают типы сущностей системы, атрибуты типов
(поля и операции) и возможные связи между ними, а также отношения типов
между собой по наследованию.
Наиболее часто используемый вид диаграмм.
o Диаграммы объектов. Показывают объекты системы и их связи, в некотором
конкретном состоянии или суммарно.
Используются редко.
o Диаграммы компонентов. Это компоненты в узком смысле, компоненты
«физического» представления системы — файлы с исходным кодом,
динамически подгражаемые библиотеки, HTML-странички и пр. Они
определяют разбиение системы на набор сущностей, расматриваемых как
атомарные с точки зрения ее сборки и конфигурационного управления.
Используются редко.
o Диаграммы развертывания. Показывают привязку (в некоторый момент
времени или постоянную) компонентов системы (во узком смысле) к
физическим устройствам — машинам, процессорам, принтерам,
маршрутизаторам и пр.
Используются редко.
 Динамические структуры, описывающие происходящие в системе процессы
o Диаграммы деятельностей. Показывают набор процессов-деятельностей и
потоки данных, передающихся между ними, а также возможные их
синхронизации друг с другом.
Используются достаточно часто.
o Диаграммы сценариев. Показывают возможные сценарии обмена
сообщениями/вызовами во времени между различными компонентами системы
(в широком смысле). Эти диаграммы являются подмножеством другого
графического языка — языка диграмм последовательностей сообщений
(Message Sequence Charts, MSC).
Используются почти так же часто, как диаграммы классов.
o Диаграммы взаимодействия. Показывают ту же информацию, что и диаграммы
сценариев, но привязывают обмен сообщениями/вызовами не к времени, а к
связями между компонентами.
Используются редко.
o Диаграммы состояний. Показывают возможные состояния отдельных
компонентов или системы в целом, переходы между ними в ответ на какиелибо события и выполняемые при этом действия.
Используются достаточно часто.
Примеры диаграмм UML для простой системы ведения банковских счетов.
Открыть
счет
Добавить/снять
деньги
Закрыть
счет
Оператор
Рисунок 1. Диаграмма вариантов использования (не архитектурная).
Client
+ name : String
+ address : String
+ clients
0..*
+ accounts
0..*
+ Client(String, String)
+ addAccount()
AccountManager
Account
+ balance : int
+ possibleCredit : int
+ status : int
+ createAccount(Client)
+ deleteAccount(Account)
+ findAccount(Client)
+ Account()
+ deposit(int)
+ withdraw(int)
Рисунок 2. Диаграмма классов.
aClient : Client
AccountManager
anAccount : Account
Оператор
Client()
createAccount(aClient)d
addAccount()
Account()
deposit()
Рисунок 3. Диаграмма сценария открытия счета.
Nonfunctional
create
deposit(s)/balance += s
Initialized
deposit(s) [balance + s >= possibleCredit] / balance += s
Suspended
withdraw(s) [balance – s < possibleCredit] / balance - = s
Functional
withdraw(s) [balance – s >= possibleCredit] / balance - = s
Рисунок 4. Диаграмма состояний счета.
Образцы проектирования и архитектурные стили
На основе имеющегося опыта исследователями и практиками разработки ПО
выработано некоторое множество типовых архитектур, знакомство с которыми позволяет
не изобретать велосипед для решения достаточно известных задач. Подобные типовые
решения на уровне архитектуры называются архитектурными стилями. Точнее,
архитектурный стиль определяет набор типов компонентов системы и набор шаблонов их
взаимодействий по передаче данных или управления. Различные архитектурные стили
подходят для решения различных задач в плане обеспечения нефункциональных
требований, хотя одну и ту же функциональность можно реализовать, используя разные
стили.
Архитектурные стили являются образцами проектирования на уровне архитектуры.
Образец проектирования (design pattern) — это шаблон решения часто встречающейся
задачи проектирования, который можно использовать всякий раз, когда эта задача
возникает. Образцы проектирования разделяются в зависимости от масштабу решений на
архитектурные, определяющие возможную декомпозицию системы в целом или больших
подсистем, области ответственности подсистем и правила их взаимодействия, проектные,
определяющие шаблон взаимодействий группы компонентов, обычно в рамках некоторой
подсистемы, для решения некоторой общей задачи проектирования в повторяющемся
контексте, и идиомы, определяющие способ использования языковых конструкций для
решения подобных задач.
Примеры архитектурных стилей приведены в следующей таблице.
Стиль или образец
Контекст использования
Конвейер обработки
данных (data flow)
Система выдает хорошо определенные
выходные данные в результате обработки
хорошо определенных входных, при этом
процесс обработки не зависит от времени,
применяется многократно, одинаково к любым
данным на входе.
Примеры
Важным свойством является четко
определенная структура данных и поддержка
возможности интеграции с другими системами
 Пакетная
обработка
Один вывод производится на основе чтения
некоторого набора данных на входе,
промежуточные преобразования
последовательны
Выполнение
тестов
 Каналы и
фильтры
Нужно обеспечить преобразование
непрерывных потоков данных, преобразования
инкрементальны, следующее может быть
начато до окончания предыдущего, возможно
добавление дополнительных преобразований
Утилиты UNIX,
компиляторы
 Замкнутый цикл
управления
Нужно обеспечить постоянное управление в
условиях плохо предсказуемых воздействий
окружения, особенно, если система должна
реагировать на внешние физические события
Системы
управления
движением
Вызов-возврат (callreturn)
Порядок выполнения действий достаточно
определен, компонентам незачем тратить время
на ожидание обращения от других
 Процедурная
декомпозиция
Данные неизменны, процедуры работы с ними
могут немного меняться, могут возникать
новые
Основная схема
построения
программ для
языков C, Pascal,
Ada
 Абстракные типы
данных
Важны возможности внесения изменений и
интеграции с другими системами, в системе
много данных, структура которых может
меняться
Библиотеки
компонентов
 Многоуровневая
система
Важны переносимость и возможность
многократного использования, имеется
естественное расслоение системы на
специфичные только для нее функции и
функции общего характера, специфичные для
платформы
Протоколы
(модель OSI и
реальные)
Независимые
компоненты
Возможно распараллеливание работы и
изпользование нескольких машин, система
естественно разбивается на слабо связанные
небольшие компоненты, работа которых может
быть организована почти независимо
 Клиент-сервер
Решаемые задачи естественно распределяются
между инициаторами и обработчиками
запросов, возможно изменение внешнего
представления данных и способов их
обработки
 Распределенные
объекты
Возможность использования распределенной
архитектуры и многочисленные данные с
изменчивой структурой
Интерактивные
системы
Необходимость достаточно быстро реагировать
на действия пользователя, изменчивость
пользовательского интерфейса
 Данныепредставлениеобработчик
Изменения во внешнем представлении
достаточно вероятны, одна и та же информация
представляется по-разному в нескольких
местах, система должна быстро реагировать на
изменения данных
 Представлениеабстракцияуправление
Интерактивная система на основе агентов,
имеющих собственные состояния и
пользовательский интерфейс, возможно
добавление новых агентов
Системы на основе
хранилища данных
Основные функции системы связаны с
хранением, обработкой и представлением
больших количеств данных
 Репозиторий
Порядок работы определяется потоком
внешних событий и вполне определен
Основная модель
бизнесприложений
Document-View в
MFC (Microsoft
Foundation
Classes)
Cреды
разработки и
CASE-системы
 Доска объявлений Способ решения задачи в целом неизвестен или Системы
слишком трудоемок, но известны методы,
распознавания
частично решающие задачу, композиция
текста
которых способна выдавать приемлемые
результаты, возможно добавление новых
потребителей данных или обработчиков
Литература
[1] И. Соммервилл. Инженерия программного обеспечения. Вильямс, 2002.
[2] Э. Дж. Брауде. Технология разработки программного обеспечения. Питер, 2004.
[3] М. Фаулер и др. Архитектура корпоративных программных приложений. Вильямс,
2004.
[4] М. Фаулер, К. Скотт. UML в кратком изложении. М., Мир, 1999.
[5] Г. Буч, Дж. Рамбо, А. Джекобсон. Язык UML. Руководство пользователя. М., ДМК,
2000.
[6] Э. Гамма, Р. Хелм, Р. Джонсон, Дж. Влиссидес. Приемы объектноориентированного проектирования. Паттерны проектирования. Питер-ДМК, 2001.
[7] F. Buschmann, R. Meunier, H. Rohnert, P. Sommerlad, M. Stal. Pattern-Oriented
Software Architecture. Wiley, 2002.
[8] L. Bass, P. Clements, R. Kazman. Software Architecture in Practice. 2-nd edition,
Addison-Wesley, 2003.
Download