Краткое содержание
Содержание
Введение
Образовательные и Web-pecypcbi
Для кого предназначена эта книга
Что необходимо знать
Примеры на языке Java
Структура книги
Об авторе
Контакты
Дополнения к предыдущему изданию
Благодарности
Соглашения, принятые в книге
От издательства
Часть I. Введение
1.2. Основная цель обучения
1.3. Что такое анализ и проектирование
1.4. Объектно-ориентированный анализ и проектирование
1.5. Краткий пример
1.6. Что такое UML
1.7. Визуальное моделирование — хороший стиль
1.8. История
1.9. Дополнительные ресурсы
Глава 2. Итеративный, эволюционный и гибкий процесс
2.2. Что такое итеративная и эволюционная разработка
2.3. Последовательный жизненный цикл
2.4. Как выполнять итеративный и эволюционный анализ и проектирование
2.5. Итеративное планирование на основе рисков и с учетом потребностей пользователей
2.6. Что такое гибкие методы
2.7. Что такое гибкое моделирование
2.8. Что такое гибкий унифицированный процесс
2.9. Другие важные принципы унифицированного процесса
2.10. Фазы унифицированного процесса
2.11. Дисциплины унифицированного процесса
2.12. Настройка процесса и выбор инструментов UP
2.13. Вы не поняли, что такое итеративная разработка или унифицированный процесс, если
2.14. История
2.15. Дополнительные ресурсы
Глава 3. Конкретные примеры
3.2. Стратегия описания конкретных примеров: итеративная разработка + итеративное изучение
3.3. Пример 1: POS-система NextGen
3.4. Пример 2: игра Monopoly®
Часть II. Начальная фаза
4.2. Какова длительность начальной фазы
4.3. Какие артефакты относятся к начальной фазе
4.4. Вы не поняли, что такое начальная фаза, если
4.5. Как использовать UML на начальной стадии
Глава 5. Эволюционное осмысление требований
5.2. Определение требований для эволюционного и каскадного процессов разработки
5.3. Грамотное определение требований
5.4. Типы и категории требований
5.5. Как требования связаны с артефактами UP
5.6. Имеются ли примеры этих артефактов в данной книге
5.7. Дополнительные ресурсы
Глава 6. Описание прецедентов
6.2. Некоторые определения
6.3. Прецеденты и модель прецедентов
6.4. Зачем нужны описания прецедентов
6.5. Прецеденты и функциональные требования
6.6. Три типа исполнителей
6.7. Основные форматы прецедентов
6.8. Пример развернутого описания прецедента Оформление продажи
6.9. Пояснения
6.10. Другие форматы описания прецедентов
6.11. Описание прецедентов, относящихся к интерфейсу пользователя, в свободном стиле
6.12. Описания прецедентов должны быть лаконичными
6.13. Описание прецедентов в формате “черный ящик”
6.14. Примите точку зрения исполнителя
6.15. Как выделять прецеденты
6.16. Как выделить полезные прецеденты
6.17. Диаграммы прецедентов
6.18. Диаграммы видов деятельности
6.19. Дополнительные преимущества описания прецедентов
6.20. Пример: игра “Монополия”
6.21. Прецеденты в рамках итеративной разработки
6.22. История
6.23. Дополнительные ресурсы
Глава 7. Другие требования
7.2. Нужно ли детально анализировать требования на начальной стадии разработки
7.3. Нужно ли помещать документацию на Web-узле проекта
7.4. Пример NextGen: фрагмент дополнительной спецификации
7.9. Комментарии: словарь терминов
7.12. Эволюция требований в итеративном процессе разработки
7.13. Дополнительные ресурсы
Часть III. Первая итерация фазы развития — основы
8.2. Начальная фаза и стадия развития
8.3. Планирование следующей итерации
Глава 9. Модели предметной области
9.2. Что такое модель предметной области
9.3. Зачем создавать модель предметной области
9.4. Как создать модель предметной области
9.5. Как выделить концептуальные классы
9.6. Пример выделения концептуальных классов
9.7. Построение диаграммы классов в рамках гибкого процесса разработки
9.8. Автоматизированное построение модели в рамках гибкого подхода к разработке
9.9. Элементы отчета: включать ли понятие “товарный чек” в модель
9.10. Имена и модели: стратегия построения карт
9.11. Как моделировать “нереальный” мир
9.12. Типичная ошибка при выделении концептуальных классов
9.13. Когда использовать классы описаний
9.14. Ассоциации
9.15. Примеры: ассоциации в моделях предметных областей
9.16. Атрибуты
9.17. Атрибуты в моделях предметных областей
9.18. Насколько корректна модель предметной области
9.19. Итеративное и эволюционное моделирование предметной области
9.20. Дополнительные ресурсы
Глава 10. Системные диаграммы последовательностей
10.2. Системные диаграммы последовательностей
10.3. Зачем строить СДП
10.4. Применение UML для построения диаграммы последовательности
10.5. Системные диаграммы последовательностей и прецеденты
10.6. Имена системных событий и операций
10.7. Как моделировать взаимодействие с внешними системами
10.8. Диаграммы последовательностей и словарь терминов
10.9. Пример диаграммы последовательности для игры “Монополия”
10.10. Итеративное и эволюционное построение СДП
10.11. История и дополнительные ресурсы
Глава 11. Описание операций
11.2. Разделы описания
11.3. Что такое системная операция
11.4. Постусловия
11.5. Постусловия описания операции enterltem
11.6. Описание операций приводит к изменению предметной области
11.7. Когда нужны описания операций
11.8. Составление описания
11.9. Пример описания операции для POS-системы NextGen
11.10. Описание операций для игры “Монополия”
11.11. Описания операций на UML и OCL
11.12. Описания операций в рамках UP
11.13. Немного истории
11.14. Дополнительные ресурсы
Глава 12. Итеративный переход от анализа требований к проектированию
12.2. Раннее начало всех видов деятельности
12.3. Возможно, на это потребуются недели
13.1. Пример
13.2. Что такое логическая архитектура
13.3. На каких уровнях сосредоточено описание примеров
13.4. Программная архитектура системы
13.5. Диаграммы пакетов UML
13.6. Проектирование на основе шаблона Layers
13.7. Принцип Model-View Separation
13.8. Взаимосвязь между СДП, системными операциями и уровнями
13.9. Логическая архитектура и диаграмма пакетов для приложения NextGen
13.10. Пример логической архитектуры игры “Монополия”
13.11. Дополнительные ресурсы
Глава 14. Переход к объектному проектированию
14.2. CASE-средства UML
14.3. Сколько времени занимает рисование до начала кодирования
14.4. Статические и динамические модели объектов
14.5. Важнее иметь навыки объектного проектирования, чем знать систему обозначений UML
14.6. Другие методы проектирования объектов: карты CRC
Глава 15. Диаграммы взаимодействия на UML
15.2. Проблема для новичков
15.3. Основные обозначения UML для диаграмм взаимодействия
15.4. Основные обозначения диаграммы последовательностей
15.5. Основные обозначения диаграммы коммуникации
Глава 16. Диаграммы классов UML
16.2. Определение: диаграмма классов проектирования
16.3. Определение: классификатор
16.4. Способы представления атрибутов UML: имя атрибута и линии ассоциаций
16.5. Блоки примечаний: примечания, комментарии, ограничения и тела методов
16.6. Операции и методы
16.7. Ключевые слова
16.8. Стереотипы, профили и метки
16.9. Свойства и строки свойств
16.10. Обобщение, абстрактные классы, абстрактные операции
16.11. Зависимость
16.12. Интерфейсы
16.13. Композиция или агрегация
16.14. Ограничения
16.15. Уточненная ассоциация
16.16. Класс ассоциации
16.17. Классы-синглетоны
16.18. Параметризованные классы и интерфейсы
16.19. Поля, определяемые пользователем
16.20. Активный класс
16.21. Связь между диаграммами классов и взаимодействия
Глава 17. GRASP: проектирование объектов на основе распределения обязанностей
17.2. Объектное проектирование — примеры входов, видов деятельности и выходов
17.3. Обязанности и проектирование на основе обязанностей
17.4. GRASP — это методический подход к объектному проектированию
17.5. Обязанности, GRASP и диаграммы UML
17.6. Шаблоны
17.7. Где мы находимся
17.8. Небольшой пример объектного проектирования на основе шаблонов GRASP
17.9. Применение шаблонов GRASP для объектного проектирования
17.10. Шаблон Creator
17.12. Шаблон Low Coupling
17.13. Шаблон Controller
17.14. Шаблон High Cohesion
17.15. Дополнительные ресурсы
Глава 18. Примеры объектного проектирования на основе шаблонов GRASP
18.2. Комментарии к артефактам
18.3. Что дальше
18.4. Реализация прецедентов для данной итерации разработки системы NextGen
18.5. Реализация прецедентов для игры “Монополия”
18.6. Итеративное и эволюционное объектное проектирование
18.7. Резюме
Глава 19. Области видимости
19.2. Области видимости
Глава 20. Преобразование проектного решения в программный код
20.2. Преобразование результатов проектирования в программный код
20.3. Создание определений классов на основе диаграмм классов
20.4. Создание методов на основе диаграмм взаимодействия
20.5. Классы коллекций в программном коде
20.6. Исключения и обработка ошибок
20.7. Определение метода Sale.makeLineltem
20.8. Порядок реализации
20.9. Программирование на основе тестирования
20.10. Еще несколько слов о преобразовании проектного решения в код
20.11. Основное программное решение для POS-системы NextGen
20.12. Основные программные решения для игры “Монополия”
Глава 21. Разработка на основе тестирования и рефакторинг
21.2. Рефакторинг
21.3. Дополнительные ресурсы
Часть IV. Вторая итерация фазы развития — дополнительные шаблоны
22.2. Важнейшие свойства UML-средств
22.3. Как выбрать систему проектирования
22.4. Как обновлять диаграммы на основе кода, если они изначально были построены вручную
22.5. Дополнительные ресурсы
Глава 23. Быстрый дополнительный анализ
23.2. Игра “Монополия”
Глава 24. Вторая итерация и дополнительные шаблоны
24.2. Требования для второй итерации
Глава 25. Дополнительные шаблоны GRASP для распределения обязанностей
25.2. Шаблон Pure Fabrication
25.3. Шаблон Indirection
25.4. Шаблон Protected Variations
Глава 26. Применение шаблонов проектирования GoF
26.2. Некоторые принципы GRASP как обобщение других шаблонов
26.3. Анализ на этапе проектирования: модель предметной области
26.6. Еще несколько слов о внешних службах с разными интерфейсами
26.11. Выводы
26.12. Дополнительная литература
Часть V. Третья итерация фазы развития
27.2. Требования третьей итерации для игры “Монополия”
Глава 28. Диаграммы видов деятельности UML
28.2. Как применять диаграммы видов деятельности
28.3. Дополнительные обозначения диаграмм видов деятельности UML
28.4. Рекомендации
28.5. Пример: диаграмма видов деятельности для приложения NextGen
28.6. Диаграммы видов деятельности в UP
28.7. Другие подходы
Глава 29. Диаграммы состояний UML и моделирование
29.2. События, состояния и переходы
29.3. Как применять диаграммы состояний
29.4. Дополнительные обозначения для диаграмм состояний
29.5. Моделирование навигации с помощью диаграммы состояний
29.6. Пример: диаграмма состояний для прецедента системы NextGen
29.7. Диаграммы состояний и UP
29.8. Дополнительная литература
Глава 30. Взаимосвязь прецедентов
30.2. Новые термины: конкретный, абстрактный, основной и дополнительный прецеденты
30.3. Отношение расширяет
30.4. Отношение обобщает
30.5. Диаграммы прецедентов
Глава 31. Дополнительные диаграммы последовательностей и описание операций
Глава 32. Уточнени модели предметной области
32.2. Обобщение
32.3. Определение концептуальных суперклассов и подклассов
32.4. Когда нужно определять концептуальный подкласс
32.5. Когда нужно определять концептуальный суперкласс
32.6. Иерархия концептуальных классов POS-системы NextGen
32.7. Абстрактные концептуальные классы
32.8. Моделирование изменения состояний
32.9. Иерархия классов и наследование
32.10. Классы ассоциаций
32.11. Агрегация и композиция
32.12. Временные интервалы и цшы товаров: устранение ошибки первой итерации
32.13. Имена ролей ассоциаций
32.14. Роли в форме понятий и роли, представленные в ассоциации
32.15. Производные элементы
32.16. Составные ассоциации
32.17. Рефлексивные ассоциации
32.18. Использование пакетов для организации элементов модели предметной области
32.19. Уточненная модель предметной области для игры “Монополия”
Глава 33. Архитектурный анализ
33.2. Точки вариации и эволюции
33.3. Архитектурный анализ
33.4. Общие методы архитектурного анализа
33.5. Определение и анализ архитектурных факторов
33.6. Пример: фрагмент таблицы архитектурных факторов POS-системы NextGen
33.7. Определение архитектурных факторов
33.8. Выводы по архитектурному анализу
33.9. Итеративный архитектурный анализ в UP
33.10. Дополнительная литература
Глава 34. Уточнение логической архитектуры
34.2. Взаимодействия на основе шаблона Layers
34.3. Другие вопросы использования шаблона Layers
34.4. Принцип Model-View Separation
34.5. Дополнительная литература
Глава 35. Новые проектные решения на основе шаблонов GoF
35.2. Переход к локальным службам и обеспечение локальной буферизации
35.3. Обработка отказов
35.5. Реализация нефункциональных или качественных требований
35.6. Доступ к внешним физическим устройствам с помощью шаблона Adapter
35.8. Обработка платежей на основе шаблонов Polymorphism и Do It Myself
35.9. Пример: игра “Монополия”
35.10. Заключение
Глава 36. Проектирование на основе пакетов
36.2. Дополнительная литература
Глава 37. Диаграммы развертывания и компонентов UML
37.2. Диаграммы компонентов
Глава 38. Проектирование каркаса взаимодействия с базой данных на основе шаблонов
38.1. Проблема: объекты, подлежащие постоянному хранению
38.2. Решение: каркас интерфейса с базой данных
38.3. Каркасы
38.4. Требования к каркасу интерфейса с базой данных
38.5. Основные принципы
38.6. Шаблон представления объектов в виде таблиц
38.7. Профиль моделирования данных UML
38.8. Шаблон Object Identifier
38.9. Доступ к службе взаимодействия с базой данных на основе шаблона Facade
38.10. Объекты-преобразователи: шаблон Database Mapper или Database Broker
38.11. Разработка каркаса на основе шаблона Template Method
38.12. Материализация на основе шаблона Template Method
38.13. Настройка преобразователей с помощью объекта MapperFactory
38.14. Шаблон Cache Management
38.15. Объединение и сокрытие операторов SQL в одном классе
38.16. Состояние транзакции и шаблон State
38.17. Обработка транзакций на основе шаблона Command
38.18. Пассивная материализация на основе шаблона Virtual Proxy
38.19. Представление отношений в таблицах
38.20. Суперкласс PersistentObject
38.21. Нерешенные вопросы
Глава 39. Документирование архитектуры с помощью АН-1 представления
39.2. Структура документа SAD
39.3. Пример: описание архитектуры POS-системы Next Gen
39.4. Пример: документ SAD для каркаса Struts
39.5. Итеративное документирование архитектуры
39.6. Дополнительная литература
Часть VI. Специальные вопросы
40.2. Адаптивное и предиктивное планирование
40.3. Планы для фазы и итерации
40.4. Как составить план итерации с учетом прецедентов и сценариев
40.5. Приблизительность начальных оценок
40.6. Организация артефактов проекта
40.7. Вы не поняли принципов итеративного планирования, если
40.8. Дополнительная литература
Приложение А. Артефакты унифицированного процесса, шаблоны GRASP и условные обозначения языка UML
Приложение Б. Словарь терминов
Литература
Предметный указатель
Текст
                    ПРИМЕНЕНИЕ UML 2.0
И ШАБЛОНОВ
ПРОЕКТИРОВАНИЯВведение в объектно-ориентированный анализ,
проектирование и итеративную разработкуТРЕТЬЕ ИЗДАНИЕ“Люди часто спрашивают меня о том, с помощью какой книги лучше всего познакомиться
с миром объектно-ориентированного проектирования. С тех пор, как я увидел книгу
Применение UML и шаблонов проектирования, я рекомендую именно ее.”- Мартин ФаулерКрэг Ларман

ПРИМЕНЕНИЕ UML 2.0
И ШАБЛОНОВ
ПРОЕКТИРОВАНИЯТРЕТЬЕ ИЗДАНИЕ
APPLYING UML
AND
PATTERNSАл Introduction to Object-Oriented analysis and Design
and Iterative DevelopmentTHIRD EDITIONCraig LarmanPRENTICEHALLPTRPrentice Hall PTRUpper Saddle River, NJ 07458
www.phptr.com
ПРИМЕНЕНИЕ UML 2.0
И ШАБЛОНОВ
ПРОЕКТИРОВАНИЯВведение в объектно-ориентированный анализ,
проектирование и итеративную разработкуТРЕТЬЕ ИЗДАНИЕКрэг ЛарманИздательский дом “Вильясм”
Москва • Санкт-Петербург • Киев
2013
ББК 32.973.26-018.2.75
Л25
УДК 681.3.07Издательский дом “Вильямс”Зав. редакцией С.Н. ТригубПеревод с английского и редакция канд. техн. наук А.Ю. ШелестоваПо общим вопросам обращайтесь в Издательский дом “Вильямс” по адресу:
info@williamspublishing.com, http://www.williamspublishing.comЛарман, Крэг.Л25 Применение UML 2.0 и шаблонов проектирования. Практическое руководство.
3-е издание. : Пер. с англ. — М. : ООО “И.Д. Вильямс”, 2013. — 736 с. : ил. — Парал.
тит. англ.ISBN 978-5-8459-1185-8 (рус.)В книге рассматриваются основные принципы и приемы объектно-ориентирован¬
ного анализа и проектирования (ООА/П). В ней вы найдете сведения об итеративном
и гибком моделировании, шаблонах проектирования, архитектурном анализе и мно¬
гих других вопросах. Весь материал рассматривается в контексте гибкого подхода к
разработке с совместным применением процесса UP и других итеративных методов.В книге рассматривается два реальных примера, позволяющих на практике освоить
принципы ООА/П, а также изучить новейшую систему обозначений языка UML 2.Книга будет хорошим руководством для всех, кто интересуется вопросами ООА/П,
языком моделирования UML 2 и современными эволюционными подходами к разра¬
ботке программного обеспечения.ББК 32.973.26-018.2.75Все названия программных продуктов являются зарегистрированными торговыми марками соот¬
ветствующих фирм.Никакая часть настоящего издания ни в каких целях не может быть воспроизведена в какой бы
то ни было форме и какими бы то ни было средствами, будь то электронные или механические,
включая фотокопирование и запись на магнитный носитель, если на это нет письменного разреше¬
ния издательства Prentice Hall, Inc.All rights reserved. This publication is protected by copyright, and permission must be obtained from
the publisher prior to any prohibited reproduction, storage in a retrieval system, or transmission in any
form or by any means, electronic, mechanical, photocopying, recording, or likewise.Russian language edition published by Williams Publishing House according to the Agreement with
R&I Enterprises International, Copyright © 2013ISBN 978-5-8459-1185-8 (pyc.)
ISBN 0-13-148906-2 (англ.)© Издательский дом “Вильямс”, 2013
© Pearson Education, Inc., 2005
ОглавлениеПредисловие 19Введение 21Часть I. Введение 27Глава 1. Объектно-ориентированный анализ и проектирование 29Глава 2. Итеративный, эволюционный и гибкий процесс 45Глава 3. Конкретные примеры 73Часть II. Начальная фаза 79Глава 4. Начальная фаза — это не стадия анализа требований 81Глава 5. Эволюционное осмысление требований 87Глава 6. Описание прецедентов 95Глава 7. Другие требования 135Часть III. Первая итерация фазы развития - основы 155Глава 8. Итерация 1 — основы 157Глава 9. Модели предметной области 165Глава 10. Системные диаграммы последовательностей 203Глава 11. Описание операций 211Глава 12. Итеративный переход от анализа требованийк проектированию 225Глава 13. Логическая архитектура и диаграммы пакетов UML 227Глава 14. Переход к объектному проектированию 243Глава 15. Диаграммы взаимодействия на UML 251Глава 16. Диаграммы классов UML 277Глава 17. GRASP: проектирование объектов на основераспределения обязанностей 299Глава 18. Примеры объектного проектированияна основе шаблонов GRASP 347Глава 19. Области видимости 387Глава 20. Преобразование проектного решения в программный код 393Глава 21. Разработка на основе тестирования и рефакторинг 409
Часть IV. Вторая итерация фазы развития —
дополнительные шаблоны 419Глава 22. Средства построения диаграмм UML 421Глава 23. Быстрый дополнительный анализ 425Глава 24. Вторая итерация и дополнительные шаблоны 431Глава 25. Дополнительные шаблоны GRASPдля распределения обязанностей 437Глава 26. Применение шаблонов проектирования GoF 459Часть V. Третья итерация фазы развития 495Глава 27. Третья итерация — вспомогательные вопросы 497Глава 28. Диаграммы видов деятельности UML 499Глава 29. Диаграммы состояний UML и моделирование 507Глава 30. Взаимосвязь прецедентов 515
Глава 31. Дополнительные диаграммы последовательностейи описание операций 523Глава 32. Уточнение модели предметной области 529Глава 33. Архитектурный анализ 561Глава 34. Уточнение логической архитектуры 579Глава 35. Новые проектные решения на основе шаблонов GoF 599Глава 36. Проектирование на основе пакетов 631Глава 37. Диаграммы развертывания и компонентов UML 639
Глава 38. Проектирование каркаса взаимодействияс базой данных на основе шаблонов 643Глава 39. Документирование архитектурыс помощью W+1 представления 673Часть VI. Специальные вопросы 687Глава 40. Еще раз об итеративной разработкеи гибком управлении проектом 689Приложение А. Артефакты унифицированного процесса, шаблоныGRASP и условные обозначения языка UML 699Приложение Б. Словарь терминов 705Литература 711Предметный указатель 717
СодержаниеПредисловие 19Введение 21Образовательные и Web-pecypcbi 22Для кого предназначена эта книга 22Что необходимо знать 22Примеры на языке Java 22Структура книги 23Об авторе 23Контакты 24Дополнения к предыдущему изданию 24Благодарности 25Соглашения, принятые в книге 25От издательства 26Часть I. Введение 27Глава 1. Объектно-ориентированный анализ и проектирование 291.1. Что вы узнаете из этой книги? 291.2. Основная цель обучения 321.3. Что такое анализ и проектирование 331.4. Объектно-ориентированный анализ и проектирование 331.5. Краткий пример 341.6. Что такое UML 371.7. Визуальное моделирование — хороший стиль 411.8. История 411.9. Дополнительные ресурсы 43Глава 2. Итеративный, эволюционный и гибкий процесс 452.1. Унифицированный процесс и другие методы 462.2. Что такое итеративная и эволюционная разработка 482.3. Последовательный жизненный цикл 522.4. Как выполнять итеративный и эволюционный анализ и проектирование 542.5. Итеративное планирование на основе рисков и с учетом потребностей
пользователей 562.6. Что такое гибкие методы 582.7. Что такое гибкое моделирование 592.8. Что такое гибкий унифицированный процесс 622.9. Другие важные принципы унифицированного процесса 632.10. Фазы унифицированного процесса 632.11. Дисциплины унифицированного процесса 642.12. Настройка процесса и выбор инструментов UP 67
8 Содержание2.13. Вы не поняли, что такое итеративная разработка или
унифицированный процесс, если...692.14. История692.15. Дополнительные ресурсы70Глава 3. Конкретные примеры733.1. Какие вопросы рассматриваются и рассматриваются при
изучении конкретных примеров743.2. Стратегия описания конкретных примеров: итеративная
разработка + итеративное изучение753.3. Пример 1: POS-система NextGen763.4. Пример 2: игра Monopoly®77Часть II. Начальная фаза79Глава 4. Начальная фаза - это не стадия анализа требований814.1. Что такое начальная фаза824.2. Какова длительность начальной фазы834.3. Какие артефакты относятся к начальной фазе834.4. Вы не поняли, что такое начальная фаза, если...854.5. Как использовать UML на начальной стадии85Глава 5. Эволюционное осмысление требований875.1. Определение требований885.2. Определение требований для эволюционного и каскадного процессов
разработки885.3. Грамотное определение требований905.4. Типы и категории требований905.5. Как требования связаны с артефактами UP915.6. Имеются ли примеры этих артефактов в данной книге925.7. Дополнительные ресурсы92Глава 6. Описание прецедентов956.1. Пример966.2. Некоторые определения966.3. Прецеденты и модель прецедентов986.4. Зачем нужны описания прецедентов996.5. Прецеденты и функциональные требования1006.6. Три типа исполнителей1006.7. Основные форматы прецедентов1016.8. Пример развернутого описания прецедента Оформление продажи1016.9. Пояснения1076.10. Другие форматы описания прецедентов1136.11. Описание прецедентов, относящихся к интерфейсу пользователя,
в свободном стиле1146.12. Описания прецедентов должны быть лаконичными116
Содержание 96.13. Описание прецедентов в формате “черный ящик” 1166.14. Примите точку зрения исполнителя 1166.15. Как выделять прецеденты 1176.16. Как выделить полезные прецеденты 1216.17. Диаграммы прецедентов 1236.18. Диаграммы видов деятельности 1256.19. Дополнительные преимущества описания прецедентов 1256.20. Пример: игра “Монополия” 1266.21. Прецеденты в рамках итеративной разработки 1286.22. История 1336.23. Дополнительные ресурсы 133Глава 7. Другие требования 1357.1. Насколько полны приводимые примеры? 1367.2. Нужно ли детально анализировать требования на начальнойстадии разработки? 1367.3. Нужно ли помещать документацию на Web-узле проекта? 1377.4. Пример NextGen: фрагмент дополнительной спецификации 1377.5. Дополнительная спецификация (комментарии) 1407.6. Пример для системы NextGen: видение (фрагмент) 1427.7. Видение (комментарий) 1457.8. Пример системы NextGen: словарь терминов (фрагмент) 1487.9. Комментарии: словарь терминов 1497.10. Пример для системы NextGen: бизнес-правила (правила предметной области) 1507.11. Бизнес-правила (комментарии) 1517.12. Эволюция требований в итеративном процессе разработки 1517.13. Дополнительные ресурсы 153Часть III. Первая итерация фазы развития — основы 155Глава 8. Итерация 1 — основы 1578.1. Требования и акценты первой итерации: основные вопросы ООА/П 1588.2. Начальная фаза и стадия развития 1608.3. Планирование следующей итерации 163Глава 9. Модели предметной области 1659.1. Пример 1679.2. Что такое модель предметной области 1689.3. Зачем создавать модель предметной области 1719.4. Как создать модель предметной области 1729.5. Как выделить концептуальные классы 1739.6. Пример выделения концептуальных классов 1769.7. Построение диаграммы классов в рамках гибкого процесса разработки 1779.8. Автоматизированное построение модели в рамках гибкого подходак разработке 1779.9. Элементы отчета: включать ли понятие “товарный чек” в модель 178
10 Содержание9.10. Имена и модели: стратегия построения карт 1789.11. Как моделировать “нереальный” мир 1799.12. Типичная ошибка при выделении концептуальных классов 1799.13. Когда использовать классы описаний 1809.14. Ассоциации 1829.15. Примеры: ассоциации в моделях предметных областей 1899.16. Атрибуты 1909.17. Атрибуты в моделях предметных областей 1989.18. Насколько корректна модель предметной области 1999.19. Итеративное и эволюционное моделирование предметной области 2009.20. Дополнительные ресурсы 201Глава 10. Системные диаграммы последовательностей 20310.1. Пример СДП для приложения NextGen 20510.2. Системные диаграммы последовательностей 20610.3. Зачем строить СДП 20610.4. Применение UML для построения диаграммы последовательности 20710.5. Системные диаграммы последовательностей и прецеденты 20710.6. Имена системных событий и операций 20810.7. Как моделировать взаимодействие с внешними системами 20810.8. Диаграммы последовательностей и словарь терминов 20910.9. Пример диаграммы последовательности для игры “Монополия” 20910.10. Итеративное и эволюционное построение СДП 21010.11. История и дополнительные ресурсы 210Глава 11. Описание операций 21111.1. Пример 21311.2. Разделы описания 21311.3. Что такое системная операция 21311.4. Постусловия 21411.5. Постусловия описания операции enterltem 21711.6. Описание операций приводит к изменению предметной области 21711.7. Когда нужны описания операций? 21811.8. Составление описания 21811.9. Пример описания операции для POS-системы NextGen 21911.10. Описание операций для игры “Монополия” 22111.11. Описания операций на UML и OCL 22111.12. Описания операций в рамках UP 22211.13. Немного истории 22311.14. Дополнительные ресурсы 223Глава 12. Итеративный переход от анализа требований
к проектированию 22512.1. Занимаясь итеративной разработкой, делайте это правильно 22612.2. Раннее начало всех видов деятельности 22612.3. Возможно, на это потребуются недели? 226
Содержание 11Глава 13. Логическая архитектура и диаграммы пакетов UML 22713.1. Пример 22813.2. Что такое логическая архитектура 22813.3. На каких уровнях сосредоточено описание примеров? 23013.4. Программная архитектура системы 23113.5. Диаграммы пакетов UML 23113.6. Проектирование на основе шаблона Layers 23213.7. Принцип Model-View Separation 23813.8. Взаимосвязь между СДП, системными операциями и уровнями 24013.9. Логическая архитектура и диаграмма пакетов для приложения NextGen 24113.10. Пример логической архитектуры игры “Монополия” 24113.11. Дополнительные ресурсы 242Глава 14. Переход к объектному проектированию 24314.1. Гибкое моделирование и облегченный процесс построения диаграмм UML 24414.2. CASE-средства UML 24514.3. Сколько времени занимает рисование до начала кодирования 24514.4. Статические и динамические модели объектов 24614.5. Важнее иметь навыки объектного проектирования, чем знать систему
обозначений UML 24714.6. Другие методы проектирования объектов: карты CRC 248Глава 15. Диаграммы взаимодействия на UML 25115.1. Диаграммы последовательностей и коммуникации 25215.2. Проблема для новичков 25515.3. Основные обозначения UML для диаграмм взаимодействия 25515.4. Основные обозначения диаграммы последовательностей 25715.5. Основные обозначения диаграммы коммуникации 269Глава 16. Диаграммы классов UML 27716.1. Применение UML: система обозначений для диаграммы классов 27816.2. Определение: диаграмма классов проектирования 27816.3. Определение: классификатор 28016.4. Способы представления атрибутов UML: имя атрибута и линии ассоциаций 28016.5. Блоки примечаний: примечания, комментарии, ограничения и тела методов 28416.6. Операции и методы 28516.7. Ключевые слова 28616.8. Стереотипы, профили и метки 28716.9. Свойства и строки свойств 28816.10. Обобщение, абстрактные классы, абстрактные операции 28816.11. Зависимость 28916.12. Интерфейсы 29116.13. Композиция или агрегация 29216.14. Ограничения 29316.15. Уточненная ассоциация 29416.16. Класс ассоциации 294
12 Содержание16.17. Классы-синглетоны 29516.18. Параметризованные классы и интерфейсы 29516.19. Поля, определяемые пользователем 29616.20. Активный класс 29716.21. Связь между диаграммами классов и взаимодействия 297Глава 17. GRASP: проектирование объектов на основе
распределения обязанностей 29917.1. UML и принципы проектирования 30017.2. Объектное проектирование — примеры входов,видов деятельности и выходов 30017.3. Обязанности и проектирование на основе обязанностей 30417.4. GRASP — это методический подход к объектному проектированию 30517.5. Обязанности, GRASP и диаграммы UML 30617.6. Шаблоны 30617.7. Где мы находимся? 30917.8. Небольшой пример объектного проектирования на основе шаблонов GRASP 30917.9. Применение шаблонов GRASP для объектного проектирования 31817.10. Шаблон Creator 31917.11. Шаблон Information Expert (или Expert) 32117.12. Шаблон Low Coupling 32617.13. Шаблон Controller 32917.14. Шаблон High Cohesion 34117.15. Дополнительные ресурсы 345Глава 18. Примеры объектного проектирования
на основе шаблонов GRASP 34718.1. Реализация прецедентов 34818.2. Комментарии к артефактам 34918.3. Что дальше? 35318.4. Реализация прецедентов для данной итерации разработки системы NextGen 35318.5. Реализация прецедентов для игры “Монополия” 37318.6. Итеративное и эволюционное объектное проектирование 38318.7. Резюме 385Глава 19. Области видимости 38719.1. Видимость объектов 38819.2. Области видимости 389Глава 20. Преобразование проектного решения в программный код 39320.1. Программирование и итеративный, эволюционный процесс разработки 39420.2. Преобразование результатов проектирования в программный код 39520.3. Создание определений классов на основе диаграмм классов 39520.4. Создание методов на основе диаграмм взаимодействия 39620.5. Классы коллекций в программном коде 39820.6. Исключения и обработка ошибок 399
Содержание 1320.7. Определение метода Sale.makeLineltem 39920.8. Порядок реализации 40020.9. Программирование на основе тестирования 40020.10. Еще несколько слов о преобразовании проектного решения в код 40120.11. Основное программное решение для POS-системы NextGen 40120.12. Основные программные решения для игры “Монополия” 404Глава 21. Разработка на основе тестирования и рефакторинг 40921.1. Разработка на основе тестирования 41021.2. Рефакторинг 41321.3. Дополнительные ресурсы 416Часть IV. Вторая итерация фазы развития —
дополнительные шаблоны 419Глава 22. Средства построения диаграмм UML 42122.1. Прямое, обратное и циклическое проектирование 42222.2. Важнейшие свойства UML-средств 42322.3. Как выбрать систему проектирования 42322.4. Как обновлять диаграммы на основе кода, если они изначальнобыли построены вручную 42422.5. Дополнительные ресурсы 424Глава 23. Быстрый дополнительный анализ 42523.1. POS-система NextGen 42623.2. Игра “Монополия” 428Глава 24. Вторая итерация и дополнительные шаблоны 43124.1. От первой ко второй итерации 43224.2. Требования для второй итерации 433Глава 25. Дополнительные шаблоны GRASP
для распределения обязанностей 43725.1. Шаблон Polymorphism 43825.2. Шаблон Pure Fabrication 44525.3. Шаблон Indirection 44925.4. Шаблон Protected Variations 451Глава 26. Применение шаблонов проектирования GoF 45926.1. Шаблон Adapter (GoF) 46026.2. Некоторые принципы GRASP как обобщение других шаблонов 46226.3. Анализ на этапе проектирования: модель предметной области 46326.4. Шаблон Factory (GoF) 46426.5. Шаблон Singleton (GoF) 466
14 Содержание26.6. Еще несколько слов о внешних службах с разными интерфейсами 46926.7. Шаблон Strategy (GoF) 47126.8. Шаблон Composite (GoF) и другие принципы проектирования 47526.9. Шаблон Facade (GoF) 48326.10. Шаблон Observer/Publish-Subscribe/Delegation Event Model (GoF) 48526.11. Выводы 49326.12. Дополнительная литература 494Часть V. Третья итерация фазы развития 495Глава 27. Третья итерация - вспомогательные вопросы 49727.1. Требования третьей итерации для POS-системы NextGen 49827.2. Требования третьей итерации для игры “Монополия” 498Глава 28. Диаграммы видов деятельности UML 49928.1. Пример 50028.2. Как применять диаграммы видов деятельности 50128.3. Дополнительные обозначения диаграмм видов деятельности UML 50328.4. Рекомендации 50328.5. Пример: диаграмма видов деятельности для приложения NextGen 50428.6. Диаграммы видов деятельности в UP 50528.7. Другие подходы 506Глава 29. Диаграммы состояний UML и моделирование 50729.1. Пример 50829.2. События, состояния и переходы 50829.3. Как применять диаграммы состояний 50929.4. Дополнительные обозначения для диаграмм состояний 51129.5. Моделирование навигации с помощью диаграммы состояний 51229.6. Пример: диаграмма состояний для прецедента системы NextGen 51329.7. Диаграммы состояний и UP 51329.8. Дополнительная литература 513Глава 30. Взаимосвязь прецедентов 515ЗОЛ. Отношение включает 51630.2. Новые термины: конкретный, абстрактный, основнойи дополнительный прецеденты 51930.3. Отношение расширяет 52030.4. Отношение обобщает 52130.5. Диаграммы прецедентов 521Глава 31. Дополнительные диаграммы последовательностей
и описание операций 52331.1. Приложение NextGen 524
Содержание 15Глава 32. Уточнение модели предметной области 52932.1. Новые понятия модели предметной области системы NextGen 53032.2. Обобщение 53232.3. Определение концептуальных суперклассов и подклассов 53332.4. Когда нужно определять концептуальный подкласс 53632.5. Когда нужно определять концептуальный суперкласс 53832.6. Иерархия концептуальных классов POS-системы NextGen 53832.7. Абстрактные концептуальные классы 54132.8. Моделирование изменения состояний 54232.9. Иерархия классов и наследование 54332.10. Классы ассоциаций 54332.11. Агрегация и композиция 54632.12. Временные интервалы и цшы товаров: устранение ошибкипервой итерации 54832.13. Имена ролей ассоциаций 54932.14. Роли в форме понятий и роли, представленные в ассоциации 55032.15. Производные элементы 55132.16. Составные ассоциации 55232.17. Рефлексивные ассоциации 55332.18. Использование пакетов для организации элементов моделипредметной области 55332.19. Уточненная модель предметной области для игры “Монополия” 559Глава 33. Архитектурный анализ 56133.1. Когда нужно приступать к архитектурному анализу 56233.2. Точки вариации и эволюции 56233.3. Архитектурный анализ 56333.4. Общие методы архитектурного анализа 56433.5. Определение и анализ архитектурных факторов 56533.6. Пример: фрагмент таблицы архитектурных факторов POS-системы NextGen 56833.7. Определение архитектурных факторов 57033.8. Выводы по архитектурному анализу 57533.9. Итеративный архитектурный анализ в UP 57633.10. Дополнительная литература 577Глава 34. Уточнение логической архитектуры 57934.1. Пример: логическая архитектура приложения NextGen 58034.2. Взаимодействия на основе шаблона Layers 58534.3. Другие вопросы использования шаблона Layers 59134.4. Принцип Model-View Separation 59634.5. Дополнительная литература 597Глава 35. Новые проектные решения на основе шаблонов GoF 59935.1. Пример: POS-система NextGen 60035.2. Переход к локальным службам и обеспечение локальной буферизации 60035.3. Обработка отказов 604
16 Содержание35.4. Взаимодействие с локальными службами на основе шаблона Proxy (GoF) 61135.5. Реализация нефункциональных или качественных требований 61535.6. Доступ к внешним физическим устройствам с помощью шаблона Adapter 61535.7. Шаблон Abstract Factory (GoF) для семейства взаимосвязанных объектов 61735.8. Обработка платежей на основе шаблонов Polymorphism и Do It Myself 62135.9. Пример: игра “Монополия” 62735.10. Заключение 630Глава 36. Проектирование на основе пакетов 63136.1. Рекомендации по организации пакетов 63236.2. Дополнительная литература 637Глава 37. Диаграммы развертывания и компонентов UML 63937.1. Диаграммы развертывания 63937.2. Диаграммы компонентов 641Глава 38. Проектирование каркаса взаимодействия
с базой данных на основе шаблонов 64338.1. Проблема: объекты, подлежащие постоянному хранению 64438.2. Решение: каркас интерфейса с базой данных 64538.3. Каркасы 64538.4. Требования к каркасу интерфейса с базой данных 64638.5. Основные принципы 64738.6. Шаблон представления объектов в виде таблиц 64738.7. Профиль моделирования данных UML 64838.8. Шаблон Object Identifier 64838.9. Доступ к службе взаимодействия с базой данных на основе шаблона Facade 64938.10. Объекты-преобразователи: шаблон Database Mapper или Database Broker 65038.11. Разработка каркаса на основе шаблона Template Method 65238.12. Материализация на основе шаблона Template Method 65438.13. Настройка преобразователей с помощью объекта MapperFactory 65938.14. Шаблон Cache Management 65938.15. Объединение и сокрытие операторов SQL в одном классе 66038.16. Состояние транзакции и шаблон State 66138.17. Обработка транзакций на основе шаблона Command 66438.18. Пассивная материализация на основе шаблона Virtual Proxy 66738.19. Представление отношений в таблицах 67038.20. Суперкласс PersistentObject 67038.21. Нерешенные вопросы 671Глава 39. Документирование архитектуры
с помощью АН-1 представления 67339.1. Документ SAD и архитектурные представления 67439.2. Структура документа SAD 67739.3. Пример: описание архитектуры POS-системы Next Gen 67739.4. Пример: документ SAD для каркаса Struts 682
Содержание 1739.5. Итеративное документирование архитектуры 68639.6. Дополнительная литература 686Часть VI. Специальные вопросы 687Глава 40. Еще раз об итеративной разработке
и гибком управлении проектом 68940.1. Как спланировать итерацию 69040.2. Адаптивное и предиктивное планирование 69040.3. Планы для фазы и итерации 69240.4. Как составить план итерации с учетом прецедентов и сценариев 69340.5. Приблизительность начальных оценок 69540.6. Организация артефактов проекта 69540.7. Вы не поняли принципов итеративного планирования, если... 69640.8. Дополнительная литература 697Приложение А. Артефакты унифицированного процесса, шаблоны
GRASP и условные обозначения языка UML 699
Приложение Б. Словарь терминов 705
Литература 711Предметный указатель717
Джулии, Хаяли и Анне,
спасибо за любовь и поддержку.ПредисловиеПрограммирование — это развлечение, но разработка качественных программ —
тяжелый труд. Между хорошей идеей, формулировкой требований, составлением “ви¬
дения” и готовым программным продуктом лежит гораздо больше, чем просто про¬
граммирование. Анализ и проектирование, определение способов решения задачи,
выбор программных средств, удобное представление проектного решения, реализа¬
ция и сопровождение программы — это основные вопросы, которые рассматривают¬
ся в данной книге. Это то, что вам предстоит узнать.Унифицированный язык моделирования UML стал общепринятым языком раз¬
работки программных систем. Это визуальный язык, используемый для изложения
основных идей. В книге основное внимание уделяется применению элементов языка
UML, а не особенностям самого языка.При разработке сложных систем важную роль играют шаблоны. Шаблоны про¬
ектирования программ позволяют описать фрагменты проектного решения, повтор¬
но использовать хорошие идеи и перенять полезный опыт других разработчиков.
Шаблоны имеют имена и определяются в форме абстрактных эвристик, правил и
лучших наработок объектно-ориентированной технологии. Ни один здравомысля¬
щий разработчик не захочет начинать создание системы с чистого листа. Эта книга
как раз и предоставляет целую палитру готовых проектных решений.Однако проектные решения выглядят слишком сухо и неестественно в отрыве от
самого процесса разработки. В этой связи стоит отметить, что в новом издании кни¬
ги автор, Крэг Ларман (Craig Larman), положил в основу разработки унифицирован¬
ный процесс UP, показал, как создавать системы в рамках этого процесса. В книге
достаточно реалистично показан пример разработки системы в рамках итеративного
процесса с учетом рисков и архитектурных особенностей. Разработка программной
системы показана в динамике. Виды деятельности процесса разработки увязаны с
другими задачами, поэтому они не выгладят оторванными от жизни. Автор книги и я
оценили реальные преимущества итеративной разработки. Именно они и положены
в основу материала, который предназначен для читателя.На мой взгляд, в книге описано множество взаимосвязанных компонентов. Здесь
систематически изложены основы объектно-ориентированного анализа и проекти¬
рования (ООА/П). Автор книги — талантливый преподаватель, замечательный мето¬
дист и признанный гуру в области применения объектно-ориентированного подхода,
имеющий тысячи учеников по всему миру. Крэг Ларман описал этот метод в контек¬
сте унифицированного процесса. Он постепенно вводит все более сложные шабло¬
ны, что делает книгу особенно полезной “при столкновении” лицом к лицу с реаль¬
ными жизненными сложностями. Кроме того, здесь использована наиболее широко
применяемая система обозначений.Я очень рад, что мне представилась возможность работать напрямую с автором
этой книги. Я с удовольствием прочел ее первое издание и был польщен предложе¬
20 Предисловиением рецензировать новые. В процессе работы над книгой мы несколько раз встре¬
чались и интенсивно обменивались электронными сообщениями. Я многому научил¬
ся у Крэга, в том числе в контексте унифицированного процесса разработки и его
реализации в конкретной организации. Надеюсь, книга станет очень полезной и для
вас, даже если вы уже знакомы с принципами объектно-ориентированного анализа и
проектирования. Как и я, вы сможете освежить в памяти его основные принципы и
углубить свои знания с помощью доступных и грамотных пояснений Крэга.Приятного чтения!Филипп Крачтен (Philippe Kmchten),
профессор в области программной инженерии
университета British Columbia,
в прошлом сотрудник компании Rational Software,Ванкувер, Канада.
ВведениеСпасибо за проявленное внимание к этой книге! Перед вами — практическое вве¬
дение в область объектно-ориентированного анализа и проектирования (ООА/П), а
также в смежные области итеративного процесса разработки. Мне очень приятно,
что предыдущие издания этой книги имели большой успех во всем мире и были пере¬
ведены на многие языки. Хотелось бы поблагодарить всех читателей!Эта книга будет полезна читателям по следующим причинам.Во-первых, в настоящее время объектная технология используется чрезвычайно
широко. Поэтому овладение принципами ООА/П — это ключ к достижению успеха в
области разработки современного программного обеспечения.Во-вторых, тем, кто еще не знаком с вопросами объектно-ориентированного ана¬
лиза и проектирования, будет полезно освоить эту область знаний. Данная книга ста¬
нет хорошим путеводителем, поскольку в ней описан гибкий подход к применению
унифицированного процесса (Unified Process), понимание которого позволит шаг за
шагом освоить путь от определения требований к системе до создания кода.В-третьих, унифицированный язык моделирования UML является признанным
стандартом для описания моделей, который обеспечивает возможность общения
между разработчиками. В данной книге вопросы ООА/П освещаются с использова¬
нием системы обозначений UML.В-четвертых, идиомы и удачные проектные решения при создании объектно-ори¬
ентированных систем были сформулированы в виде шаблонов, которые эксперты
предлагают применять при создании систем. Из этой книги вы узнаете, как приме¬
нять шаблоны проектирования, включая популярные шаблоны GoF, а также шаблоны
GRASP, в которых сконцентрированы фундаментальные принципы распределения
обязанностей при объектно-ориентированном проектировании. Изучив и применив
шаблоны, можно повысить уровень своего мастерства в области анализа и проекти¬
рования.В-пятых, структура и содержание этой книги проверены годами практического
опыта обучения специалистов искусству объектно-ориентированного анализа и про¬
ектирования. Этот опыт позволил выработать четкий, мотивированный и эффектив¬
ный подход к изучению данного предмета, обеспечивающий оптимальность процесса
чтения и обучения.В-шестых, для иллюстрации всего процесса объектно-ориентированного анализа
и проектирования в книге приводится исчерпывающее описание двух реальных при¬
меров.В-седьмых, здесь показано, как отобразить артефакты объектно-ориентированно¬
го проектирования в коде на языке Java. Кроме того, в книге вы найдете сведения о
разработке на основе тестирования и рефакторинге.В-восьмых, в книге рассказывается о том, как разработать многоуровневую архи¬
тектуру и связать уровень графического интерфейса пользователя с уровнями пред¬
метной области и технических служб.И наконец, здесь рассказывается, как разработать объектно-ориентированный
каркас и использовать его для работы с базой данных.
22 ВведениеОбразовательные и Web-ресурсыСтатьи, посвященные объектной технологии, можно найти по адресу www.craiglarman.com.Сотни, а может и тысячи, преподавателей во всем мире используют эту книгу в
своей профессиональной деятельности. Она переведена более чем на десять языков.
На Web-узле автора содержится множество образовательных ресурсов, включая все
рисунки данной книги, оформленные в виде презентаций Microsoft PowerPoint. Если
вы работаете в области образования, обращайтесь к автору за дополнительными
учебными материалами.В свою очередь, автор коллекционирует материалы других преподавателей, ис¬
пользующих данную книгу. Если у вас есть чем поделиться, свяжитесь с автором.Для кого предназначена эта книгаЭту книгу следует рассматривать как введение в область ООА/П, а также связанные
с ними проблемы анализа требований и этапы итеративной разработки на примере
унифицированного процесса. Она не предназначена для профессионалов, а рассчита¬
на на следующую аудиторию.■ Разработчики и студенты с опытом создания программ на объектно-ориентиро¬
ванных языках, которые пока не являются экспертами в области объектно-ори¬
ентированного анализа и проектирования.■ Студенты компьютерных специальностей, изучающие объектную технологию.■ Специалисты по объектно-ориентированному анализу и проектированию, кото¬
рые хотят изучить систему обозначений унифицированного языка моделирова¬
ния UML (Unified Modeling Language), ознакомиться с шаблонами или углубить
свои знания в области объектно-ориентированного анализа и проектирования.Что необходимо знатьДля успешного овладения предлагаемым материалом необходимо иметь следую¬
щие знания.■ Навыки и опыт программирования на объектно-ориентированном языке типа
Java, С#, C++ или Python.■ Основные понятия объектной технологии, такие как класс, экземпляр, интер¬
фейс, полиморфизм, инкапсуляция и наследование.Определения основных понятий объектной технологии в книге не приводятся.Примеры на языке JavaВ книге приводятся примеры кода и обсуждаются вопросы реализации принци¬
пов ООА/П на языке Java, поскольку в последнее время он приобрел очень широкую
популярность. Однако представленные здесь идеи можно применить к большинству
(если не ко всем) объектно-ориентированных языков программирования» в том чис¬
ле C# или Python.
Введение 23Структура книгиОбщий принцип организации книги сводится к следующему. Вопросы объек¬
тно-ориентированного анализа и проектирования рассматриваются в той последо¬
вательности, в которой они возникают в процессе разработки системы в течение
“начальной” фазы (термин из описания унифицированного процесса) и трех после¬
довательных итераций (рис. В.1).Структура книги
ОбзорИтерация 1Итерация 2Итерация 3СпециальныевопросыОбъектно* I
ориентированный 1
анализ 1Объектно-ориентированноепроектированиеОтображение
проектного
решения в кодВопросы щобъектно-ориентированного
анализа и проектирования
рассматриваются
на итерациях 1, 2 и 3Рис. В.1. Организация книги соответствует процессу разработки программной системы1. В главах, посвященных “начальной” фазе, рассматриваются вопросы анализа
требований.2. При описании первой итерации ООА/П вводятся основные понятия анализа
и проектирования, а также рассматриваются вопросы распределения обязанно¬
стей между объектами.3. При переходе ко второй итерации основное внимание уделяется проектирова¬
нию объектов, особенно применению некоторых популярных шаблонов проек¬
тирования.4. При рассмотрении третьей итерации затрагивается множество вопросов, в том
числе связанных с анализом архитектуры и проектированием каркасов.Об автореКрэг Ларман (Craig Larman) руководит исследовательскими работами в между¬
народной консалтинговой компании Valtech, имеющей свои представительства в
Европе, Азии и Северной Америке. Эта компания специализируется на разработке
систем электронной коммерции, применении объектных технологий и итеративной
разработке программных систем в рамках унифицированного процесса.Начиная с середины 1980-х годов Крэг помогал тысячам разработчиков освоить
объектно-ориентированную технологию программирования, анализа и проектирова¬
ния с использованием UML, а также консультировал организации по вопросам реали¬
зации итеративного процесса.
24 ВведениеПосле неудачной попытки сделать карьеру странствующего уличного музыканта
в 1970-е годы он занялся разработкой программных систем на языках APL, PL/1 и
CICS. В начале 1980-х годов он стал “поклонником” искусственного интеллекта, ме¬
тодов проектирования баз знаний и способов обработки естественных языков и на¬
чал разрабатывать базы знаний на языках Lisp, Prolog и Smalltalk. Кроме того, Крэг
работал также в компаниях, которые занимались разработкой коммерческих си¬
стем на Java, .NET и C++. Он солирует на гитаре в своей группе Changing Requirements
(Изменчивые требования) (вообще-то, группа называется просто Requirements, но ее
состав периодически изменяется).Крэг Ларман имеет степени бакалавра и магистра компьютерных наук Ванкуверс¬
кого университета имени Симона Фрейзера (Simon Fraser University), Канада.КонтактыС Крэгом Ларманом можно связаться по адресу craig0craiglarman.com, а также
www.craiglarman.com. Автор с удовольствием ответит на вопросы читателей и пре¬
подавателей.Дополнения к предыдущему изданиюХотя в основу этой книги положено ее предыдущее издание, она существенно об¬
новлена и дополнена.■ Используется новейшая система обозначений языка UML 2.0.■ Добавлено описание второго примера.■ Более подробно освещены вопросы итеративной и эволюционной разработки
на основе ООА/П.■ В книге поставлены новые образовательные цели, и материал в книге перепи¬
сан для облегчения его изучения.■ Добавлены новые образовательные ресурсы для преподавателей.■ Описаны гибкий подход к моделированию, разработка на основе тестов и ре¬
факторинг.■ Более подробно рассмотрены вопросы моделирования с помощью диаграмм ви¬
дов деятельности UML.■ Приведены рекомендации по применению унифицированного процесса в кон¬
тексте гибкого моделирования и итеративных методов разработки, таких как
ХР и Scrum.■ Описана система обозначений UML для документирования архитектуры.■ Добавлена новая глава, посвященная эволюционному процессу формулировки
требований.■ Модифицировано описание прецедентов в соответствии с очень популярным
подходом, предложенным в [37].
БлагодарностиВведение 25Прежде всего большое спасибо моим друзьям и коллегам из компании Valtech, ко¬
торые внесли свой вклад в создание и рецензирование этой книги, в том числе Крису
Тарру (Chris Tarr), Мишелю Эзрану (Michel Ezran), Тиму Снайдеру (Tim Snyder),
Куртису Хайту (Curtis Hite), Челсо Гонзалесу (Celso Gonzalez), Паскалю Рокусу (Pascal
Roques), Кену Делонгу (Ken DeLong), Бретту Шухерту (Brett Schuchert), Эшли
Джонсону (Ashley Johnson), Крису Джонсу (Chris Jones), Томасу Лиоу (Thomas Liou),
Дериллу Геберту (Darryl Gebert) и многим другим, кого я не в состоянии перечис¬
лить.Спасибо Филиппу Крачтену (Philippe Kruchten) за написание предисловия, рецен¬
зирование книги и другую помощь.Отдельное спасибо Мартину Фаулеру (Martin Fowler) и Алистеру Кокбурну (Alistair
Cockburn) за плодотворное обсуждение процесса разработки и вопросов проектиро¬
вания, а также за предоставленные материалы и рецензирование книги.Большое спасибо Ойстену Хогену (Oystein Haugen), Крису Кобрину (Cris Kobryn),
Джиму Румбаху (Jim Rumbaugh) и Брену Селику (Bran Selik) за редактирование мате¬
риала по UML 2.Благодарю Джона Влиссидеса (John Vlissides) и Криса Кобрина (Cris Kobryn) за
удачные цитаты.Большое спасибо сотрудникам компании Chelsea Systems и лично Джону Грею
(John Gray) за помощь в формулировке требований к их системе ChelseaStore POS,
разработанной с помощью технологии Java.Благодарю Пита Коада (Pete Coad) и Дейва Астелса (Dave Astels) за их поддержку.Выражаю признательность другим рецензентам, в том числе Стиву Адольфу (Steve
Adolph), Брюсу Андерсону (Bruce Anderson), Лену Бассу (Len Bass), Гари К. Эвансу
(Gary К. Evans), Элу Горнеру (А1 Goerner), Люку Хохманну (Luke Hohmann), Эрику
Лефебвру (Eric Lefebvre), Дэвиду Нанну (David Nunn) и Роберту Дж. Вайту (Robert J.
White).Благодарю Поля Беккера (Paul Becker) из издательства Prentice-Hall за его веру в
успех первого издания, а также Поля Петралиа (Paul Petralia) за сопровождение по¬
следующих.И наконец, отдельное спасибо Грэхем Гласс (Graham Glass) за открытую дверь.Соглашения, принятые в книгеНовые термины выделяются курсивом.Имена классов и методов выделяются следующим образом: Класс, метод.Ссылки на литературные источники заключаются в квадратные скобки, напримерт.
26 ВведениеОт издательстваВы, читатель этой книги, и есть главный ее критик и комментатор. Мы ценим
ваше мнение и хотим знать, что было сделано нами правильно, что можно было сде¬
лать лучше и что еще вы хотели бы увидеть изданным нами. Нам интересно услышать
и любые другие замечания, которые вам хотелось бы высказать в наш адрес.Мы ждем ваших комментариев и надеемся на них. Вы можете прислать нам бумаж¬
ное или электронное письмо, либо просто посетить наш Web-cepeep и оставить свои
замечания там. Одним словом, любым удобным для вас способом дайте нам знать,
нравится или нет вам эта книга, а также выскажите свое мнение о том, как сделать
наши книги более интересными для вас.Посылая письмо или сообщение, не забудьте указать название книги и ее авторов,
а также ваш обратный адрес. Мы внимательно ознакомимся с вашим мнением и обя¬
зательно учтем его при отборе и подготовке к изданию последующих книг.Наши координаты:E-mail: info @williamspublishing. comWWW: http: //www.williamspublishing.comИнформация для писем из:России: 1270559, Москва, ул. Лесная, д. 43, стр. 1Украины: 03150, Киев, а/я 152
ЧастьВведениеВ этой части...Глава 1. Объектно-ориентированный анализ и проектирование
Глава 2. Итеративный, эволюционный и гибкий процесс
Глава 3. Конкретные примеры
Объектно-ориентированный
анализ и проектированиеLe temps est ип grand professeur, mais malhemreusement il tue tous ses eleves.
(Время— великий учитель, no, к сожалению, он убивает всех своих учеников.)Гектор Берлиоз (Hector Berlioz)Основные задачи■ Описать цели и задачи книги.■ Определить понятия объектно-ориентированного анализа и проекти-■ Проиллюстрировать материал на простом примере.■ Кратко описать язык UML и метод быстрого визуального моделиро-1.1. Что вы узнаете из этой книги?Какой смысл вкладывается в понятие “хорошо спроектированная объектно-ориен¬
тированная система”? Эта книга поможет разработчикам и студентам получить прак¬
тические навыки объектно-ориентированного анализа и проектирования (ООА/П).
Такие навыки необходимы для разработки профессиональных, робастных программ¬
ных систем, созданных на основе объектной технологии проектирования и с помо¬
щью объектно-ориентированных языков программирования типа Java или С#.
30 Часть I. ВведениеЧто дальше?ПредисловиеВ этой главе определяются задачи книги и основные понятия ООА/П. Затем
речь идет об итеративной и эволюционной разработке, в процессе которой
применяются принципы ООА/П. Конкретные примеры разрабатываютсяв процессе трех итерации.следующая глава\Введение(учебныересурсы)Введение
в ООА/ПИтеративная,
эволюционная
и быстрая
разработка—о—КонкретныепримерыАнглийская поговорка гласит: “Если у вас есть молоток, это еще не значит, что
вы архитектор”. Это особенно справедливо по отношению к объектной технологии.
Владение объектно-ориентированным языком программирования (например, Java) —
это необходимое, но не достаточное условие для создания объектной системы. Очень
важно также уметь “мыслить объектами”.В этой книге содержится вводная информация о процессе объектно-ориентиро¬
ванного анализа и проектирования с помощью унифицированного языка моделиро¬
вания UML {Unified Modeling Language), шаблонов и быстрого подхода к унифициро¬
ванному процессу проектирования (рис. 1.1). Унифицированный процесс является
примером итеративной разработки. Книга не рассчитана на опытных специалистов.
Основное внимание уделяется основам проектирования, способам распределения
обязанностей между объектами, часто используемой системе обозначений языка
UML и типичным шаблонам проектирования. В то же время, особенно в последних
главах, рассматриваемые темы излагаются более подробно, и речь идет о разработке
каркасов и архитектурном анализе.Язык UML или “объектное” мышление. Однако эта книга не только о языке
UML. UML — это стандарт системы обозначений для построения диаграмм. Нужно
не только освоить эту систему обозначений; гораздо важнее изучить принципы
объектно-ориентированного проектирования, научиться “мыслить объектами”. Язык
UML — это не принцип или метод ООА/П, это всего лишь система обозначений.
Можно в совершенстве освоить синтаксис диаграмм UML и специализированные
CASE-средства, но не научиться при этом разрабатывать новые эффективные про¬
граммы или модифицировать существующие. Получить навыки разработки гораздо
важнее и сложнее. И данная книга посвящена именно этой проблеме.Однако для объектно-ориентированного анализа и проектирования нужен свой
язык, позволяющий формулировать мысли и общаться с другими разработчиками.
Поэтому в данной книге рассказывается о том, как применить язык UML в процессе
ООА/П, и рассматриваются наиболее типичные примеры применения этого языка.Объектно-ориентированное проектирование (ООП): принципы и шаблоны.
Как распределить обязанности между классами и объектами? Как должны взаимодей¬
ствовать объекты? Какие функции выполняют конкретные классы? Эти вопросы яв¬
ляются определяющими при разработке системы. Сам автор книги придерживается
классической концепции объектно-ориентированного проектирования — проектиро¬
вания на основе обязанностей. Некоторые проверенные временем решения проблем,
возникающих в процессе разработки, могут быть (и были) сформулированы в виде
набора принципов, эвристик или шаблонов (patterns) — именованных формул решения
проблем, позволяющих систематизировать процесс разработки конкретных систем.
Глава 1. Объектно-ориентированный анализ и проектирование 31Эта книга позволяет быстро научиться использовать такие фундаментальные идиомы
объектно-ориентированного проектирования.Конкретные примеры. Изложение материала проиллюстрировано на несколь¬
ких конкретных примерах, которые рассматриваются на протяжении всей книги. На
этих примерах достаточно глубоко исследуются вопросы анализа и проектирования.
При этом затронуто множество проблем, неизбежно возникающих при разработке
реальной системы.Прецеденты. Процесс ООП (как и разработка программной системы в целом)
тесно связан с подготовительным этапом анализа требований, который зачастую вклю¬
чает в себя описание прецедентов (use case). Поэтому рассматриваемые в книге при¬
меры начинаются с описания прецедентов, которые в строгом смысле не являются
объектно-ориентированными.Итеративная разработка, быстрое моделирование и быстрый процесс UP. Что
должен делать разработчик или группа разработчиков, чтобы обеспечить реализа¬
цию требований к системе? Результаты анализа требований и ООА/П необходимо
представить и реализовать в контексте некоторого процесса разработки. В данном
случае принимается быстрый (легкий или гибкий) подход к хорошо известному уни¬
фицированному процессу UP (Unified Process), который используется в качестве при¬
мера итеративного процесса разработки. Однако рассматриваемые методики анализа и
проектирования применимы ко многим подходам, поэтому изучение их в контексте
быстрого унифицированного процесса не ограничивает применимости к другим ме¬
тодам, таким как Scrum, разработка на основе свойств (Feature-Driven Development)
и т.д.Рис. 1.1. Рассмотренные вопросы и темы
32 Часть I. ВведениеИ наконец, эта книга поможет студентам или разработчикам:■ применять принципы и шаблоны для создания более совершенных объектных
систем;■ итеративно распределять стандартные виды деятельности в процессе ана¬
лиза и проектирования в контексте быстрого подхода к унифицированному
процессу;■ создавать типичные диаграммы в системе обозначений UML.Все эти приемы проиллюстрированы в контексте конкретных примеров систем,разрабатываемых в течение нескольких итераций.Другие навыкиДанная книга — не исчерпывающее руководство по созданию программных систем.
Это всего лишь введение в вопросы анализа требований, ООА/П, объектно-ориенти¬
рованного программирования, UML и итеративной разработки. Остальные вопросы
затрагиваются лишь поверхностно. Однако для построения программных систем не¬
обходимо задействовать многие другие навыки и виды деятельности. Например, на
успех проекта в значительной степени влияют разработка пользовательского интер¬
фейса или базы данных, а также тестирование системы.1.2. Основная цель обученияНа этапе анализа и проектирования могут использоваться различные виды дея¬
тельности и артефакты, а также принципы и рекомендации. Как же выделить среди
всех рассмотренных здесь вопросов единственный, самый важный с практической
точки зрения?Наиболее важным моментом объектно-ориентированной разработки является ква¬
лифицированное распределение обязанностей между программными объектами.На каком основании это можно утверждать? Дело в том, что это единственный
вид деятельности, без которого невозможно обойтись, — то ли на этапе построения
диаграмм UML, то ли на этапе программирования. Он оказывает определяющее вли¬
яние на робастность, масштабируемость, расширяемость и возможность повторного
использования компонентов.Конечно же, в процессе^ЬОА/П решаются и другие важные вопросы, однако рас¬
пределению обязанностей (responsibility assignment) уделяется особое внимание, посколь¬
ку это самая сложная и жизненно важная задача (со многими степенями свободы или
альтернативами). В реальном проекте разработчик может не иметь возможности вы¬
полнения любых других видов деятельности анализа или проектирования — зачастую
участники проектов стараются немедленно приступить к написанию кода. Но даже в
этой ситуации приходится распределять обязанности.
Глава 1. Объектно-ориентированный анализ и проектирование 33Поэтому при описании этапа проектирования основное внимание уделяется рас¬
пределению обязанностей.Для овладения навыками распределения обязанностей предлагается девять фун¬
даментальных принципов, систематизированных в виде шаблонов GRASP.1.3. Что такое анализ и проектированиеЭтап анализа (analysis) состоит в исследовании системных требований и пробле¬
мы, а не в поисках путей ее решения. Например, при разработке новой информаци¬
онной системы для автоматизации торговли необходимо описать способы ее исполь¬
зования и основные функции.Анализ — это достаточно широкое понятие. Его содержание более точно отража¬
ют термины анализ требований (requirements analysis) (т.е. исследование требований
к системе) и объектно-ориентированный анализ (object-oriented analysis) (исследование
объектов предметной области).В процессе проектирования (design) основное внимание уделяется концептуальному
решению (в виде программного обеспечения или аппаратных средств), обеспечиваю¬
щему выполнение основных требований, но не вопросам его реализации. Например,
на этапе проектирования описываются программные объекты или схема базы дан¬
ных. Идеи проектирования зачастую исключают низкоуровневые или “очевидные”
детали — очевидные с точки зрения потенциального пользователя. Конечно же, про¬
ектные решения могут быть реализованы в программном коде, и эта реализация
должна быть точной и полной.Как и понятие анализа, этот термин тоже стоит уточнить и говорить об объектно-
ориентированном проектировании (object-oriented design) или проектировании базы дан¬
ных (database design).Подытоживая вышесказанное, ООА/П можно определить как “выполнение пра¬
вильных действий (анализ) и обеспечение их правильности (проектирование)”.1.4. Объектно-ориентированный
анализ и проектированиеВ процессе объектно-ориентированного анализа основное внимание уделяется опре¬
делению и описанию объектов (или понятий) в терминах предметной области.
Например, в случае информационной системы аэропорта среди понятий должны
присутствовать Plane (самолет), Flight (рейс) и Pilot (пилот).В процессе объектно-ориентированного проектирования (или просто объектного про¬
ектирования) определяются программные объекты и способы их взаимодействия
с целью выполнения системных требований. Например, в системе аэропорта про¬
граммный объект Plane может содержать атрибут tailNumber (бортовой номер) и
метод getFlightHistory (получить историю полетов) (рис. 1.2).2 Зак. 3357
34 Часть I. ВведениеПредставление
средствами объектно-
ориентированного языка
программированияPlanetailNumberВизуализация ^
понятия
предметной
областиIpublic class Plane
{private String tailNumber;
public List getFlightHistory(){...}
}Рис. 1.2. Представление объектов с использованием объектно-ориентированного подходаИ наконец, на этапе реализации (implementation) или объектно-ориентированного про¬
граммирования (object-oriented programming) обеспечивается реализация разработан¬
ных компонентов, таких как класс Plane, на языке Java.1.5. Краткий примерПрежде чем вдаваться в детали итеративной разработки, анализа требований,
UML и ООА/П, рассмотрим “с высоты птичьего полета” основные действия, вы¬
полняемые в процессе разработки программной системы, и создаваемые при этом
диаграммы. В качестве примера возьмем игру в кости, в которой игрок бросает два
кубика. Если сумма очков равна семи, участник считается победителем, в противном
случае — проигравшим.Определение прецедентовАнализ требований может включать описание процессов или сценариев использо¬
вания приложения, которое может быть представлено в форме прецедентов.ОпределитьСоздать модель I Построить 1 Создатьпредметной 1 диаграммы 1 диаграммы классовпрецеденты j области ! взаимодействия 1 проектированияПрецеденты не являются артефактами объектно-ориентированного анализа — это
просто повествовательные истории. Однако они являются популярным средством
анализа требований. Например, приведем краткую версию прецедента Игра в кости
(Play a Dice Game).Игра в кости. Игрок отправляет запрос на выбрасывание костей. Система
представляет результаты: если сумма очков составляет 7, игрок считается по¬
бедителем, в противном случае — проигравшим.
Глава 1. Объектно-ориентированный анализ и проектирование 35Определение модели предметной областиОпределитьпрецедентыжСоздать модель"^
предметной
областиПостроитьдиаграммывзаимодействияСоздать
диаграммы классов
проектированияОбъектно-ориентированный анализ связан с описанием предметной области с
точки зрения классификации объектов. Декомпозиция предметной области задачи
состоит в идентификации понятий, атрибутов и ассоциаций из предметной области,
имеющих важное значение для решения задачи.Результат анализа выражается в модели предметной области (domain model), кото¬
рая иллюстрируется с помощью набора диаграмм с изображенными на них понятия¬
ми или объектами предметной области.Например, фрагмент модели предметной области игры в кости показан на
рис. 1.3.Рис. 1.3. Фрагмент модели предметной области игры в костиЭта модель иллюстрирует понятия Player (игрок), Die (кость) и DiceGame (игра
в кости), а также их связи и атрибуты.Модель предметной области — это не описание программных объектов. Это пред¬
ставление понятий, выраженных в терминах реального мира. Эту модель также на¬
зывают концептуальной объектной моделью (conceptual object model).Распределение обязанностей между объектами
и диаграммы взаимодействийПостроить
диаграммы I
взаимодействия |Определить 1
прецеденты jСоздать модель 1
предметной 1
области JСоздать 1
диаграммы классов 1
проектирования j
36 Часть I. ВведениеОбъектно-ориентированное проектирование связано с определением програм¬
мных объектов, их обязанностей и способов взаимодействия. Для иллюстрации вза¬
имосвязей между объектами используется диаграмма последовательностей (sequence
diagram), которая представляет собой один из видов диаграммы взаимодействия UML
(interaction diagram). Она отражает потоки сообщений между программными объек¬
тами и вызовы методов.Например, на рис. 1.4 показана диаграмма последовательностей, иллюстрирую¬
щая объектно-ориентированное программное решение для игры в кости. Эта диа¬
грамма иллюстрирует передачу сообщений между экземплярами классов DiceGame и
Die. Заметим, что диаграммы UML зачастую изображают фломастером на доске, а не
только строят с помощью специализированного программного обеспечения.Рис. 1.4. Диаграмма последовательностей, иллюстрирующая передачу сообщений междупрограммными объектамиОбратите внимание на следующую особенность. Хотя в реальном мире кости под¬
брасывает игрок, в программной системе эту функцию выполняет объект DiceGame
(т.е. передает сообщения объектам Die). Дело в том, что программные объекты в не¬
котором смысле соответствуют объектам реального мира, но не являются их точны¬
ми моделями или копиями.Разработка диаграмм классов проектированияОпределитьпрецедентыСоздать модель
предметной
областиПостроитьдиаграммывзаимодействияСоздать М
диаграммы классов
проектирования
Глава 1. Объектно-ориентированный анализ и проектирование 37Помимо динамического представления (dynamic view) взаимосвязи объектов, отобра¬
жаемой на диаграмме взаимодействий, очень полезно строить статическое представ¬
ление (static view) системы в виде диаграммы классов проектирования (design class dia¬
gram). На такой диаграмме отображаются атрибуты и методы классов.Например, анализ диаграммы взаимодействия игры в кости приводит к фрагменту
диаграммы классов, показанному на рис. 1.5. Поскольку сообщение play передается
объекту DiceGame, класс DiceGame должен содержать метод play, а класс Die — мето¬
ды roll и getFaceValue.В отличие от модели предметной области, отражающей понятия реального мира,
эта диаграмма описывает программные классы.DiceGame1 2 >Diediel : Die
die2 : DiefaceValue : intgetFaceValue() : int
roll()play()Рис. 1.5. Фрагмент диаграммы классов проектированияХотя полученная диаграмма классов проектирования не до конца соответствует
модели предметной области, некоторые имена классов и их характеристики совпада¬
ют. В этом смысле объектно-ориентированные проектные решения и языки позволя¬
ют уменьшить разрыв между представлением информации в виде программных ком¬
понентов и ментальными моделями предметной области. Это улучшает образность
представления.Еще несколько слов об игре в костиПрограммное моделирование игры в кости — очень простая задача, позволяющая
сконцентрировать внимание на некоторых шагах и артефактах объектно-ориентиро¬
ванного анализа и проектирования. Для простоты изложения в тексте главы были
прокомментированы не все используемые на диаграммах обозначения. Эти артефак¬
ты будут более подробно рассмотрены в последующих главах, посвященных вопросам
анализа и проектирования.1.6. Что такое UML“Унифицированный язык моделирования UML — это визуальный язык для
определения, конструирования и документирования артефактов систем” [99].Слово “визуальный” в приведенном определении является ключевым. UML — это
важный фактический стандарт для системы обозначений элементов диаграмм или
представления изображений (с элементами текста), связанных с программным обе¬
спечением, преимущественно объектно-ориентированным.В данной книге не приводится исчерпывающее описание UML, поскольку его си¬
стема обозначений является весьма объемной. Здесь внимание сконцентрировано на
чаще всего используемых диаграммах и их элементах, а также на основных обозначе¬
ниях, которые вряд ли изменятся в следующих версиях UML.
38 Часть I. ВведениеВ UML определены различные профили (profile), задающие подмножества систе¬
мы обозначений для некоторых стандартных предметных областей, таких как диа¬
граммы компонентов Enterprise JavaBeans (профиль UML EJB).Следующим уровнем, представляющим интерес преимущественно для разработчи¬
ков CASE-средств, является положенная в основу системы обозначений UML метамо¬
дель UML (meta-model UML). Она описывает семантику моделируемых элементов, и
ее не обязательно изучать разработчикам.Три способа использования UMLВ [55] описаны три способа применения языка UML.■ Для черновиков — неполные и неформальные диаграммы (зачастую нарисован¬
ные от руки на доске), создаваемые для прояснения сложных проектных реше¬
ний. Здесь используется мощь визуального представления.■ Для создания проектной документации — относительно детализированные
диаграммы проектирования, применяемые для визуализации и лучшего пони¬
мания существующего кода, обратного проектирования или генерации кода.• В процессе обратного проектирования UML-средство читает исходный код
или выполняемые файлы и генерирует диаграммы классов, последовательно¬
стей и пакетов на языке UML. Эти “чертежи” позволят читателю лучше по¬
нять общую структуру системы и принципы взаимодействия ее элементов.• До начала процесса программирования некоторые детальные диаграммы
дают возможность сгенерировать код автоматически (например, на языке
Java). Обычно диаграммы используются для генерирования некоторой части
кода, а остальной код добавляется разработчиком вручную.■ В качестве языка программирования — полные выполняемые спецификации
программных систем на языке UML. Выполняемый код можно автоматически
сгенерировать. Однако разработчику его сложно осознать или модифициро¬
вать — человек работает только с “языком программирования UML”. Такой
способ использования UML требует отображения всей логики системы или ее
поведения (возможно, с использованием диаграмм взаимодействия или состоя¬
ний). Он также придает разработке робастность и надежность.Быстрый подход к моделированию (agile modeling) предполагает использование UML
для построения черновиков. Это самый типичный способ применения UML, кото¬
рый зачастую позволяет значительно сэкономить время разработки. UML-средства
могут быть полезными при разработке, но автор агитирует своих читателей приме¬
нять быстрый или гибкий подход к моделированию на основе языка UML.Три аспекта использования UMLЯзык UML описывает типы диаграмм, например диаграммы классов или после¬
довательностей. Он не привязан ни к какому методу или ракурсу моделирования.
Например, одни и те же обозначения для диаграммы классов языка UML можно ис¬
пользовать для представления концептуальных классов или понятий (в модели пред¬
метной области) либо программных классов на языке Java.
Глава 1. Объектно-ориентированный анализ и проектирование 39UML и “серебряная пуля”В 1986 году вышла широко известная статья доктора Фредерика Брукса
(Frederick Brooks) под названием Серебряной пули не существует. Она также была
опубликована в его классической книге Мифический человеко-месяц (издание, посвя¬
щенное двадцатой годовщине первого выхода книги в свет). Настойчиво реко¬
мендую ее прочесть! Основная мысль этой статьи сводится к развенчанию фун¬
даментального заблуждения (многократно повторяемого) в том, что существует
некоторое средство или прием программирования, который позволит существен¬
но повысить производительность, надежность или простоту процесса разработ¬
ки. Однако никакие средства не заменят процесс проектирования.Наверняка вам приходилось слышать (обычно от разработчиков CASE-
средств), что построение диаграмм UML улучшает проектные решения или что
разработка архитектуры на основе модели (Model Driven Architecture — MDA) с
помощью средств, основанных на UML, станет “серебряной пулей* решения про-Время покажет. На сегодня UML — это просто стандартный набор обозна¬
чений для диаграмм (набор линий, прямоугольников и т.д.)* Визуальное моде¬
лирование с помощью единой системы обозначений — само по себе достойная
цель. Однако вряд ли его важность можно сравнить с важностью знания прин¬
ципов проектирования и получением навыков мышления в терминах объектов.
Знание подходов к проектированию — это совершенно отличная и более важная
область, которую нельзя освоить в процессе изучения языка UML или исполь¬
зования CASE- или MDA-средств. Человек, не владеющий подходами к объектно-
ориентированному проектированию, не имеющий навыков программирования,
с помощью UML просто “нарисует” плохой проект. Более детально этот вопрос
обсуждается в статьях [13, 85].Таким образом, данная книга — это введение в объектно-ориентированный
анализ и проектирование, а также применение UML для профессионального
объектно-ориентированного проектирования.Такой подход декларируется в рамках одного из объектно-ориентированных мето¬
дов [29]. То есть, одни и те же обозначения элементов диаграмм можно применять
для построения трех ракурсов и аспектов моделей (рис. 1.6).1. Концептуальный аспект (conceptual perspective) — диаграммы описывают сущ¬
ности реального мира или предметной области.2. Аспект (программной) спецификации (specification perspective) — диаграммы
(с использованием обозначений, принятых в рамках концептуального аспекта)
описывают программные абстракции или компоненты со своими специфика¬
циями и интерфейсами, однако без привязки к конкретной реализации (напри¬
мер, без конкретного соответствия языку C# или Java).3. Аспект (программной) реализации (implementation perspective) — диаграммы
интерпретируются как описания программной реализации на базе конкретной
технологии или языка (например, Java).
40 Часть I. ВведениеКонцептуальный аспект
(модель предметной области)Обозначения для диаграмм
классов UML используются
для представления понятий
из реального мираАспект спецификацииDiceGameDieили реализации
(диаграммы классов
проектирования)diel : Die2 >faceValue : intdie2 : DiegetFaceValue() : int
roll()Обозначения для диаграммplay()классов используются
для представленияпрограммных элементовРис. 1.6. Различные ракурсы использования UMLПодобным примером служат рис. 1.3 и рис. 1.5, на которых одни и те же обозна¬
чения диаграммы классов UML используются для визуализации моделей предметной
области и проектирования.На практике аспект спецификации (без указания конкретной технологии, такой,
как Java или .NET) редко используется для проектирования. Чаще всего диаграммы
UML применяются в аспекте реализации.Значение термина “класс” в различных аспектахНа языке UML прямоугольники, показанные на рис. 1.6, обозначают классы.
Однако этот термин может означать различные феномены: физические понятия, аб¬
страктные концепции, программные компоненты, события и т.д.1В рамках конкретного процесса или метода используется альтернативная терми¬
нология. Например, в контексте UP прямоугольные обозначения UML, представлен¬
ные в модели предметной области, называются понятиями предметной области, или
концептуальными классами, поскольку модель предметной области обеспечивает кон¬
цептуальный ракурс рассмотрения. Если эти же обозначения UML использованы в
модели проектирования, то в контексте UP они официально называются классами
проектирования, поскольку модели проектирования соответствует ракурс специфика¬
ции или реализации.Для простоты в данной книге будут использоваться термины, связанные с унифи¬
цированным процессом разработки с применением UML.■ Концептуальный класс— понятие из реального мира. Рассматривается в концеп¬
туальном ракурсе. В рамках UP модель предметной области содержит концепту¬
альные классы.■ Программный класс — класс, представляющий спецификацию или реализацию
программного компонента, независимо от процесса или метода.■ Класс реализации — класс, реализованный на конкретном объектно-ориентиро-
ванном языке, например на Java.1 В контексте UML, класс — это специальный вид достаточно общего элемента модели, по¬
лучившего название классификатора (classifier). Классификатор — это сущность со структурными
свойствами и/или поведением, в частности, класс, исполнитель, интерфейс и прецедент.DiceGame1 Включает 2DiefaceValue : int
Глава 1. Объектно-ориентированный анализ и проектирование 41UML1HUML2По состоянию на конец 2004 года самой новой версией языка UML была версия 2.
Данная книга основывается на UML 2, используемые в ней обозначения были внима¬
тельно проверены основными разработчиками этого стандарта.Почему в нескольких следующих главах речь не идет об UMLЭта книга посвящена не просто системе обозначений языка UML, а гораздо более
широкой проблеме применения UML, шаблонов и итеративного процесса в контек¬
сте ООА/П и анализа требований. Этапу ООА/П обычно предшествует этап анализа
требований. Поэтому в первых главах рассматриваются важные вопросы описания
прецедентов и анализа требований, а уже в последующих — подробности процесса
ООА/П и специфика применения языка UML.1.7. Визуальное моделирование — хороший стильОчевидно, что использование UML делает процесс проектирования более нагляд¬
ным. При этом учитывается свойство человеческого мозга быстро схватывать графи¬
ческие символы и взаимосвязи, представленные в виде двумерных диаграмм, состоя¬
щих из прямоугольников и линий.Эта старая и простая идея зачастую теряется среди всевозможных деталей и
средств UML. Так быть не должно! Диаграммы помогают нам лучше увидеть общую
картину и понять взаимосвязи между элементами этапа анализа и программирова¬
ния, а также избавиться от ненужных деталей. В этом состоит основная роль UML
или любого языка построения диаграмм.1.8. ИсторияИстория ООА/П насчитывает множество важных моментов, и это краткое опи¬
сание не может охватить всех специалистов, кто внес свой вклад в развитие этой об¬
ласти. 1960-е и 1970-е годы ознаменовались появлением объектно-ориентированных
языков программирования, таких как Simula и Smalltalk. Основной вклад в развитие
этих языков внесли Кристен Нигард (Kristen Nygaard) и Алан Кей (Alan Kay) — раз¬
работчик языка Smalltalk. Алан Кей ввел термины “объектно-ориентированное про¬
граммирование” и “персональный компьютер”, а также помог воплотить идеи совре¬
менных персональных компьютеров в компании Xerox PARC2.2 Алан Кей (Alan Kay) начал работать в области объектно-ориентированного программиро¬
вания и разработки персональных компьютеров еще в 1960-е годы, будучи студентом выпускных
курсов. В декабре 1979 года по совету знаменитого сотрудника компании Apple Джефа Раскина
(Jef Raskin) (главного разработчика компьютеров Мае) совладелец компании Apple Стив Джобс
(Steve Jobs) посетил Алана Кея и других исследователей (включая Дена Ингалса (Dan Ingalls),
который реализовал видение Кея) в Xerox PARC, где ему был продемонстрирован персональ¬
ный компьютер, предназначенный для использования языка Smalltalk. Увиденные там графиче¬
ский интерфейс пользователя, перекрывающиеся окна, объектно-ориентированное программи¬
рование и объединенные в сеть персональные компьютеры перевернули мировоззрение Стива
Джобса, и он вернулся в компанию Apple с новым видением, на что и надеялся Раскин. В ре¬
зультате в компании Apple родились компьютеры Lisa и Macintosh.
42 Часть I. ВведениеОднако в этот период процесс ООА/П был еще не формализован и оставался
таким вплоть до 1982 года, когда впервые внимание исследователей сосредоточи¬
лось на самом процессе разработки. Эта веха связана с именем Гради Буча (Grady
Booch) (также одним из создателей языка UML), который написал свою первую ста¬
тью [20], где впервые ввел термин “объектно-ориентированное проектирование”.
В 1980-е годы свои идеи развивали и многие другие пионеры ООА/П: Кент Бек (Kent
Beck), Питер Коад (Peter Coad), Дон Файесмит (Don Firesmith), Айвар Якобсон (Ivar
Jacobson) (один из создателей языка UML), Стив Меллор (Steve Mellor), Бертран
Мейер (Bertrand Meyer), Джим Румбах (Jim Rumbaugh) (один из создателей языка
UML), Ребекка Вирфс-Брок (Rebecca Wirfs-Brock) и многие другие. Бертран Мейер
опубликовал одну из известных ранних книг, посвященных объектно-ориентиро¬
ванному проектированию программного обеспечения в 1988 году. В этом же году
Меллор (Mellor) и Шлеер (Schlaer) ввели новый термин “объектно-ориентированный
анализ” в своей книге Object-Oriented Systems Analysis. В конце 1980-х Питер Коад раз¬
работал полноценный метод ООА/П и опубликовал его в двухтомнике Object-Oriented
Analysis и Object-Oriented Design, который увидел свет в 1990-1991 годах. Также в 1990
году Ребекка Вирфс-Брок совместно с другими авторами описала подход к объектно-
ориентированному проектированию на основе обязанностей в популярной книге
Designing Object-Oriented Software. В 1991 году были опубликованы еще две очень популяр¬
ные книги ООА/П. Автором первой является Джим Румбах и другие; она посвящена
методу ОМТ. Во второй книге описывается метод Буча. Она называется Object-Oriented
Design with Applications. В 1992 году Айвар Якобсон опубликовал известную книгу Object-
Oriented Software Engineering, в которой речь шла не только об ООА/П, но и о написа¬
нии прецедентов в контексте анализа требований.Язык UML появился в 1994 году в результате совместных усилий Гради Буча
(Grady Booch) и Джима Румбаха (Jim Rumbaugh) по объединению их популярных ме¬
тодов — метода Буча и ОМТ (Object Modeling Technique) — в рамках единой системы
обозначений. Первая публикация, посвященная вопросам, которые сегодня относят¬
ся к UML, называлась Unified Method. Затем к ним присоединился сотрудник компа¬
нии Rational Corporation Айваром Якобсоном (Ivar Jacobson), создатель метода OOSE
(Object-Oriented Software Engineering). Впоследствии эту группу разработчиков назва¬
ли “три товарища”. Объединив усилия, авторы решили сфокусироваться на создании
общей системы обозначений для построения диаграмм — UML, а не на разработке
единого метода проектирования. Это было не просто прихотью, а насущной необ¬
ходимостью, поскольку многие разработчики программных средств и группа OMG
(Object Management Group), занимающаяся разработкой промышленных стандартов
в области объектно-ориентированного подхода, отмечали необходимость создания
открытого стандарта моделирования. Таким образом, процесс пошел, и в 1997 году
был принят первый стандарт UML 1. В разработку UML внесли свой вклад и другие
специалисты, среди которых наиболее заметным является, пожалуй, Крис Кобрин
(Cris Kobryn), руководитель процесса его текущей модификации.Язык UML в настоящее время является юридическим и фактическим стандартом
системы обозначений для построения диаграмм в рамках объектно-ориентирован¬
ного моделирования и продолжает развиваться в своих новых версиях. Самая све¬
жая и подробная информация об этом языке содержится по адресам www.omg.org и
www.uml.org.
Глава 1. Объектно-ориентированный анализ и проектирование 431.9. Дополнительные ресурсыВ последующих главах читателю будут рекомендованы многие публикации по
ООА/П, касающиеся конкретных аспектов этого подхода, в частности объектно-ори¬
ентированного проектирования. Базовыми по этому направлению являются книги,
упомянутые в предыдущем разделе.Базовая система обозначений очень популярно и доступно изложена в книге
Мартина Фаулера (Martin Fowler) [55]. Автор настоятельно рекомендует изучить эту
книгу, а также множество других книг Фаулера, посвященных практическим аспектам
и быстрому проектированию.Подробное описание системы обозначений языка UML приводится в книге
Румбаха [107]. Заметим, что эта книга предназначена не для изучения вопросов
объектного моделирования или ООА/П, а лишь для ознакомления с системой обо¬
значения элементов диаграмм UML.Описание текущей версии языка UML и его интерактивные спецификации можно
найти по адресам www.omg.org и www.uml.org.Вопросы визуального моделирования с помощью UML в духе быстрой и гибкой
разработки описаны в книге Скотта Амблера (Scott Ambler) [6], а также по адресу
www.agilemodeling.com.Большое количество ссылок на методы ООА/П содержится по адресам www.
cetus-links.org и www.iturls.com.Шаблонам проектирования посвящено множество книг, однако классическим
учебником считается книга Гамма (Gamma), Хелма (Helm), Джонсона (Johnson) и
Влиссидеса (Vlissides) [58]. Эта книга действительно необходима всем, кто планиру¬
ет изучать объектное проектирование. Однако она рассчитана не на новичков, а на
специалистов, уже знакомых с основами объектного проектирования и программи¬
рования. Ссылки на множество Web-узлов, связанных с шаблонами проектирования,
можно найти также по адресам www.hillside.net и www.iturls.com.
2Итеративный, эволюционный
и гибкий процессИспользуйте итеративную разработку только в тех проектах, которые должныбыть успешно завершены.Мартин Фаулер (Martin Fowler)ВведениеИтеративная разработка — это основа подхода к созданию программных систем,
положенного в основу описания объектно-ориентированного анализа и проектирова¬
ния в данной книге. Такие адаптивные приемы, как быстрое моделирование, позволя¬
ют применять язык моделирования UML наиболее эффективно. Унифицированный
процесс — это пример одного из самых популярных итеративных методов разработки
на базе ООА/П. В данной главе рассматривается именно этот процесс, а также осно¬
вы быстрого моделирования с использованием языка UML.
46 Часть I. ВведениеЧто дальше? После ознакомления с основными понятиями ООА/П в данной главе речь
идет об итеративной разработке. В следующей главе рассматриваются
конкретные примеры, которые будут эволюционировать на протяжении
трех итераций./ \Итеративная,Введение эволюционная Конкретные нв ООА/П и быстрая примеры ачалоразработка—о • о оИтеративная и эволюционная разработка существенно отличается от последователь¬
ного, или каскадного (waterfall), жизненного цикла и предполагает раннее программи¬
рование и тестирование частей системы в многократно повторяемых циклах работы
над проектом. При использовании такого подхода разработка обычно начинается
еще до детального определения всех требований. При этом для прояснения и улуч¬
шения спецификации активно применяется обратная связь с заинтересованными ли¬
цами.Таким образом, в процессе итеративной разработки прояснение требований и
проектных решений во многом обеспечивается обратной связью. В отличие от этого
при использовании каскадного процесса до программирования существенные усилия
затрачиваются на предварительное определение теоретических требований и выра¬
ботку потенциальных проектных решений. Анализ успешных/неудачных проектов
свидетельствует о том, что неудачные проекты, которые выполнялись в рамках ка¬
скадного процесса разработки, составляют большую часть всех неудачно завершив¬
шихся проектов. Проведенные исследования позволяют сделать вывод о том, что
итеративные методы повышают вероятность успешного завершения проектов и их
эффективность, а также позволяют добиться получения более качественного про¬
граммного обеспечения.2.1. Унифицированный процесс и другие методыПо существу, процесс разработки программного обеспечения (software development
process) включает построение, развертывание и, возможно, поддержку системы.
Унифицированный процесс UP (Unified Process) [74] — это широко используемый итера¬
тивный процесс разработки объектно-ориентированных систем. В частности, широ¬
кую популярность приобрел унифицированный процесс RUP (Rational Unified Process)
[81], обеспечивающий более детальную проработку всех этапов, определенных в про¬
цессе UP.Унифицированный процесс является достаточно популярным подходом к объект-
но-ориентированному анализу и проектированию. Поскольку изучение ООА/П сле¬
дует проводить в контексте некоторого процесса разработки, в качестве такого про¬
цесса в этой книге выбран именно процесс UP. Кроме того, поскольку этот процесс
является достаточно общим подходом, в рамках которого собраны наиболее извест¬
ные удачные методы анализа и проектирования, с ним полезно познакомиться как
разработчикам-профессионалам, так и студентам.
Глава 2. Итеративный, эволюционный и гибкий процесс 47Процесс UP является чрезвычайно гибким и открытым. Он позволяет использо¬
вать различные приемы и из других итеративных методов, таких как экстремальное
программирование (Extreme Programming — ХР), Scrum и т.д. Например, разработку на
основе тестирования (test-driven development), рефакторинг (refactoring) и непрерывную
интеграцию (continuous integration) метода ХР можно использовать и в рамках про¬
екта на основе процесса UP. Более подробно разработка на основе тестирования и
рефакторинг будут рассматриваться в главе 21. Так что в рамках UP можно без осо¬
бых проблем воспользоваться приемами проведения семинаров и ежедневных обсуж¬
дений, определенных в процессе Scrum.Выбор процесса UP в качестве основы для изложения материала вовсе не означа¬
ет преуменьшение значимости всех других методов. Дело обстоит совсем иначе. При
выполнении консультационных работ автор книги всегда поддерживал желание сво¬
их заказчиков проанализировать и адаптировать все полезные приемы из различных
методов разработки. Не стоит придерживаться догмы: “мой метод лучше, чем ваш”.В унифицированном процессе нашел отражение и получил детальное описание
наиболее удачный опыт разработки систем, в частности итеративный жизненный
цикл и оценка рисков.Таким образом, в данной главе содержится описание унифицированного процесса
по трем причинам.1. UP — это итеративный процесс. Принципы ООА/П описываются в этой книге в
контексте итеративной разработки, которая зарекомендовала себя наилучшим
образом при создании множества систем.2. В рамках унифицированного процесса очень удобно описывать принципы
ООА/П. Описание планомерного использования этих принципов в контексте
процесса UP и предоставляет эта книга.3. Процесс UP является очень гибким и может использоваться в рамках легко на¬
страиваемого подхода, который объединял бы полезные приемы из других ме¬
тодов разработки (таких, как ХР или Scrum). Более подробно этот вопрос будет
рассматриваться ниже.В данной главе приводятся лишь начальные сведения о гибком процессе UP, а не
его полное описание. Основное внимание уделяется общим идеям и артефактам,
связанным с анализом требований и ООА/П.Если меня не интересует унифицированный процессУнифицированный процесс рассматривается в качестве примера, в рамках которо¬
го проводится итеративный и эволюционный анализ требований и ООА/П. Анализ
и проектирование всегда выполняются в контексте некоторого процесса. В данном
случае в качестве такого процесса рассматривается UP.Однако основной идеей этой книги является рассмотрение следующих вопросов.■ Как “мыслить” объектами и проектировать их.■ Как использовать язык UML, шаблоны проектирования, гибкое моделирование
и эволюционный анализ требований.■ Как формулировать описание прецедентов и т.д.
48 Часть I. ВведениеВсе вышеперечисленные аспекты являются независимыми от какого бы то ни
было процесса и могут применяться во многих современных итеративных, эволюци¬
онных и гибких методах, таких как Scrum, Lean Development, DSDM, Feature-Driven
Development, Adaptive Software Development и т.д.2.2. Что такое итеративная
и эволюционная разработкаВ основу унифицированного процесса и многих других современных методов по¬
ложена важная идея — это итеративная разработка (iterative development). В рамках
этого подхода разработка выполняется в виде нескольких краткосрочных мини-про¬
ектов фиксированной длительности (например, по три недели), называемых итера¬
циями (iteration). Каждая итерация включает свои собственные этапы анализа тре¬
бований, проектирования, реализации и завершается тестированием, интеграцией и
созданием работающей части системы.Итеративный жизненный цикл основывается на постоянном расширении и до¬
полнении системы в процессе нескольких итераций с периодической обратной свя¬
зью и адаптацией добавляемых модулей к существующему ядру. Система постепенно
разрастается шаг за шагом, поэтому такой подход иногда называют итеративной и ин¬
крементальной разработкой (iterative and incremental development) (рис. 2.1). Поскольку
обратная связь и адаптация приводят к развитию полученных ранее спецификаций и
проектных решений, этот подход иногда называют также итеративной и эволюционной
разработкой (iterative and evolutionary development).Первые идеи итеративного процесса назывались “проектированием по спирали и
эволюционной разработкой” [18, 59].ТребованияПроектированиеРеализация &
Тестирование &
Интеграция &
Дальнейшее
проектированиеТребованияВремяV.у3 недели (например)j5ПроектированиеРеализация &
Тестирование &
Интеграция &
Дальнейшее
проектированиеОкончательнаяОкончательнаяинтеграция &интеграция &СистемноеСистемноетестирование тестированиеОбратная связь ■
от итерации N
приводит
к необходимости
уточнения и адаптации
требований
и проектного решения
на итерации N+1о о Итерации ^СистемафиксированнойразвиваетсядлительностиинкрементальноРис. 2.1. Итеративная и эволюционная разработка
Глава 2. Итеративный, эволюционный и гибкий процесс 49ПримерВ качестве примера (но не рецепта на все случаи жизни) рассмотрим трехнедель¬
ную итерацию процесса разработки. В понедельник примерно один час уйдет на
распределение и осмысление задач и требований этой итерации. Один из участ¬
ников проекта в этот день может выполнить обратное проектирование и отобра¬
зить код, полученный на предыдущей итерации, в диаграммах UML (с помощью
CASE-средств), а также распечатать основные диаграммы. Оставшаяся часть дня
может быть посвящена проектированию у доски и попарному выполнению биз-
нес-моделирования. Полученные диаграммы можно снять на цифровой фотоап¬
парат и ввести в компьютер. В этот же день пишется необходимый псевдокод и
замечания по проектированию. Остальные дни итерации отводятся на реализа¬
цию, тестирование (модулей, применимости, удобства и т.д.), дальнейшее проек¬
тирование, интеграцию, системное тестирование и завершение разработки части
системы. К другим видам деятельности относится демонстрация результатов ру¬
ководителям проекта и заинтересованным лицам, обсуждение с ними этих резуль¬
татов, а также планирование последующей итерации.Обратите внимание, что при таком подходе исключено и слишком быстрое на¬
писание кода (без детальной проработки) и чрезмерно длительный этап детально¬
го проектирования и построения диаграмм без обратной связи. Проектирование и
визуальное моделирование с помощью UML осуществляется в течение одного дня,
причем для выполнения этого вида деятельности разработчики обычно разбиваются
на пары.В результате каждой итерации получается работающая, но не полнофункциональ¬
ная система, которую еще нельзя “выставлять на продажу”. Система может приобре¬
сти товарный вид только после 10 или 15 итераций.Результатом каждой итерации является не экспериментальный прототип, и итера¬
тивная разработка не сводится к прототипированию. Скорее, результатом итерации
является окончательная версия некоторой части всей системы.Управление изменениями в процессе
итеративной разработкиПодзаголовком одной книги, посвященной итеративной разработке, является
фраза “Допускайте изменения” [12]. Эта фраза может служить девизом итеративного
процесса разработки. Вместо того чтобы бороться за создание окончательного и не¬
изменного варианта модели (как правило, безуспешно) и пытаться корректно сфор¬
мулировать, зафиксировать, подписать и “заморозить” набор требований и модель до
начала ее программной реализации (как в каскадном процессе), гораздо лучше осо¬
знать важность (и неизбежность) постоянной модификации и адаптации модели в
процессе разработки системы и смириться с необходимостью регулярного внесения
изменений. Именно такую возможность и предоставляет итеративный и эволюцион¬
ный процесс разработки.Это не означает, что итеративная разработка и унифицированный процесс разви¬
ваются спонтанно и бесконтрольно. В последующих главах будет рассказано о том, как
обеспечить баланс между стабильностью набора требований, с одной стороны, и его
50 Часть I. Введениереальной модификацией в процессе все более глубокого осознания задач и специфи¬
ки проекта его руководителями (или изменением рыночной ситуации), — с другой.На каждой итерации разработки рассматривается небольшое подмножество тре¬
бований, для удовлетворения которых быстро разрабатывается, реализуется и те¬
стируется небольшая часть системы. На начальных итерациях требования и модель
проекта могут быть очень далеки от идеала. Однако достаточно сжатые временные
рамки каждой итерации, на которой выполняется весь процесс проектирования и ре¬
ализации, обеспечивают быструю и своевременную обратную связь и общение между
пользователями, разработчиками и специалистами по тестированию.Ранняя обратная связь имеет неоценимое значение. При этом не тратится драго¬
ценное время на длительные размышления и формулировку “завершенных” коррект¬
ных требований или на получение полного проектного решения. Благодаря обратной
связи у специалистов по тестированию в процессе разработки постоянно появляются
новые идеи и углубляется понимание требований и задач проекта. Конечные поль¬
зователи получают возможность быстро увидеть часть системы и сказать: “Да, это
именно то, что мне нужно. Но когда я попробовал поработать с этой программой,
у меня появились новые пожелания”.1 И это “да... но” не является сигналом тревоги.
Это нормальный путь развития и движения к совершенству, благодаря которому ру¬
ководители проекта смогут лучше осознать основные задачи проекта и требования
к системе. И это, естественно, не хаотическое и спонтанное движение, когда разра¬
ботчики постоянно изменяют направление своей деятельности. При таком способе
разработки достигается компромисс между устойчивостью и изменчивостью.Помимо прояснения системных требований, ранняя обратная связь и тестиро¬
вание каждой небольшой части системы (в частности, под нагрузкой) позволяют
оценить преимущества выбранной стратегии или ее недостатки. В последнем случае
на следующей итерации можно внести изменения в базовую архитектуру системы.
Гораздо лучше оценить возможные риски и критические моменты на начальной ста¬
дии проекта, чем на конечном этапе реализации; и итеративная разработка обеспе¬
чивает именно такой механизм.Таким образом, проект выполняется в виде последовательности циклов, каждый
из которых включает этап построения системы, получения обратной связи и адапта¬
ции. Не удивительно, что на начальных итерациях отклонения от “пути истинного” в
развитии системы (с точки зрения окончательной формулировки требований и про¬
ектных решений) гораздо существеннее, чем на последних итерациях. Со временем
процесс развития системы должен стать более устойчивым (рис. 2.2).Преимущества итеративной разработкиИтеративная разработка обладает следующими преимуществами.■ Меньший риск неудачного завершения проекта или получения некачественного
программного кода, большая производительность. Эти преимущества подтверж¬
даются исследованиями итеративных и эволюционных методов разработки.■ Своевременное (раннее) осознание возможных технических рисков, осмысле¬
ние требований, задач проекта и удобства использования системы.■ Быстрый и заметный прогресс.1 Правда, скорее всего, он скажет: “Вы абсолютно не поняли, чего я хотел”.
Глава 2. Итеративный, эволюционный и гибкий процесс 51Ранняя обратная связь, возможность учета пожеланий пользователей и адапта¬
ции системы. В результате система более точно удовлетворяет реальные требо¬
вания руководителей проекта и потребителей.Управляемая сложность. Команда разработчиков не перегружена лишней рабо¬
той на этапе анализа и проектирования и не “парализована” слишком сложны¬
ми и долгосрочными задачами.Полученный при реализации каждой итерации опыт можно методически ис¬
пользовать для улучшения самого процесса разработки.На начальных итерациях возможны значительные
отклонения от “правильного курса”. Благодаря обратной
связи и адаптации процесс разработки системы сводится к
наиболее подходящим требованиям и проектному решениюНа поздних итерациях
требования изменяются редко.
Такие изменения повышают
конкурентоспособность системыVОдна итерация проектирования,
реализации, интеграции и тестированияРис. 2.2. В процессе итеративной разработки, благодаря обратной связи и адаптации,система приобретает должный вид. Со временем требования и проектные решения пре¬
терпевают все менее серьезные измененияКакой должна быть длительность итерацииВ рамках большинства итеративных методов рекомендуется устанавливать дли¬
тельность каждой итерации в пределах от двух до шести недель. Небольшие шаги,
быстрая обратная связь и адаптация — это основные принципы итеративной разра¬
ботки. Большая длительность итераций сводит на нет саму идею итеративной раз¬
работки и повышает риск неудачного завершения проекта. Если длительность ите¬
рации составляет менее двух недель (например, одну неделю), то разработчикам не
остается времени для выполнения хоть сколько-нибудь существенной части работ и
получение обратной связи. Если же итерация занимает более шести недель, то по¬
ставленные для нее задачи могут оказаться слишком сложными. Кроме этого, откла¬
дывается также и момент получения обратной связи. При слишком длительных ите¬
рациях теряется сама идея итеративности. Поэтому чем короче, тем лучше.Очень важно, чтобы длительность итераций была фиксированной (timeboxed).
Например, если длительность итерации должна составлять три недели, то за это вре¬
мя нужно успеть не только разработать и реализовать намеченную часть системы, но
и провести ее интеграцию, тестирование и адаптацию. Если за указанный период вы¬
полнить все эти задачи нереально, нужно сократить список требований для данной
итерации и перенести их реализацию на следующий цикл, но ни в коем случае не
сдвигать дату завершения итерации.
52 Часть I. Введение2.3. Последовательный жизненный циклПоследовательный жизненный цикл (или процесс типа “водопада”, waterfall) пред¬
полагает детальное определение всех или большинства требований еще до перехода
к программированию. При использовании такого подхода к разработке полное про¬
ектное решение (или набор моделей) зачастую разрабатывается перед собственно реа¬
лизацией системы. Более того, иногда предпринимается также попытка определения
“достоверного” плана или графика выполнения работ. К сожалению, такой подход к
разработке зачастую оказывается нежизнеспособным.Предупреждение: наложение последовательного жизненного цикла
на итеративную разработкуЕсли в “итеративном” проекте большинство требований определяется перед на¬
чалом проектирования; предпринимается попытка создания исчерпывающих и
подробных спецификаций; или модели UML вместе с проектными решениями
разрабатываются до перехода к программированию, знайте, что мышление “в
духе” последовательного жизненного цикла может негативно отразиться на этом
проекте. Такой подход нельзя считать настоящей итеративной разработкой (на¬
пример, на основе метода UP), независимо от чьих-либо заявлений.Проведенные исследования убедительно свидетельствуют о том [84, 86], что по
иронии судьбы в 1960-1970-е годы рекомендуемый для применения последователь¬
ный жизненный цикл оказался неудачным для многих проектов. В настоящее время
каскадный процесс однозначно ассоциируется с высокой вероятностью неудачного
завершения проектов, низкой производительностью и высокими шансами получения
несовершенного программного кода (по сравнению с итеративными проектами).
Около 45% требований, которые были сформулированы в рамках каскадного процес¬
са, никогда не используются на практике, а построенные графики работ и оценки мо¬
гут отличаться вплоть до 400% по сравнению с реально полученными результатами.Оглядываясь назад, теперь можно с уверенностью утверждать, что подобные реко¬
мендации во многом основывались лишь на предположениях и слухах. В то же время
эффективность итеративных и эволюционных подходов к разработке подтверждена
на практике. Для таких проектов характерна высокая степень успешного завершения,
лучшая продуктивность и более качественный программный код.Не рассматривайте итеративный проект в терминах
последовательного жизненного циклаСтоит еще раз подчеркнуть, что мышление “в духе” последовательного жизнен¬
ного цикла очень часто сопровождает так называемый итеративный проект. Такие
подходы, как “написание всех прецедентов до перехода к программированию” или
“построение большого количества объектно-ориентированных моделей на UML до
реализации”, являются примерами некорректной подмены основных принципов
процесса UP. Разработчики унифицированного процесса сформулировали подобное
неправильное понимание, т.е. преждевременные анализ и моделирование, как основ¬
ную причину его некорректного использования [79].
Глава 2. Итеративный, эволюционный и гибкий процесс 53Почему каскадный процесс является таким ненадежнымНа этот вопрос нельзя дать один простой ответ, однако главная причина связа¬
на с тем, что в основу многих неудачно завершившихся проектов было положено
основное неверное предположение о том, что спецификации являются стабильны¬
ми и могут быть корректно определены еще в начале работ над системой. Однако
такой подход является неверным, а зачастую и дорогостоящим. Исследования [23]
показали, что в типичных проектах требования изменяются примерно на 25%, а в
крупных — на 50% [76]. Эта тенденция проиллюстрирована на рис. 2.3.Как видно из рисунка, для больших проектов процент изменяющихся требований
чрезвычайно высок. Из приведенного графика следует, что для предметной области
разработки программного обеспечения (или разработки нового продукта— new product
development) свойственна большая вероятность изменений и значительная неста¬
бильность. Это известно любому опытному разработчику или менеджеру. Для програм¬
много обеспечения обычно не характерно массовое производство (т.е. редко изменя¬
ющаяся область), когда возможно (и вполне приемлемо) разработать и использовать
устойчивые спецификации и надежные планы в самом начале процесса разработки.Размер проекта в функциональных точках
Рис. 2.3. Процент изменений для проектов различного размераТаким образом, любой анализ, моделирование или управление проектом, основан¬
ные на предположении о стабильности создаваемых артефактов, по существу дела яв¬
ляются далеко не лучшим подходом. Изменения (change) — это постоянная составляю¬
щая проектов, связанных с разработкой программного обеспечения. Итеративные и
эволюционные методы учитывают и допускают возможность изменения частично раз¬
работанных спецификаций, моделей и графиков работ на основе обратной связи.Необходимость обратной связи и адаптацииДля изменяющихся систем (например, большей части проектов, связанных с раз¬
работкой программного обеспечения) обратная связь и адаптация являются наибо¬
лее важными средствами достижения успеха.
54 Часть I. Введение■ Обратная связь на ранних стадиях процесса разработки, когда разработчики
анализируют спецификации и пользуются демонстрационными материалами,
полученными от заказчиков, для уточнения требований.■ Обратная связь от специалистов по тестированию и разработчиков, обеспечи¬
вающая возможность уточнения проектных решений или моделей.■ Обратная связь от менеджеров, которые на основе уже реализованных свойств
системы уточняют график работ и оценку хода выполнения проекта.■ Обратная связь от пользователей и других заинтересованных лиц, которые мо¬
гут изменить приоритет реализации различных функций системы на последую¬
щих итерациях.2.4. Как выполнять итеративный и эволюционный
анализ и проектированиеСейчас у читателя может сложиться впечатление, что нет особого смысла в ана¬
лизе и проектировании до программирования, однако неправильно также думать о
том, что, начав проект, нужно провести “полный” предварительный анализ. На са¬
мом деле существует золотая середина. Ниже приведен небольшой пример (его не
следует считать рецептом на все случаи жизни) того, как можно правильно органи¬
зовать работу в контексте проекта UP. В данном случае предполагается, что перед
передачей системы заказчику будет выполнено порядка 20 итераций.1. Перед итерацией 1 проводится первый семинар по определению требований, ко¬
торый должен занимать строго определенное время, например два дня. На этом
семинаре должны присутствовать как представители заказчика (специалисты в
предметной области), так и разработчики (в том числе главный архитектор).• В первый день утром проводится анализ высокоуровневых требований и
идентифицируются имена прецедентов и свойств, а также наиболее важные
нефункциональные требования. Результаты такого анализа наверняка будут
далеки от совершенства.• Главный архитектор и специалисты в предметной области из полученного
ранее списка должны выбрать 10% элементов (например, 10% из 30 имен
прецедентов), которые удовлетворяли хотя бы одному из приведенных ниже
критериев: 1) архитектурно значимые (после реализации такого элемента
можно переходить к проектированию, построению и тестированию базовой
архитектуры системы); 2) важные для рассматриваемой предметной области
(свойства, которые заслуживают пристального внимания); 3) связанные с вы¬
сокой степенью риска (например, “необходимо обеспечить одновременную
обработку 500 транзакций”). Предположим, удовлетворяющие критериям
прецеденты/свойства были выбраны и получили идентификаторы П1, П11
и П14.• В оставшиеся 1.5 дня выполняется детальный анализ функциональных и не¬
функциональных требований для выбранных трех прецедентов. В результате
10% выделенных прецедентов будут проанализированы достаточно детально,
а остальные 90% — лишь поверхностно.
Глава 2. Итеративный, эволюционный и гибкий процесс 552. Перед итерацией 1 нужно провести семинар по планированию итерации, на
котором для проектирования, построения и тестирования в рамках опреде¬
ленного промежутка времени (например, для четырехнедельной итерации)
должно быть выбрано подмножество элементов из прецедентов П1, П11 и П14.
Обратите внимание, что на итерации 1 эти три прецедента реализуются не пол¬
ностью, поскольку для этого потребовалось бы гораздо больше усилий. После
выбора подмножества целей нужно обеспечить их дальнейшее разбиение на на¬
бор более конкретных задач для текущей итерации. Это существенно поможет
группе разработчиков.3. Теперь можно приступить к итерации 1, длительность которой составляет три
или четыре недели (в соответствии с выбранными времениши рамками).• В течение первых двух дней разработчики и другие специалисты должны по¬
парно заниматься моделированием и проектированием, строить диаграммы
UML на доске или с использованием других доступных средств. Как правило,
вся эта деятельность выполняется в общей комнате под руководством главно¬
го архитектора.• В оставшиеся дни данной итерации разработчики занимаются программиро¬
ванием, тестированием и непрерывной интеграцией полученных модулей,
руководствуясь построенными ранее моделями и помня о том, что эти моде¬
ли являются неполными, а зачастую и неопределенными.• В процессе итерации выполняются различные виды тестирования: модуль¬
ное тестирование, тестирование нагрузки, удобства использования и т.д.• За неделю до завершения итерации необходимо определить, достижимы ли
ранее сформулированные для нее цели. Если нет, то необходимо выполнить
их перераспределение, поместив второстепенные цели обратно в список за¬
дач, ожидающих своего решения.• Во вторник последней недели нужно “заморозить” программный код, поме¬
стить его в хранилище, объединить с остальными модулями и выполнить его
тестирование. Тем самым должно быть обеспечено получение работоспособ¬
ной части системы на данной итерации.• В среду утром демонстрационная версия части системы должна быть пред¬
ставлена заинтересованным лицам (заказчику и пользователям). Это позво¬
лит оценить динамику развития проекта. Кроме того, разработчики смогут
воспользоваться обратной связью.4. Незадолго до завершения итерации 1, например в среду или четверг, необходи¬
мо провести второй семинар по формулировке требований. На этом семинаре
пересматриваются и уточняются все артефакты, которые были получены на
предыдущем семинаре. Затем выбираются другие 10-15% прецедентов, имею¬
щих важное архитектурное значение или играющих ключевую роль в исследу¬
емой предметной области. На протяжении одного или двух последующих дней
выбранные прецеденты подробно анализируются. После завершения анализа в
распоряжении разработчиков имеется уже порядка 25% детально описанных
прецедентов и нефункциональных требований. И снова не стоит забывать о
том, что эти описания могут быть еще далеки от совершенства.
56 Часть I. Введение5. Утром в пятницу нужно провести очередной семинар по планированию следую¬
щей итерации.6. При выполнении итерации 2 выполняются те же шаги, что и на итерации 1.7. Описанные выше виды деятельности выполняются для четырех итераций и
пяти семинаров по формулировке требований. В результате в конце итерации 4
около 80-90% требований будут описаны достаточно подробно. В то же время
будет реализовано лишь 10% системы.• Не забывайте о том, что получение набора детально описанных требований
к системе основывается на обратной связи и постоянном развитии. Поэтому
для всех артефактов характерно более высокое качество по сравнению со
спецификациями, создаваемыми в рамках последовательного жизненного
цикла.8. На текущий момент выполнено лишь 20% всего проекта. В терминах процесса
UP это означает, что завершена фаза развития (elaboration phase). Именно сей¬
час в контексте уточненных высокоуровневых требований необходимо тщатель¬
но оценить затраченные усилия и время. Благодаря исследованию реальной си¬
туации, обратной связи, а также раннему программированию и тестированию
можно достаточно точно оценить, что может быть сделано и сколько для этого
потребуется времени.9. При дальнейшем развитии проекта уже не стоит проводить семинары по фор¬
мулировке требований, поскольку они уже достаточно стабильны. Однако это
вовсе не означает, что требования полностью “заморожены”. Необходимо про¬
должить выполнение последовательности трехнедельных итераций, проводя
в последнюю пятницу каждой из них семинар по планированию последующей
итерации. На этих семинарах в контексте знаний и полученных результатов
должен обсуждаться один основной вопрос: “Каковы наиболее критичные тех¬
нические и другие требования, реализацию которых нужно обеспечить в тече¬
ние следующих трех недель?”.На рис! 2.4 представлена динамика развития проекта, состоящего из двадцати по¬
следовательных итераций.2.5. Итеративное планирование на основе рисков
и с учетом потребностей пользователейПроцесс UP (и другие современные методы) поддерживают итеративное плани¬
рование, которое управляется как рисками, так и потребностями пользователей. Это
означает, что цели, выбираемые на ранних итерациях, должны обеспечить: 1) иден¬
тификацию и учет наибольших рисков и 2) реализацию наиболее важных для пользо¬
вателей свойств системы.Итеративная разработка на основе рисков во многом сконцентрирована на по¬
строении архитектуры. Это означает, что на ранних итерациях разработчики в
основном занимаются построением, тестированием и получением устойчивой базо¬
вой архитектуры системы, поскольку отсутствие надежной архитектуры — это высо¬
кий риск, который может негативно повлиять на весь проект в целом.
Глава 2. Итеративный, эволюционный и гибкий процесс 571 2 3 4 520В данном примере чч
предполагается,
что при выполнении
итеративного проекта
будет выполнено
20 итерацийч Семинары по определению требований\ ' /4 \ ' \V \ I V \При итеративной
и эволюционной
разработке требования
эволюционируют
на ранних итерациях,
в процессе проведения
семинаров по опреде¬
лению требований
(например). Возможно,
после 4 итераций 90%
требований будут
сформулированы и
уточнены. В то же время
будет реализовано
лишь 10% программных
элементовоvoфа.20%ф3х55СОО.I—Оо.с2%Итерация 1оvoфQ.30%5%Итерация 250%8%Итерация 390%10%Итерация 490%20%Итерация 5Неделя 1неделя 2неделя 3Пн Вт Ср Чт Пт Пн Вт Ср Чт Пт Пн Вт Ср Чт Пт+ч/ IЧ'.чf•• fСеминарГ ибкоеНачалоПересмотр"Замора¬Демонс¬Семинарпо опре¬модели¬кодиро¬целейживание"трацияподелениюрованиевания иитерации,програм¬полученныхпланиро¬целейи проекти¬тестиро¬если работымного кодарезультатовваниюитерациирование,ванияоказалосьи разме¬и проведениеследующейс участиемпостроениеслишкомщениесеминара поитерации.группыдиаграмммногоего в хра¬определению2 часаразработ¬UML счнилищетребований.чиков.на доске.2 дня,о1 час5 часовНа данном этапевыполняется большаяНа семинарах ^часть анализа, проекти¬выполняетсярования и построениямоделированиедиаграмм UMLпрецедентовРис. 2.4. Эволюционный анализ и проектирование - это основные виды деятельности на ран¬
них итерациях
58 Часть I. ВведениеИтерации в учебных примерах и в реальном проектеИтерация 1 для практических примеров данной книги во многом обусловлена
учебными целями, а не задачами реального проекта. Именно поэтому она не на¬
правлена на построение архитектуры или устранение наибольших рисков. В ре¬
альном же проекте эти вопросы должны быть решены в первую очередь. Однако
основное внимание в книге уделяется фундаментальным принципам ООА/П и
языку UML. Поэтому в ней рассматриваются вопросы, призванные проиллюстри¬
ровать базовые принципы анализа и проектирования, а не способы решения наи¬
более сложных проблем.2.6. Что такое гибкие методыГибкие методы (agile development) поддерживают итеративную и эволюционную
разработку с адаптивным планированием и инкрементальным получением конечного
программного продукта, а также включают другие аспекты “гибкости”, например бы¬
струю и гибкую реакцию на изменения.Точно определить понятие “гибких методов” невозможно, поскольку в каждом них
используются достаточно разные подходы. В то же время короткие и фиксированные
по времени итерации, эволюционное уточнение планов, требований и проектных ре¬
шений — это базовые приемы, которые присутствуют в большинстве из них. Кроме
того, в гибких методах поддерживаются принципы и методики, обеспечивающие
простоту, легкость, самоорганизацию команды разработчиков и многое другое.Примером гибкого подхода к разработке может служить метод Scrum, в рамках
которого участники проекта размещаются в общей рабочей комнате, а также форми¬
руются самоорганизующиеся группы разработчиков. При этом их координация осу¬
ществляется путем проведения ежедневных семинаров, на которых каждый из участ¬
ников должен ответить на четыре заданных ему вопроса. В свою очередь, метод ХР
предлагает выполнять программирование в парах, а также вести разработку на основе
рисков (test-driven development).В качестве гибкого подхода к разработке может использоваться любой итератив¬
ный метод, в том числе UP. Процесс UP является гибким по своей природе и позво¬
ляет использовать полезные приемы из других методов, таких как Scrum или ХР.Манифест и основные принципы гибкого процесса
Манифест гибкого процессаЛюди и взаимодействие, а не процессы и средства.Работоспособное программное обеспечение, а не исчерпывающая документация.Сотрудничество с потребителями, а не обсуждение контракта.Реакция на изменения, а не следование плану:
Глава 2. Итеративный, эволюционный и гибкий процесс 59Основные принципы гибкого процесса1. Наивысший приоритет — удовлетворить потребности пользователей путем ран¬
него и непрерывного предоставления работоспособного программного обеспе¬
чения, реализующего требуемые функции.2. Необходимость изменений допускается даже на поздних этапах выполнения
проекта. Гибкие процессы позволяют учесть изменение требований и предоста¬
вить пользователям еще большие преимущества.3. Как можно чаще нужно предоставлять работоспособное программное обеспе¬
чение (каждые несколько недель или несколько месяцев) и стремиться макси¬
мально сократить эти временные интервалы.4. На протяжении всего проекта специалисты в предметной области и разработ¬
чики должны ежедневно работать вместе.5. Основу проекта должны составлять интересы потребителей. Предоставьте им
среду для работы, учитывайте их потребности и доверяйте им. Лишь в этом
случае можно успешно завершить проект.6. Наиболее эффективным способом обмена информацией внутри отдельных
групп разработчиков и между группами являются обсуждения “лицом к лицу”.7. Работоспособное программное обеспечение — это основная мера оценки разви¬
тия проекта.8. Гибкие методы способствуют устойчивости процесса разработки.9. Спонсоры, разработчики и пользователи должны поддерживать устойчивый
темп развития проекта независимо друг от друга.10. Постоянное стремление к техническому усовершенствованию и улучшению
проектных решений повышают гибкость.11. Обеспечение простоты — это искусство максимизации количества работы, ко¬
торую не нужно делать. Это очень важно!12. Наилучшую архитектуру и проектные решения, а также требования могут раз¬
работать только самоорганизующиеся группы разработчиков.13. Разработчики должны регулярно анализировать состояние проекта и думать,
как можно повысить его эффективность. Затем в организацию работ можно
внести соответствующие изменения.В 2001 году группа специалистов, заинтересованных в развитии итеративных
и гибких методов, провели общий семинар для поиска общей платформы в своих
исследованиях. Независимо от этого некоммерческая организация Agile Alliance
(www.agilealliance.com) предложила манифест и набор принципов, которые отра¬
жали бы основной смысл гибких методов.2.7. Что такое гибкое моделированиеОпытным аналитикам и специалистам по моделированию хорошо известен следу¬
ющий секрет.Основная цель моделирования (например, с использованием языка UML) за¬
ключается в том, чтобы попять, а не документировать.
60 Часть I. ВведениеДругими словами, моделирование может и должно способствовать лучшему по¬
ниманию проблемы или пространства решений. С этой точки зрения “применение
UME’ (что на самом деле должно означать “применение ООА/П”) вовсе не означает,
что проектировщик должен создать множество детальных диаграмм UML, которые
использовал бы программист. (Большинство из них склонны к не очень гибкому мыш¬
лению “в духе” каскадного процесса.) Моделирование должно позволить быстрее (по
сравнению с кодированием) исследовать возможные альтернативы и наметить путь
для получения качественных проектных решений.Такой подход, хорошо согласующийся с гибкими методами, в [6] называется гиб¬
ким моделированием (agile modeling) и предполагает использование нескольких при¬
емов.■ Применение гибкого метода вовсе не означает, что моделирование вообще не
выполняется. В рамках многих гибких методов, например, при разработке на
основе свойств (Feature-Driven Development), DSDM или Scrum, обычно прово¬
дятся достаточно продолжительные семинары по моделированию. Даже осно¬
ватели метода ХР, одного из наиболее известных гибких методов, в котором
моделированию уделяется не слишком много внимания, поддерживают гибкое
моделирование. Такой подход в течение многих лет используется на практике
достаточно большим количеством специалистов.■ Моделирование и модели в основном используются для улучшения понимания
решаемой проблемы и взаимодействия разработчиков, а не документирования.■ Не нужно строить модель или применять язык UML для описания всех или
большей части проектных решений. Решение простых и очевидных проблем
лучше отложить на стадию программирования и тестирования. Выполняйте
моделирование и используйте UML для небольшой части проектных решений,
которые являются неочевидными или трудными для понимания.■ Пользуйтесь настолько простыми средствами, насколько это возможно. Приме¬
няйте простые инструменты, которые повышают креативность, не требуют
чрезмерных затрат (умственных, времениых и т.д.) и позволяют быстро вносить
требуемые изменения. Кроме того, стоит задуматься о развертывании большого
визуального пространства. Например, рисуйте диаграммы UML на белой доске,
а затем фотографируйте их на цифровую фотокамеру.2• Это вовсе не означает, что нельзя использовать текстовые процессоры или
CASE-cpeдетва, поддерживающие UML. Однако подобные вспомогательные
инструменты должны поддерживать творческий подход к проведению иссле¬
дований и выполнению других видов работ, а также позволять быстро вно¬
сить все требуемые изменения. Основное правило заключается в том, чтобы
применять простые и гибкие технологии.2 Насчет использования доски можно дать два совета. Если в вашем распоряжении нет доста¬
точного количества белых досок (а вам требуется большое рабочее пространство), воспользуй¬
тесь пластичными клейкими листами, которые можно прикрепить к стене. Соответствующие
товары имеются на рынке как в Северной Америке, так и в Европе. Цифровые фотографии
диаграмм, нарисованных на доске, часто выглядят не очень удачно (из-за эффекта отражения).
Поэтому при фотографировании не пользуйтесь вспышкой, а для “улучшения” полученных изо¬
бражений применяйте специальное программное обеспечение (именно так и поступал автор
данной книги).
Глава 2. Итеративный, эволюционный и гибкий процесс 61■ Не следует выполнять моделирование в одиночку. Лучше разделиться на пары
или тройки и рисовать диаграммы на белой доске. При этом не следует забы¬
вать об основной цели моделирования: изучить, разобраться в существующей
проблеме, а затем поделиться полученными знаниями с другими разработчика¬
ми. Организуйте работу так, чтобы все могли принять участие в процессе моде¬
лирования.■ Создавайте модели параллельно. Например, на одной доске можно рисовать
динамическую диаграмму взаимодействий UML, а на второй доске — дополни¬
тельную статическую диаграмму классов. Разрабатывайте две модели (два пред¬
ставления) одновременно, периодически переключаясь между ними.■ При разработке модели на доске используйте простую систему обозначений,
которая лучше всего подходит в конкретной ситуации. При этом строгое сле¬
дование нотации UML вовсе не обязательно, поскольку специалисты по моде¬
лированию и без этого прекрасно могут понять друг друга. Ограничьтесь про¬
стыми, часто используемыми, элементами UML.■ Учитывайте тот факт, что все модели наверняка окажутся неточными, а про¬
граммный код и проектные решения — совсем другими. Лишь протестирован¬
ный программный код способен продемонстрировать правильность принятых
проектных решений, а все построенные ранее диаграммы следует рассматри¬
вать лишь как незавершенные рекомендации, которые лучше рассматривать
как результат предварительных исследований.■ Разработчики должны выполнять моделирование и объектно-ориентированное
проектирование для повышения собственного понимания проблемы, а не для
того, чтобы передать построенные диаграммы другим разработчикам (как, на¬
пример, в каскадном жизненном цикле).Гибкое моделирование в данной книгеАвтор данной книги и многие разработчики на практике уже в течение многих
лет активно пользуются моделированием на доске. Однако при ознакомлении с диа¬
граммами UML в данной книге у читателя может возникнуть впечатление, что ав¬
тор на самом деле не применяет данный подход, поскольку большинство диаграмм
создано с помощью специальных программных средств. Во многом это сделано для
улучшения восприятия. Для того чтобы изменить первое впечатление, в книгу были
добавлены цифровые снимки диаграмм, которые были вручную нарисованы на до¬
ске. Это несколько ухудшает их ясность, но в то же время позволяет удостовериться в
том, что гибкое моделирование является полезным практическим приемом, который
разработчики часто используют в своей профессиональной деятельности.Например, на рис. 2.5 приведен набросок диаграммы UML, который был создан
автором при руководстве одним из проектов. Для его создания потребовалось всего
20 минут. При этом рядом находилось четыре разработчика. В тот момент нам было
необходимо разобраться со взаимодействием между компонентами внутри разраба¬
тываемой системы. Благодаря совместной работе упрощается понимание сути про¬
цессов и легче достигается общее понимание проблемы. Именно в таком контексте и
нужно пользоваться гибким моделированием и языком UML.
62 Часть I. ВведениеSc«WM* »V *****Ш>■ь«»пffctboW.ЛЕэ)HEfi, KevvUfaiimic 55SPLIT t* okjtftp)s>neP.fMWE («МлСЗ)
fttfM.b l«* ofajtcVO^ЫрпС ")f№»bzPttpx«Lpf€. ( >s1*1»5>C3mewhe.^ *)i.jLe.sumC C.FS <toj&cK3)•C: - ■. _ jtlytysDSl*p ()l&UHE-C ")■i»W>4>pO<+• pC ) rXРж. 2.5. Набросок диаграммы последовательности на языке UML2.8. Что такое гибкий унифицированный процессУнифицированный процесс задумывался авторами не как тяжелый или детерми¬
нированный, хотя обширный набор необязательных видов деятельности и артефактов
иногда наводит разработчиков на такую мысль. Он разрабатывался как адаптивный и
подвижный — гибкий UP (agile UP). Это обеспечивается следующим образом.■ Выбирается небольшой набор видов деятельности и артефактов UP. Различные
проекты могут выиграть от такого подхода в большей или меньшей степени,
однако в любом случае стоит стремиться к простоте. Не забывайте о том, что
все артефакты UP являются необязательными, и избегайте их создания, если
при этом нельзя получить новое качество. Сосредоточьтесь на раннем програм¬
мировании, а не на раннем документировании.■ Поскольку унифицированный процесс является итеративным, то анализ тре¬
бований и проектирование не завершаются к моменту начала реализации.
Требования и модель проектирования адаптивно настраиваются в течение не¬
скольких итераций на основе обратной связи.
Глава 2. Итеративный, эволюционный и гибкий процесс 63■ Применяйте язык UML вместе с приемами гибкого моделирования.■ Не существует подробного плана всего проекта. Разрабатывается лишь план вы¬
сокого уровня, или так называемый укрупненный план (phase plan), в котором
указывается дата завершения проекта и даты выполнения основных этапов,
однако этот план не детализируется. Подробный план, или так называемый
план итерации (iteration plan), строится для каждой итерации в отдельности.
Детальное планирование выполняется адаптивно от итерации к итерации.В учебных примерах основное внимание будет сосредоточено на относительно
небольшом наборе артефактов и итеративной разработке, как и положено в рамках
гибкого процесса UP.2.9. Другие важные принципы
унифицированного процессаОсновной идеей унифицированного процесса является разбиение процесса раз¬
работки на короткие итерации фиксированной длительности, а также обеспечение
ее адаптивности и эволюционности. К числу других важных принципов и концепций
унифицированного процесса относятся следующие.■ Оценка рисков и ключевых моментов проекта на ранних итерациях.■ Постоянный отклик пользователей, обратная связь и модификация требований.■ Построение общей базовой архитектуры на ранних итерациях.■ Постоянный контроль качества, раннее и частое тестирование в реальных усло¬
виях.■ Применение прецедентов.■ Визуализация программной модели (с помощью языка UML).■ Внимательное управление требованиями.■ Обработка запросов на внесение изменений и управление конфигурацией.2.10. Фазы унифицированного процессаВ рамках унифицированного процесса работа над проектом включает четыре
основные фазы.1. Начало (inception) — определение начального видения проблемы, прецедентов,
оценка сложности задачи.2. Развитие (elaboration) — формирование более полного видения проблемы,
итеративная реализация базовой архитектуры, создание наиболее критичных
компонентов (разрешение высоких рисков), идентификация основных требо¬
ваний, получение более реалистичных оценок.3. Конструирование (construction) — итеративная реализация оставшихся менее
критичных и простых элементов, подготовка к развертыванию.4. Передача (transition) — бета-тестирование и развертывание.
64 Часть I. ВведениеЭти фазы более детально обсуждаются в последующих главах.Это не последовательный жизненный цикл, при котором сначала определяются
все требования, а только затем начинается вся разработка системы.Начальная фаза — это не стадия формулировки требований. Это, скорее, этап оце¬
нивания ситуации, на котором принимается решение о целесообразности или неце¬
лесообразности дальнейшей разработки.Развитие — это не стадия формулировки требований или проектирования, а фаза
итеративной реализации базовой архитектуры и разрешения высоких рисков.На рис. 2.6 показана взаимосвязь терминов, принятых при описании графика вы¬
полнения работ в рамках унифицированного процесса. Заметим, что один цикл раз¬
работки (который завершается созданием коммерческой версии программного про¬
дукта) состоит из многих итераций.Цикл разработки, А >Итерация Фаза< А 'НачалоРезвипеонструироваш -ежПеродачаt tВехаКонецитерации,на которойполученыважныерешенияи оценкиРелизСтабильно
работающая часть
программного
продукта. В идеале
релиз должен
появляться в конце
каждой итерацииИнкрементРазница (дельта)
между релизами
двухпоследовательныхитерацийtОкончательныйрелизТеперь система
пригодна для
коммерческого
использованияРис. 2.6. Термины, используемые при описании графика выполнения работ в рамкахунифицированного процесса2.11. Дисциплины унифицированного процессаУнифицированный процесс предполагает выполнение различных видов деятель¬
ности, например описание прецедентов, в рамках определенных дисциплин (disci¬
plines). По существу, дисциплина — это набор видов деятельности (и связанных с ними
артефактов) в рамках одного этапа, например в рамках анализа требований. В кон¬
тексте унифицированного процесса артефактом (artifact) называется любой резуль¬
тат работы: код, графическое изображение для Web, схема базы данных, текстовые
документы, диаграммы, модели и т.д.В рамках UP существует несколько дисциплин. В этой книге внимание сосредото¬
чено на некоторых артефактах следующих трех дисциплин.
Глава 2. Итеративный, эволюционный и гибкий процесс 65■ Бизнес-моделирование (business modeling). Эта дисциплина подразумевает раз¬
работку модели предметной области (domain model), которая является визуаль¬
ным представлением наиболее важных сущностей из предметной области и их
взаимосвязей для разрабатываемого приложения.■ Требования (requirements). В рамках этой дисциплины создается модель пре¬
цедентов (Use-Case Model) и дополнительная спецификация (Supplementary
Specification). В этих двух артефактах отражаются функциональные и нефунк¬
циональные требования.■ Проектирование (design). Сюда относится модель проектирования (Design
Model), которая отражает программные объекты.Более полный перечень дисциплин UP показан на рис. 2.7.В контексте UP реализация (implementation) означает программирование и по¬
строение системы, но не ее развертывание. Дисциплина “Окружение” (environ¬
ment) предполагает установку необходимых средств и настройку процесса для дан¬
ного проекта.На каждой итерации выполняется
работа в рамках большинства
дисциплин. Однако основные
акценты смещаются со временем.Данный пример является
иллюстративным и не носит
рекомендательного характераПримеры
дисциплин UPБизнес-моделированиеТребованияПроектированиеРеализацияТестированиеРазвертываниеКонфигурация и
управление изменениямиУправление проектомОкружениеЧетырехнедельная итерация (например).
Мини-проект, включающий работу в рамках
большинства дисциплин, в результате реализации
которого получен устойчивый работающий кодРис. 2.7. Дисциплины унифицированного процесса33ак.3357
66 Часть I. ВведениеДисциплины и фазыКак видно из рис. 2.7, в течение одной итерации работа выполняется в рамках
всех или большинства дисциплин. Однако удельный вес каждой дисциплины в общем
объеме работ изменяется со временем. На ранних итерациях, естественно, основное
внимание уделяется требованиям и проектированию, а на более поздних, когда тре¬
бования и ядро системы уже “устоялись” благодаря обратной связи и адаптации, дея¬
тельность в рамках этих дисциплин сходит на нет.На рис. 2.8 показан удельный вес различных дисциплин в контексте фаз унифи¬
цированного процесса (начало, развитие и т.д.). Заметим, что это соотношение сле¬
дует рассматривать лишь как рекомендацию, а не догму. Например, фазе развития
присущ относительно большой удельный вес работ по определению требований и
проектированию. Однако при этом выполняется и программная реализация. В про¬
цессе конструирования основное внимание переключается с анализа требований на
реализацию.Удельный В
вес дисциплин
изменяется
со временем.Данный пример
является
иллюстративным
и не носит реко¬
мендательного
характераРис. 2.8. Дисциплины и фазыФазы UP, дисциплины и структура книгиНа каких фазах и дисциплинах будет сосредоточено внимание при рассмотрении
реальных примеров? Ответ сводится к следующему.При описании реальных примеров основное внимание будет уделяться фазам на¬
чала и развития. При этом будут рассмотрены некоторые артефакты дисциплин
бизнес-моделирования, требований и проектирования, поскольку именно с эти¬
ми дисциплинами наиболее тесно связаны анализ требований, ООА/П, шаблоны
и язык UML.В начальных главах книги рассматриваются виды деятельности начальной фазы
реализации проекта. Последующие главы посвящены нескольким итерациям фазы
развития. В следующем списке и на рис. 2.9 представлена структура книги в контек¬
сте фаз UP.1. В главах, посвященных “начальной” фазе, рассматриваются вопросы анализа
требований.
Глава 2. Итеративный, эволюционный и гибкий процесс 672. При описании первой итерации вводятся основные понятия анализа и про¬
ектирования, а также рассматриваются вопросы распределения обязанностей
между объектами.3. При переходе ко второй итерации основное внимание уделяется проектирова¬
нию объектов, особенно некоторым наиболее часто используемым шаблонам
проектирования.4. При рассмотрении третьей итерации затрагивается множество вопросов, в том
числе связанных с анализом архитектуры и проектированием каркасов.Структура книгиНачарег*!Итерация фазы I .. Итерация фазы
развития 1 J \ развития 2чИтерация фазы
развития 3I Hi §|, 11 jig IСпециальныевопросыОбъектно-Объектно-Отображениеориентированныйориентированноепроектногоанализпроектированиерешения в код_ jВопросы |объектно-ориентированного
анализа и проектирования
рассматриваются
на итерациях 1, 2 и 3Рис. 2.9. Структура книги в контексте фаз и итераций UP2.12. Настройка процесса и выбор инструментов UPНеобязательные артефакты и приемыПочти все артефакты унифицированного процесса являются необязательными! В
то же время его некоторые принципы и концепции являются основными и неотъем¬
лемыми. К ним относятся итеративная разработка на основе рисков, а также непре¬
рывный контроль качества.Однако при более пристальном взгляде на UP оказывается, что все виды деятель¬
ности и артефакты (модели, диаграммы, документы и т.д.) являются необязательными
(за исключением, возможно, кода).АналогияНабор возможных артефактов, описанных в рамках UP, можно рассматривать как
ассортимент медикаментов в аптеке. Покупатель вряд ли купит в аптеке все воз¬
можные медикаменты; он ограничится некоторым небольшим набором нужных
ему лекарств. Так и разработчики проекта в рамках UP должны выбрать для себя
небольшой набор артефактов, наиболее точно удовлетворяющий их потребности.
В целом, нужно сосредоточиться на небольшом подмножестве артефактов, имеющих
решающее практическое значение.
68 Часть I. ВведениеНабор инструментовВыбранные для данного проекта артефакты 1й приемы можно описать в кратком
перечне под названием “Набор инструментов” ^Development Case) (артефакт дисци¬
плины “Окружение”). Например, в табл. 2.1 указан набор инструментов для проекта
NextGen, рассматриваемого в этой книге в качестве примера.В последующих главах рассказывается о создании некоторых из этих артефактов,
включая модель предметной области, модель прецедентов и модель проектирования.Выбранный для этого проекта набор артефактов и приемов не обязательно подой¬
дет для всех проектов. Например, для системы управления автомобилем более полез¬
ными окажутся различные диаграммы состояний. При разработке системы электрон¬
ной коммерции для Web основное внимание нужно уделить прототипам интерфейса
пользователя. Артефакты проекта по озеленению должны значительно отличаться от
документации проекта системной интеграции.Таблица 2.1. Примерный набор инструментов унифицированного процесса
(н — начало, р - развитие)ДисциплинаПриемыАртефактИтерация-»НачалоИРазвитиеЕ1..ЕПКонструи¬рованиеС1..СпПередачаТ1..ТпБизнес-моделированиеГибкое моде¬
лирование,
регулярные
семинарыМодель предмет¬
ной областинТребованияРегулярныесеминарыМодель преце¬
дентовнРВидение системынРДополнительнаяспецификациянРСловарь терминовнРПроектированиеГибкое моде¬
лирование,
разработка на
основе рисковМодель проекти¬
рованиянРОписание архи¬
тектурынМодель данныхнРРеализацияРазработка
на основе
рисков, пар¬
ное програм¬
мирование,
непрерывная
интеграцияУправлениепроектомГибкое
управление,
ежедневные
семинары в
стиле Scrum
Глава 2. Итеративный, эволюционный и гибкий процесс 692.13. Вы не поняли, что такое итеративная
разработка или унифицированный
процесс, если...Вот несколько признаков, свидетельствующих о непонимании сущности унифици¬
рованного процесса и итеративной разработки.■ Вы пытаетесь определить большую часть требований до начала проектирования
и реализации. Аналогично, вы стараетесь получить большую часть проектных
решений до начала реализации; пытаетесь полностью определить и утвердить
архитектуру до начала итеративного программирования и тестирования.■ Вы много дней или даже недель занимаетесь моделированием на языке UML
или думаете, что в процессе проектирования и создания диаграмм UML нужно
точно и подробно определить проектное решение, а этап программирования —
это лишь механическое преобразование модели в код.■ Вы считаете, что начальная фаза эквивалентна определению требований, раз¬
витие означает проектирование, а построение — реализацию (т.е. пытаетесь
проектировать линейный жизненный цикл на UP).■ Вы думаете, что задачей фазы развития является полное и точное определение
моделей, которые на этапе конструирования будут отображены в коде.■ Вам кажется, что продолжительность итерации должна составлять три месяца,
а не три недели.■ Вы считаете, что унифицированный процесс предполагает выполнение множе¬
ства операций и создание многочисленных документов, и рассматриваете UP
как формальный нервный процесс, включающий множество этапов.■ Вы хотите детально спланировать проект от начала до конца; стараетесь зара¬
нее предугадать все необходимые итерации и предсказать возможное развитие
событий на каждой из них.2.14. ИсторияДля краткого ознакомления с историей развития методов разработки можно обра¬
титься к [86]. Итеративные методы начали развиваться гораздо раньше, чем принято
считать в настоящее время. Во второй половине 1950-х годов именно эволюционный,
итеративный и инкрементальный подход к разработке (IID — Iterative, Incremental
Development), а не каскадный процесс использовался при выполнении космического
проекта Mercury. В 1960-х годах этот подход использовался и в рамках проекта по соз¬
данию подводной лодки Trident, а также во многих других крупных проектах. Первая
статья, в которой “пропагандировался” итеративный подход, была опубликована в
1968 году в исследовательском центре Watson Research Center компании IBM.В 1970-х годах итеративный подход применялся во многих больших аэрокосми¬
ческих и военных проектах, в том числе при разработке программного обеспечения
управления полетом космического корабля Shuttle. (Это программное обеспечение
было разработано в течение 17 итераций, каждая из которых длилась примерно 4 не¬
70 Часть I. Введениедели.) Еще в 1970-х годах основной идеолог инженерии программного обеспечения
Халан Миле (Harlan Mills) писал о проблемах, связанных с использованием каскадно¬
го процесса, и о необходимости применения итеративных методов. Частный консуль¬
тант Том Гилб (Tom Gilb) в 1970-х годах хорошо описал первый итеративный метод
Evo. В конце 1970-х-начале 1980-х годов в Министерстве обороны США активно ис¬
пользовался каскадный процесс (DoD-2167). Однако после проведения исследований
в конце 1980-х годов оказалось, что около 50% поддерживаемых этим министерством
проектов были закрыты или привели к получению непригодных результатов. В ко¬
нечном счете такая неудачная практика выполнения проектов была отменена (в 1987
году), и был осуществлен переход к использованию итеративных методов. В то же
время следует заметить, что устаревший каскадный процесс и в настоящее время ока¬
зывает негативное влияние на некоторые проекты Министерства обороны США.В тех же 1980-х годах Фредерик Брукс (Frederick Brooks), автор книги [25] и
основной идеолог инженерии программного обеспечения того времени, много гово¬
рил и писал о недостатках каскадной разработки и о необходимости перехода к ите¬
ративным методам. В 1980-х годах стоит вспомнить еще об одной статье Барри Боэма
(Barry Boehm), в которой была описана спиральная модель итеративного подхода к
разработке на основе рисков. В этой публикации подчеркивалось, что при использо¬
вании каскадного процесса разработки существенно возрастает вероятность неудач¬
ного завершения проекта.В начале 1990-х годов итеративный и инкрементальный подход к разработке был
де-факто признан преемником каскадного процесса. В то же время начался настоя¬
щий расцвет итеративных и эволюционных методов, таких как UP, DSDM, Scrum, ХР,
и многих других подходов к разработке.2.15. Дополнительные ресурсыКраткое и доступное введение в проблемы унифицированного процесса (и его мо¬
дификации в виде Rational Unified Process) содержится в книге главного архитектора
RUP Филиппа Крачтена (Philippe Kruchten) [81]. Заслуживает внимания также книга
Крачтена и Кролла (Kroll) The Rational Unified Process Made Easy.В книге [84] обсуждается итеративный и гибкий подход к разработке, а также рас¬
сматриваются четыре итеративных метода (ХР, UP, Scrum и Evo). С помощью этой
книги можно ознакомиться с причинами возникновения и историей развития этих
методов, а также анализом причин несостоятельности каскадного жизненного цикла.Другие “гибкие” методы описаны в серии книг ХР (Extreme Programming — экс¬
тремальное программирование) [12, 14, 73]. Некоторые приемы ХР упоминаются в
последующих главах. Большинство идей ХР (таких, как программирование с предва¬
рительным тестированием (test-first programming), непрерывная интеграция и итера¬
тивная разработка) схожие с концепциями UP (или совпадают с ними), поэтому их
можно применять в проектах UP.Еще одним популярным итеративным методом разработки является Scrum. В рам¬
ках этого метода используются 30-дневные фиксированные итерации и ежедневные
короткие семинары, на которых каждому из разработчиков задается несколько во¬
просов. Для более подробного ознакомления с процессом Scrum обратитесь к книге
Agile Software Development with Scrum.
Глава 2. Итеративный, эволюционный и гибкий процесс 71Гибкое моделирование рассматривается в книге Скотта Амблера (Scott Ambler)
[6].Компания IBM продает ориентированный на Web программный продукт, в кото¬
ром содержатся документы, связанные с процессом RUP. Там подробно описаны арте¬
факты и виды деятельности RUP, а также приводятся шаблоны для большинства арте¬
фактов. Освоить унифицированный процесс можно и по книгам, но многие считают
продукт RUP очень полезным средством для обучения и реализации процесса UP.В Web можно воспользоваться следующими ресурсами.■ www.agilealliance.com. Большая коллекция статей, посвященных исключи¬
тельно итеративным и гибким методам, а также соответствующих тематических
ссылок.■ www.agilemodeling.com. Статьи, посвященные гибкому моделированию.■ www.cetus-links.org. Web-узел Cetus Links уже многие годы специализируется
на объектных технологиях. На нем содержится много ссылок на тему итератив¬
ных и гибких методов даже несмотря на то, что многие из них напрямую никак
не связаны с объектной технологией.■ www.bradapp.net. Брэд Эпплтон (Brad Appleton) поддерживает большую кол¬
лекцию ссылок, связанных с вопросами инженерии программного обеспече¬
ния, в том числе с итеративными методами.■ www.iturls.com. Этот Web-узел предоставляет механизм поиска статей, посвя¬
щенных итеративным и гибким методам. Для удобства использования этого ме¬
ханизма нужно перейти к англоязычному пользовательскому интерфейсу.
Конкретные примерыСуществует совсем немного вещей,, которые придумать труднее, 'Чблс хороший пример.Марк Твен (Mark Twain)Основная задача■ Ознакомиться с конкретными примерами, рассматриваемыми в этой
книге.ВведениеРассматриваемые в этой книге конкретные примеры выбраны именно потому,
что многие знакомы с подобными задачами. В книге рассматриваются интересные и
сложные проектные решения, позволяющие сконцентрироваться на фундаменталь¬
ных принципах ООА/П, анализе требований, UML и шаблонах, а не на постановке
задач и предметной области.Что дальше? После ознакомления с итеративным процессом в данной главе рассматриваются
конкретные примеры и основные элементы уровня логики приложения, которые
будут рассматриваться в книге. Следующая глава посвящена стадии начала
разработки учебных приложений. При этом подчеркивается, что начало не является
фазой каскадного процесса, на которой проводится ранний анализ всех требований/ \Итеративная,Введение эволюционная Конкретные Начальная Эволюционныев ООА/П и быстрая примеры . требования^ фЭЗЭразработкао о • о о
74 Часть I. Введение3.1. Какие вопросы рассматриваются
и не рассматриваются при изучении
конкретных примеровАрхитектура типичной информационной системы включает графический интер¬
фейс пользователя, взаимодействие с базой данных, уровень логики приложения и
взаимосвязь с другими программными системами или архитектурными компонента¬
ми (рис. 3.1).Хотя объектно-ориентированную технологию можно применять ко всем уровням,
в данной книге основное внимание уделяется вопросам анализа и проектирова¬
ния базового уровня логики приложения, а другие уровни рассматриваются только по¬
верхностно.При рассмотрении других уровней (например, интерфейса пользователя) мы, в
основном, сосредоточимся на разработке их интерфейса с уровнем логики приложе¬
ния.Почему основное внимание в процессе ООА/П уделяется базовому уровню логи¬
ки приложения? На этот вопрос можно ответить следующим образом.■ Другие уровни обычно в значительной мере зависят от платформы или от реа¬
лизации. Например, чтобы изучить вопросы объектно-ориентированного про¬
ектирования Web-интерфейса или интерфейса пользователя на Java, необхо¬
димо детально разобраться с такими каркасами, как Struts или Swing. Если же
в качестве платформы разработки выбрана .NET или Python, базовые знания
должны быть совершенно другими.■ В отличие от этого объектно-ориентированное проектирование уровня логики
приложения одинаково для всех технологий.■ Основные знания и навыки, приобретенные в процессе изучения ООП в кон¬
тексте уровня логики приложения, применимы ко всем другим уровням или
компонентам.■ Подход к проектированию (в том числе на основе шаблонов) быстро изменяет¬
ся с появлением новых каркасов или технологий. Например, в середине 1990-х
разработчикам приходилось создавать свои собственные доморощенные объек¬
тно-реляционные уровни доступа к базам данных. А спустя несколько лет они
предпочли использовать свободно распространяемые решения с открытым ко¬
дом, такие как Hibernate (для технологии Java).
Глава 3. Конкретные примеры 75Неосновное внимание
в примерахОбсуждается связь
с другими уровнями
и вопросы удобства
использованияОсновное внимание
в примерахРассматриваютсяпринципыпроектированияобъектовНеосновное внимание
в примерахРис. 3.1. Уровни и объекты типичной объектно-ориентированной системы с указанием
степени детализации их описания в данной книге3.2. Стратегия описания конкретных
примеров: итеративная
разработка + итеративное изучениеСтруктура материала в этой книге основывается на итеративной стратегии раз¬
работки. Объектно-ориентированный анализ и проектирование применяются к раз¬
работке конкретных систем в процессе реализации нескольких итераций. На первой
итерации обеспечивается выполнение некоторых базовых функций, а на последую¬
щих расширяется функциональность систем (рис. 3.2).В соответствии с итерационной стратегией разработки в книге будут последова¬
тельно представлены главы, посвященные объектно-ориентированному анализу и
проектированию, системе обозначений языка UML и шаблонам. В главах, посвящен¬
ных первой итерации, будут рассмотрены базовые вопросы анализа и проектирова¬
ния, а также основные обозначения, принятые в UML. В главах, посвященных вто¬
рой итерации, будут описаны новые идеи, новые обозначения UML, шаблоны и т.д.
Это же касается и третьей итерации.ПользовательскийинтерфейсУровень логики
приложенияДругие уровни
или компонентыРегистрация.Доступ
к базе данных.
76 Часть I. ВведениеРассматриваются
вопросы анализа
и проектирования,
связанные
с первой итерациейРассматриваются
новые вопросы
анализаи проектированияАналогичноРис. 3.2. Последовательность изучения материала соответствует
итеративному процессу разработки приложения3.3. Пример 1: POS-система NextGenПервым примером, рассматриваемым в этой книге, является система автоматиза¬
ции торговой точки — POS-система NextGen. Рассматриваемая задача очень интерес¬
на своими требованиями и проблемами, возникающими в процессе проектирования.
Кроме того, она очень реалистична. Многие организации действительно разрабаты¬
вают POS-системы (point-of-sale system) на основе объектной технологии.POS-система — это компьютеризированное приложе¬
ние, предназначенное для организации товарооборота и
обработки платежей в обычных магазинах. Система авто¬
матизации торговли включает аппаратные компоненты
(компьютер и устройство считывания штрихкода), а так¬
же программное обеспечение, выполняющее основные
задачи системы. Это приложение связано с различными
служебными программами, например с программой вы¬
числения налогов, разработанной сторонними произ¬
водителями, или с системой складского учета товаров.Подобные системы должны быть устойчивыми к сбоям,
т.е. работоспособными при временном выходе из строя удаленных служб (например,
системы складского учета товаров). В критических ситуациях они должны обслужи¬
вать продажу товаров и обеспечивать обработку хотя бы платежей наличными (что¬
бы хозяин магазина не обанкротился).POS-система должна поддерживать различные типы клиентских терминалов и ин¬
терфейсов, в том числе клиентский терминал с Web-браузером (“тонкого” клиента),
обычный персональный компьютер с графическим интерфейсом пользователя типа
Java Swing, сенсорный ввод информации, беспроводный интерфейс и т.п.Более того, коммерческие POS-системы должны уметь работать с различными ка¬
тегориями потребителей, для которых определены отдельные бизнес-правила. Для
каждого потребителя может быть предусмотрена своя логика выполнения отдельных
операций в рамках сценария использования системы, например, специфические дей¬
ствия при добавлении нового товара или создании новой продажи. Следовательно, не¬
обходимо предусмотреть механизм обеспечения этой гибкости и настройки системы.На основе итеративной стратегии разработки мы выполним все необходимые
этапы создания системы: формулировку требований, объектно-ориентированный
анализ, проектирование и реализацию.
Глава 3. Конкретные примеры 773.4. Пример 2: игра “Монополия”Чтобы показать применимость основных при¬
емов ООА/П к различным задачам, в качестве вто¬
рого примера рассмотрим программную версию
игры “Монополия”. Хотя предметная область и
требования к этой системе не имеют ничего обще¬
го с коммерческими системами типа POS-системы
NextGen, при разработке программы применяются
те же методы моделирования предметной области,
объектно-ориентированного проектирования, ша¬
блоны и обозначения UML. Как и система автома¬
тизации розничной торговли, программная версия
игры “Монополия” реально существует и продает¬
ся. Она также поддерживает разнообразное клиент¬
ское программное обеспечение и Web-интерфейс.Мы не станем здесь описывать правила игры
“Монополия”. Наверное, каждый человек в любой
стране, будучи ребенком или подростком, играл
в эту игру. Если вас миновала эта участь, правила
игры можно найти на многих Web-узлах.Программная версия игры работает в режиме моделирования. Один человек на
чинает игру и указывает количество моделируемых игроков, а затем наблюдает за хо
дом игры, отслеживая действия своих соперников и выполняя собственные.
ЧастьIIНачальная фазаВ этой части...Глава 4. Начальная фаза — это не стадия анализа требований
Глава 5. Эволюционное осмысление требований
Глава 6. Описание прецедентов
Глава 7. Другие требования
4Начальная фаза — это не
стадия анализа требованийLe meiux est Vennemi du bien (лучшее - враг хорошего).Вольтер (Voltaire)»■sarВведениеНачальная фаза — это краткий период формирования общего вадения и рамок про¬
екта. Он включает анализ примерно 10% прецедентов, осмысление основных нефунк¬
циональных требований, создание бизнес-плана и подготовку среды разработки, что¬
бы уже на следующей стадии развития можно было приступать к программированию.Что дальше?Итеративная,
эволюционная
и быстрая
разработкао После рассмотрения учебных примеров в данной главе рассматривается стадия
начала, которая не является фазой определения требований каскадного процесса
разработки. В следующей главе рассматриваются отличия эволюционных
требований от требований, формулируемых в рамках каскадного процесса/\КонкретныепримерыНачальнаяфазаЭволюционныетребованияПрецеденты о
82 Часть II. Начальная фаза4.1. Что такое начальная фазаДля большинства проектов необходим небольшой начальный этап, на котором
нужно сформулировать ответы на следующие вопросы.■ Каково ваше ведение проекта?■ Реально ли осуществить задуманное?■ Что лучше: купить или разработать?■ В какую сумму (примерно) обойдется реализация проекта: 10-100 тысяч или
миллионы долларов?■ Стоит ли браться за этот проект?Определив свое видение задачи и приблизительно оценив необходимые затраты,
можно приступать к изучению требований. Однако задачей начальной фазы не является
определение всех требований, составление правдоподобного бюджета или плана реали¬
зации проекта.Это очень важный вопрос, и специалистам со старомодным мышлением в рамках
каскадного процесса необходимо тщательно пересмотреть свое видение данной
стадии, приступая к разработке проекта в рамках UP. Унифицированный процесс
отличается от каскадного. На первой стадии не следует определять все требования
или создавать реалистичные планы. Эти задачи решаются на стадии развития.На этом этапе необходимо лишь осмыслить общие задачи проекта и его реали¬
стичность, а также сформировать объективное мнение о целесообразности продол¬
жения проекта (более глубокое изучение будет выполнено на стадии развития).Большая часть анализа требований приходится на стадию развития, При этом ана¬
лиз требований выполняется параллельно с созданием окончательного кода и его тестиро¬
вания.Поэтому для большинства проектов начальная фаза должна быть относительно
короткой и занимать не более одной-двух недель. На самом деле, если этот этап за¬
нимает более одной недели, значит, начальная фаза была пропущена. На этой стадии
нужно лишь решить, заслуживает ли данный проект серьезных инвестиций (на этапе
его развития), а не выполнять его.В двух словах начальную стадию можно охарактеризовать так.Представишь масштаб продукта, сформировать свое видение и оценить
затраты.Основная проблема этой фазы.Заинтересованные лица должны прийти к соглашению относительно сути
проекта и целесообразности серьезных инвестиций.
Глава 4. Начальная фаза - это не стадия анализа требований 83Полезная аналогияКогда в нефтяной промышленности принимается решение о начале разработки
нового месторождения, выполняются следующие действия.1. Определяется, достаточно ли информации и аргументов для обоснования не¬
обходимости бурения пробной скважины.2. Если да, то проводятся измерения и выполняется бурение пробной скважины.3. Оценивается нефтяной запас и целесообразность затрат на разработку.4. Начинается разработка.Начальная фаза разработки программного продукта соответствует первому этапу
в этой аналогии, когда специалисты еще не знают, каков нефтяной запас в данном
регионе или какой будет стоимость его разработки. Для подобных выводов еще не¬
достаточно информации. Конечно, очень заманчиво сразу ответить на все вопросы
“сколько” и “когда”, не приступая к исследованию проблемы, но нефтяники понима¬
ют, что это нереально.В терминах UP реальное исследование проблемы выполняется на стадии разви¬
тия. Начальная фаза сродни анализу достижимости, на этой стадии требуется при¬
нять решение о целесообразности капиталовложений в бурение пробной скважины.
И только после бурения пробной скважины и исследования нового месторождения
(фазы развития) появляются основания для реалистичных оценок и планов. Так и в
итеративной разработке: на начальной стадии нельзя рассчитывать на построение
обоснованных планов и оценок. В этот период можно оценить лишь масштаб, уро¬
вень необходимых затрат и принять решение о целесообразности дальнейших иссле¬
дований.4.2. Какова длительность начальной фазыИтак, начальная фаза предназначена для формирования общего ведения задач
проекта, выяснения достижимости поставленных целей и принятия решения о це¬
лесообразности дальнейших серьезных исследований на стадии развития. Если ре¬
шение о перспективности и реалистичности проекта принято заранее (например,
на том основании, что команда разработчиков уже успешно участвовала в подобных
проектах), то фаза начала будет особенно краткой. Она может включать лишь ввод¬
ный семинар, на котором обсуждаются начальные требования и планирование пер¬
вой итерации. После этого можно сразу перейти к фазе развития.4.3. Какие артефакты относятся к начальной фазеВ табл. 4.1 приводится список типичных артефактов фазы начала (или первых
шагов фазы развития) с краткими пояснениями. В последующих главах некоторые
из этих артефактов будут рассмотрены подробнее, особенно модель прецедентов.
В контексте итеративной разработки необходимо понимать, что на этой стадии не
стоит выполнять серьезное исследование, все артефакты будут позднее доработаны.
Поэтому на начальной стадии можно вообще обойтись без документирования либо
ограничиться краткими артефактами.
84 Часть II. Начальная фазаНапример, в модели прецедентов (которая будет рассмотрена в последующих гла¬
вах) могут содержаться имена наиболее важных прецедентов и их исполнителей. При
этом лишь 10% этих прецедентов могут быть детализированы (чтобы сформировать
общее видение масштаба проблемы, задач проекта и возможных рисков).Начальная фаза может включать и программирование, т.е. создание прототипов
(особенно относящихся к интерфейсу пользователя), обеспечивающих обоснование
правильности идеи. Это поможет лучше осознать системные требования и выявить
наиболее серьезные технические проблемы.Таблица 4.1. Приблизительный перечень артефактов начальной фазыАртефактПояснениеВидение и финансовые оценки
проектаМодель прецедентовДополнительная спецификацияСловарь терминовПеречень рисков и план управ¬
ления имиПрототипы и обоснование идеи
План итерацииПлан на следующую фазу и план
разработкиНабор инструментовОписываются общие задачи и ограничения, оценивается стоимость
проекта и приводится заключениеОписываются функциональные требования. На начальной стадии
определяются имена большинства всех прецедентов, и примерно
10% из них анализируются более детальноОписываются другие требования, в основном нефункциональные.
На начальной стадии полезно сформулировать основные нефунк¬
циональные требования, которые могут повлиять на выбор архи¬
тектурыСодержит ключевую терминологию по данной предметной области
и словарьОписываются экономические, технические риски, риски, связанные
с организацией планирования и ресурсами, а также методы их пре¬
одоленияПриводятся для лучшего осмысления проекта и оценки технических
идейОписывается, что предстоит делать на первой итерации фазы раз¬
витияПриблизительный план фазы развития, описание средств, челове¬
ческих ресурсов, необходимых навыков и других ресурсовОписание этапов UP и артефактов данного проекта. Напомним, что
в рамках UP набор артефактов определяется для каждого проекта
в отдельностиПеречисленные артефакты создаются на данной стадии не полностью. Они будут
постоянно обновляться и совершенствоваться на последующих итерациях. Приве¬
денные названия артефактов соответствуют терминологии, принятой в специфика¬
ции UP.Не слишком ли много документацииНапомним, что все артефакты являются не обязательными. Выберите только те
из них, которые действительно важны для данного проекта, а на остальные не об¬
ращайте внимания.Поскольку речь идет об эволюционной разработке, на начальной стадии не нужно
создавать полные спецификации. Необходимо лишь разработать базовые документы,
Глава 4. Начальная фаза — это не стадия анализа требований 85которые будут уточняться на стадии развития с учетом обратной связи от предыду¬
щих этапов программирования и тестирования.Заметим, что артефакт — это не документ или диаграмма, а процесс осмысления,
анализа и разработки (с последующей записью результатов во избежание повторения
или забывания). К этому сводится основная идея быстрого или гибкого моделирова¬
ния — главная цель моделирования состоит в улучшении понимания, а не в получе¬
нии надежного документа. Генерал Эйзенхауэр говорил следующее: “При подготовке
к битве я всегда убеждался в бесполезности планов, но планирование — процесс обя¬
зательный” [14, 98].Артефакты предыдущих проектов в рамках UP можно повторно использовать в
последующих. Скорее всего, между проектами будет много общего, в частности ри¬
ски, методы управления проектом, тестирование, артефакты окружения. Во всех
проектах UP артефакты должны иметь одинаковые имена (например, “Перечень рис¬
ков”, “Перечень документов” и т.д.). Это упрощает процесс поиска схожих артефак¬
тов и возможность их повторного использования в новых проектах.4.4. Вы не поняли, что такое
начальная фаза, если...■ Для большинства проектов она занимает более нескольких недель.■ На этом этапе вы стараетесь определить все требования. f■ Надеетесь, что оценки и планы будут реалистичными. ^^■ Занимаетесь определением архитектуры, хотя это надо делать на стадии раз¬
вития.■ Считаете правильной следующую последовательность действий: 1) определение
требований; 2) проектирование архитектуры; 3) реализация.■ У вас отсутствует артефакт “Видение” или коммерческая оценка.■ Имена большинства прецедентов и исполнителей не определены.■ Все прецеденты описываются очень подробно.■ Ни один из прецедентов не описан в деталях. На самом деле, 10-20% преце¬
дентов должны быть подробно описаны, чтобы можно было оценить масштаб
проблемы.4.5. Как использовать UML на начальной стадииЦелью начальной фазы является сбор информации, достаточной для формиро¬
вания общего ведения, принятия решения о достижимости целей проекта и целесо¬
образности серьезных вложений на стадии развития. Следовательно, эта стадия не
предполагает построения большого количества диаграмм UML, за исключением не¬
скольких простых диаграмм прецедентов. На начальной стадии основное внимание
уделяется пониманию масштабов проекта и анализу 10% требований, выражаемых
преимущественно в текстовой форме. На практике большая часть диаграмм UML по¬
является на следующем этапе — стадии развития.
ГлаваЭволюционное осмысление
требованийМы живем в мире, в котором люди не знают, чего они хотят, но готовы пройтисквозь ад, чтобы получить это.Дон Маркус (Don Marquis)Основные задачи■ Обосновать эволюционный процесс осмысления требований.■ Определить модель FURPS+.■ Определить артефакты UP, связанные с требованиями.ВведениеВ этой главе кратко описывается итерационный и эволюционный процесс осмыс¬
ления требований, а также конкретные артефакты UP, связанные с требованиями. Это
позволит обеспечить необходимый базис для перехода к главам, посвященным анализу
требований. Кроме того, здесь кратко иллюстрируются несовершенство процесса ана¬
лиза требований в рамках каскадного процесса разработки, при котором делается по¬
пытка определить так называемую “полную спецификацию” до начала разработки.Что дальше? После знакомства с фазой начала в данной главе рассматриваются вопросы
определения требований и их эволюционного уточнения. Следующая глава
посвящена прецедентам - основному инструменту формулировки требований
в процессе UP и многих других современных методахКонкретныепримерыо /Начальнаяфаза—о—Эволюционные
требования
—•—\Прецеденты—о—Другиетребования О
88 Часть II. Начальная фаза5.1. Определение требованийТребования (requirements) — это возможности или условия, которым должна соот¬
ветствовать система или проект [74].В рамках унифицированного процесса провозглашается ряд идей, к числу кото¬
рых относится управление требованиями. Это не означает необходимости окончатель¬
ного определения и стабилизации требований на первой фазе проекта, как в рамках
каскадного процесса. Наоборот, с учетом постоянно меняющихся требований заинте¬
ресованных лиц предлагается “систематизированный подход к поиску, документиро¬
ванию, организации и отслеживанию изменчивых требований к системе” [112].То есть, к формулировке требований нужно относиться очень ответственно, под¬
ходя к этому вопросу постепенно и грамотно.Основная задача этапа определения требований — найти, обсудить и зафиксиро¬
вать, что действительно требуется от системы в форме, понятной и клиентам и чле¬
нам команды разработчиков.5.2. Определение требований для эволюционного
и каскадного процессов разработкиОбратите внимание на слово “изменчивые” в предыдущем подразделе. В контексте
UP изменение требований считается главным “двигателем” прогресса. Это является
чрезвычайно важным и кардинальным отличием итеративного и эволюционного мыш¬
ления от традиционного подхода, связанного с каскадным процессом разработки.В UP и других эволюционных методах (Scrum, ХР, FDD и др.) написание оконча¬
тельной версии программного кода и его тестирование начинается задолго до окон¬
чательного определения требований. Программирование начинается, когда опреде¬
лены лишь 10-20% наиболее архитектурно значимых и связанных с наибольшими
рисками требований.Как же совместить эволюционное осмысление требований с ранним началом про¬
ектирования и программирования? Об этом речь шла в разделе 2.4, а также пойдет в
разделе 6.21.Внимание!Если вам пришлось участвовать в итеративном проекте на основе так называемо¬
го метода UP, когда в начале проекта до этапа программирования и тестирования
пытаются определить все требования (описать прецеденты и т.д.), то произошло
большое недоразумение. Это не процесс UP и не итеративный проект.В 1960-1970-е годы, когда я начинал свою карьеру разработчика, было распростра¬
нено общее заблуждение о том, что полный анализ требований необходимо выпол¬
нять в начале работы над проектом по созданию системы (предполагался каскадный
процесс разработки). В начале 1980-х годов стало понятно, что так поступать непра¬
вильно. Такой подход привел к краху многих проектов. “Корни заблуждения” уходили
к представлению о том, что программный проект подобен хорошо прогнозируемому
Глава 5. Эволюционное осмысление требований 89процессу промышленного производства. Однако разработка программных систем —
это абсолютно другая область, требования к которой очень быстро изменяются.Напомним известную статистику: примерно 25% требований изменяются в про¬
цессе разработки программной системы. Поэтому любые методы, которые пред¬
полагают полное определение и фиксирование требований в начале разработки,
обречены на неудачу, поскольку базируются на неправильных предположениях, ис¬
ключающих неизбежное изменение требований в процессе разработки.Эту точку зрения подтверждает и исследование причин неудач 1027 программных
проектов [117]. Какие выводы сделаны в этой работе? Оказалось, что максимальный
вклад в неудачное завершение проекта вносит каскадный процесс разработки (под¬
разумевающий детальное предварительное определение требований). В 82% проек¬
тов эта причина оказалась основной. Процитируем заключение этой работы.“...подход, связанный с полным определением требований до того, как они будут удов¬
летворены, более неприемлем.Бизнес-требования изменяются очень быстро. Это значит, что нельзя исходить из
предположения неизменности требований к системе и стремиться задокументировать
их до начала разработки. Недопустимо тратить время на попытки максимального
уточнения требований в начале работы над проектом ”.Еще одно исследование позволяет ответить на следующий важный вопрос: если
все же отталкиваться от предварительного анализа требований в рамках каскадно¬
го процесса, то сколько заранее определенных свойств оказываются действительно
полезными для конечного программного продукта? В работе [75] проанализирова¬
ны тысячи проектов, и результаты анализа весьма красноречивы: 45% таких свойств
никогда не используются, а еще 19% используются очень редко (рис. 5.1). Таким об¬
разом, почти 65% требований, определенных в рамках каскадного процесса разра¬
ботки, не имеют смысла!Результаты этих исследований не означают, что следует приступать к кодирова¬
нию в первый же день проекта, забывая об анализе требований. Существует компро¬
мисс: итеративный и эволюционный анализ требований в сочетании с итеративной
разработкой и активным участием заинтересованных лиц, оцениванием и обратной
связью.Рис. 5.1. Реальное использование свойств, определенных в рамках каскадногопроцесса разработки
90 Часть II. Начальная фаза5.3. Грамотное определение требованийВернемся к цитате, описывающей лучшие примеры управления требованиями в рам¬
ках UP.“.. систематизированный подход к поиску, документированию, организации и отслежи¬
ванию изменчивых требований к системе ”. [112]Помимо слова “изменчивый” отметим также слово “поиск”. Предполагается, что
требования должны постоянно и грамотно корректироваться в процессе описания
прецедентов и специальных семинаров, участниками которых должны быть разра¬
ботчики и пользователи, а также фокус-группы опытных пользователей. Результаты
каждой итерации разработки должны демонстрироваться пользователям для получе¬
ния обратной связи.В рамках UP приветствуется любой метод извлечения требований, который по¬
зволяет получить новые знания и повысить активность пользователей. В рамках про¬
ектов UP применима даже простая практика создания карточек, присущая процессу
экстремальной разработки ХР, если она позволит сделать работу более эффектив¬
ной. Такая практика предполагает постоянное присутствие пользователя-эксперта в
офисе, где выполняется проект. Практика замечательная, но зачастую трудно реали¬
зуемая.5.4. Типы и категории требованийВ рамках UP, согласно модели FURPS+ [63], требования делятся на следующие ка¬
тегории.1■ Функциональные требования — свойства, возможности, безопасность.■ Удобство — человеческий фактор, справочная система, документация.■ Надежность — частота сбоев, возможность восстановления и предсказуемость
поведения.■ Производительность — время отклика, точность, доступность, использование
ресурсов.■ Возможность поддержки — адаптивность, возможность поддержки, соответ¬
ствие международным стандартам, возможность конфигурирования.Символ “+” в названии FURPS+ означает дополнительные (не определяющие) фак¬
торы, к которым относятся следующие.■ Реализация — требования к ресурсам, языки и средства, аппаратное обеспечение.■ Интерфейс — ограничения, накладываемые необходимостью взаимодействия с
внешними системами.1 Существует несколько принципов систематизации требований и перечней атрибутов каче¬
ства. Они опубликованы в книгах и документах организаций, занимающихся вопросами стан¬
дартизации, в том числе в стандарте ISO 9126 (список требований аналогичен модели FURPS+).
Несколько списков требований были разработаны институтом SEI (System Engineering Institute).
Все эти требования можно использовать в проектах UP.
Глава 5. Эволюционное осмысление требований 91■ Операции — управление системой и ее параметры.■ Пакетирование — например, упаковка.■ Юридические вопросы — авторское право и т.п.Категории FURPS+ полезно использовать при формулировке требований, чтобы
не упустить важные аспекты жизнедеятельности системы.Некоторые из этих требований (удобство, надежность, производительность и воз¬
можность поддержки) называются атрибутами качества (quality attributes). Обычно
требования делят на две большие категории: функциональные (относящиеся к пове¬
дению) и нефункциональные (все остальные). Некоторые специалисты не любят такое
обобщенное деление [10], но оно применяется довольно часто.Как будет ясно при изучении вопросов архитектурного анализа, атрибуты каче¬
ства оказывают значительное влияние на архитектуру системы. Например, требова¬
ния высокой надежности и производительности определяют выбор программных и
аппаратных компонентов, а также их конфигурацию.5.5. Как требования связаны с артефактами UPВ UP предусмотрены несколько артефактов, связанных с требованиями. Как и все
артефакты UP, они являются необязательными. К основным из них относятся следу¬
ющие.■ Модель прецедентов (Use-Case Model). Набор типичных сценариев использо¬
вания системы. Эта модель предназначена в основном для определения функци¬
ональных требований или требований, связанных с поведением.■ Дополнительная спецификация (Supplementary Specification). Включает в
основном требования, не определяемые прецедентами. Этот артефакт пред¬
назначен для формулировки нефункциональных требований, например, свя¬
занных с производительностью или лицензированием. Здесь же могут быть
описаны функциональные свойства (feature), не представленные в описании
прецедентов, например, связанные с генерацией отчетов.■ Словарь терминов (glossary). В простейшем случае в этом словаре определяют¬
ся важные термины. Зачастую он также служит словарем данных (data dictionary),
в котором описываются требования, связанные с данными, например, правила
верификации, допустимые значения и т.д. В словаре можно детализировать лю¬
бой элемент: описание атрибута объекта, параметры вызова операции, макет
отчета и т.д.■ Видение (vision). В этом документе подытоживаются высокоуровневые требова¬
ния, освещенные в модели прецедентов и дополнительной спецификации. Это
краткий обзорный документ для быстрого ознакомления с главными идеями
проекта.■ Бизнес-правила (business rule). Обычно бизнес-правила (или правила предмет¬
ной области) описывают требования или политики, выходящие за пределы кон¬
кретного программного проекта. Эти правила работают в определенной пред¬
метной области, и им должны удовлетворять многие приложения. Прекрасным
примером являются государственные нормы налогообложения. Эти правила мо¬
92 Часть II. Начальная фазагут быть детально представлены в дополнительной спецификации. Но посколь¬
ку они применимы не только в данном конкретном проекте, их целесообразно
поместить в главном артефакте, описывающем бизнес-правила и используемом
всеми аналитиками компании. Это облегчит их повторное использование в дру¬
гих проектах.Что такое корректный формат артефактовВ UP все артефакты являются информационными абстракциями. Их можно хра¬
нить на Web-страницах, настенных плакатах или в любом другом виде. Шаблоны та¬
ких артефактов содержатся в интерактивной документации по процессу разработки
RUP, но их придерживаться необязательно.5.6. Имеются ли примеры этих
артефактов в данной книгеЭта книга является введением в ООА/П в рамках итеративного процесса раз¬
работки. Анализ требований не является главной темой этой книги, но изучение
ООА/П без конкретных примеров или вне контекста требований даст неполную
картину. Останется непонятным влияние требований на процесс ООА/П. Поэтому
очень полезно привести хороший пример артефактов UP, связанных с требования¬
ми. Такие примеры можно найти в этой книге (табл. 5.1).Таблица 5.1. Примеры артефактов, связанных с требованиямиАртефакт, связанный
с требованиямиГде находится примерКомментарийМодель прецедентовДополнительная специфи¬
кация, словарь терминов,
видение и бизнес-правилаНачальная: глава 6
Детализированная: глава 30Конкретные примеры: глава 7Прецеденты часто используются в UP и
в качестве отправной точки для ООА/П,
поэтому они детально описываются в
начальных главах книгиЭти примеры приводятся для цель¬
ности изложения, но их можно про¬
пустить, поскольку они напрямую не
относятся к тематике ООА/П5.7. Дополнительные ресурсыСсылки на литературу, связанную с формулировкой требований в процессе опи¬
сания прецедентов, приводятся в следующей главе. Отправной точкой для изучения
требований в процессе описания прецедентов можно считать книгу [37].Требования и многие другие вопросы, связанные с разработкой программных про¬
дуктов, обсуждаются на Web-узле www.swebok.org под флагом организации SWEBOK
(Software Engineering Body of Knowledge).Институт SEI (www.sei.cmu.edu) разработал несколько предложений по стандар¬
тизации требований к качеству. Стандарты ISO 9126, IEEE Std 830 и IEEE Std 1061,
относящиеся к требованиям и атрибутам качества, приводятся на различных Web-
узлах.
Глава 5. Эволюционное осмысление требований 93Однако книги, посвященные анализу требований, нужно изучать критически,
даже те из них, где речь идет об описании прецедентов, итеративной разработке и
требованиях в рамках UP. Это объясняется следующей причиной.Большинство авторов книг тяготеют к последовательному жизненному циклу и
определению требований до начала фазы проектирования и реализации. Это может
быть связано с тем, что авторы книг имели опыт разработки систем в последователь¬
ном жизненном цикле и привыкли вырабатывать требования до начала проектиро¬
вания. И даже если в подобных книгах упоминается итеративная разработка, то за¬
частую это просто дань моде.Все рекомендации типа “старайтесь сначала определить большинство требова¬
ний, а затем приступайте к проектированию и реализации” не имеют ничего общего
с итеративной разработкой и UP.
ГлаваОписание прецедентовНеобходимый первый шаг для достижения заветной цели — понять, чего же вы хотите.Бен Штайн (Ben Stein)Основные задачи■ Определить и описать прецеденты.■ Использовать сжатый, свободный и развернутый форматы описания
идеальных прецедентов.■ Применить тесты для выявления подходящих прецедентов.■ Связать работу над прецедентами с итеративной разработкой.ВведениеПрецеденты — это повествовательные истории об использовании системы, кото¬
рые широко используются для осмысления и формулировки требований. Они оказы¬
вают влияние на множество аспектов проекта, включая ООА/П. В этой главе изуча¬
ются основные понятия, связанные с описанием прецедентов, и приводятся примеры
прецедентов и диаграмм UML. Здесь основное внимание уделяется собственно во¬
просам анализа, а не обозначениям UML. Построить диаграмму прецедентов очень
просто, а их описание может занять несколько недель, или даже больше.
96 Часть II. Начальная фазаЧто дальше? После рассмотрения требований в данной главе анализируются прецеденты,
определяющие функциональные требования. В следующей главе
рассматриваются другие требования, определяемые в рамках UP, в том числе
дополнительная спецификация для нефункциональных требований
/ \Начальная Эволюционные п Другие Требованияфаза требования рецеденты требования итерации 1о о • о оНа рис. 6.1 показана взаимосвязь артефактов UP, среди которых особо выделено
текстовое описание прецедентов. Входной информацией для такого описания служат
диаграммы прецедентов и высокоуровневые цели системы. В свою очередь, преце¬
денты оказывают влияние на множество артефактов анализа, проектирования, реа¬
лизации, управления проектом и тестирования.6.1. ПримерПрецеденты — это рассказы об использовании системы в процессе решения по¬
ставленных задач. Вот пример сжатого формата описания прецедента.Обработка продажи (process sale). Покупатель подходит к кассе с выбранны¬
ми товарами. Кассир с помощью POS-системы регистрирует каждый товар.
Система отображает информацию о каждом наименовании товара и вычисляет
общую сумму. Покупатель вводит требуемую информацию; система ее верифи¬
цирует и регистрирует. Система выполняет инвентаризацию. Покупатель по¬
лучает товарный чек и покидает магазин с покупками.Еще раз подчеркнем, что прецеденты — это не диаграммы, а текстовые описания.
Диаграммы имеют лишь второстепенное значение, и непонимание этого является
типичной ошибкой новичков.Зачастую прецеденты нужно продумывать гораздо детальнее. Но основная идея
состоит в исследовании и формулировке функциональных требований путем написа¬
ния историй “из жизни системы”. Эти истории помогают сформулировать различные
задачи и представляют собой сценарии использования системы.1 На первый взгляд,
описать прецеденты не сложно, хотя зачастую достаточно трудно определить, что
требуется от системы и описать это на нужном уровне детализации.6.2. Некоторые определенияСначала введем некоторые неформальные определения. Исполнителем (actor) бу¬
дем называть сущность, обладающую поведением, например, человека (идентифици¬
руемого по роли, к примеру, кассира), компьютерную систему или организацию.Сценарий (scenario) — это специальная последовательность действий или взаимо¬
действий между исполнителями и системой. Его иногда также называют экземпляром1 Термин “прецедент” (use case) появился в Швеции и в переводе означал “случай ис¬
пользования” (usage case).
Глава 6. Описание прецедентов 97прецедента (use case instance). Это один конкретный сценарий использования систе¬
мы либо один проход прецедента, например, сценарий успешной покупки товаров за
наличный расчет либо сценарий неудачного завершения покупки из-за прерванной
транзакции по обработке данных кредитной карточки.Бизнес-модели¬рованиеПример взаимосвязи артефактов UPМодель предметной областиSale1 1..*SalesLineltemquantitydateОбъекты, атрибуты,
ассоциацииМодель прецедентовОпреде¬лениетребо¬ванийИмена
прецедентов
-►Оформлениепродажи1. Покупатель
подходит...2.Кассир вводит
идентификатор
товара.3...Временные
рамки, цели,
исполнители, Видение
свойстваДиаграмма прецедентовТермины,атрибуты,валидация Словарь
—ЦОперация:enterltem(...)Постусловия:Дополнительная
спецификация
ъ,^Описания операций
Определение требованийСистемные диаграммыпоследовательностей У iMwvDan™,
 атрибуты качестваНефункциональные
требования,Модель проектирования:Register:ProductCatalog: SaleПроекти¬рованиеenterltem
(itemID, quantity)
• ►spec = getProductSpec( itemID )addLineItem( spec, quantity )Puc. 6.1. Взаимосвязь артефактов UP4 3ak. 3357
98 Часть II. Начальная фазаНеформально, прецедент (use case) — это набор взаимосвязанных успешных и не¬
удачных сценариев, описывающий использование системы исполнителем для реше¬
ния одной из задач. Рассмотрим свободный формат прецедента, включающего неко¬
торые альтернативные сценарии.Возврат товараОсновной успешный сценарий. Покупатель подходит к кассе с товарами, подлежащи¬
ми возврату. Кассир использует POS-систему для регистрации каждого возвращае¬
мого товара...Альтернативные сценарии. Если в авторизации кредитной карточки отказано, кас¬
сир информирует об этом покупателя и предлагает ему другой способ оплаты по¬
купки.Если идентификатор товара в системе не обнаружен, система уведомляет об этом
кассира и предлагает ему вручную ввести идентификационный код (возможно,
штрихкод поврежден и его сложно считать).Если у системы возникают сложности при коммуникации с внешней системой вы¬
числения налога...Несколько другое, но подобное определение прецедента приводится в RUP.Прецедент— это набор сценариев использования, в котором каждый экземпляр
сценария представляет собой последовательность действий, выполняемых систе¬
мой для достижения ощутимого для конкретного исполнителя результата [112].6.3. Прецеденты и модель прецедентовВ контексте UP модель прецедентов (Use-Case Model) относится к дисциплине
“Требования”. Действительно, требования — это весь набор прецедентов, т.е. модель
функционирования системы и ее окружения.Описания прецедентов — это текстовые документы, а не диаграммы. Моделирование
прецедентов — это процесс написания текста, а не рисования.Модель прецедентов — это не единственный артефакт анализа требований в рам¬
ках UP. К данной стадии относятся также дополнительная спецификация, словарь
терминов, видение системы и описание бизнес-правил. Все эти документы являются
полезным на этапе анализа требований, но не относятся к тематике данной главы.Модель прецедентов может включать диаграммы прецедентов на UML, отражаю¬
щие имена прецедентов и исполнителей, а также их взаимоотношения. Диаграммы
прецедентов позволяют оценить рамки системы и ее окружение, а также обеспечива¬
ют простой способ перечисления имен прецедентов.
Глава 6. Описание прецедентов 99Прецеденты не имеют отношения к объектно-ориентированной разработке и не
относятся к ООА. Однако это не проблема. Прецеденты используются настолько ши¬
роко, что их полезность очевидна. Можно утверждать, что прецеденты обеспечива¬
ют важнейшую начальную информацию для классического ООА/П.6.4. Зачем нужны описания прецедентовУ потребителей и конечных пользователей есть свои задачи, решение которых
должна обеспечить компьютерная система. Эти задачи могут варьироваться от реги¬
страции торговых операций до оценивания объемов добычи нефти из перспектив¬
ных месторождений. Существует несколько способов выделения этих задач или си¬
стемных требований. Наилучшие из них достаточно просты и доступны, поскольку
это облегчает участие конечных пользователей в определении требований к системе.
А участие в этом процессе потребителей снижает риск провала проекта. Эти рассуж¬
дения могут показаться очевидными, но они очень важны. Ученые могут придумы¬
вать сложные методы анализа, освоение которых может привести в состояние комы
любого специалиста по предметной области. Одной из главных причин провала
проектов по разработке программных систем является недостаточное привлечение
пользователей к процессу разработки [84]. Поэтому важность участия пользователей
в процессе анализа системы трудно переоценить.Прецеденты — это механизм упрощения этапа формулировки требований для всех
заинтересованных лиц.2Важной особенностью описания прецедентов является их ориентация на цели и
задачи пользователя. В процессе описания необходимо задавать вопросы: “Кто явля¬
ется пользователем системы? Каковы типичные сценарии использования системы?
Каковы цели и задачи пользователей?”. Такой взгляд на систему гораздо больше ори¬
ентирован на пользователя, чем обычный список системных требований.Зачастую прецеденты нужно продумывать гораздо детальнее. Но основная идея
состоит в исследовании и формулировке функциональных требований путем написа¬
ния историй “из жизни системы”. Эти истории помогают сформулировать различные
задачи и представляют собой сценарии использования системы. На первый взгляд,
описать прецеденты не сложно, хотя зачастую достаточно трудно определить, что
требуется от системы и описать это на нужном уровне детализации.О прецедентах написано достаточно много. Но все равно существует опасность, что
умные творческие люди могут слишком усложнить изначально простую идею. Зачастую
начинающие специалисты по описанию прецедентов слишком увлекаются созданием
диаграмм прецедентов, описанием их взаимосвязей, составлением пакетов прецеден¬
тов, рассмотрением необязательных атрибутов и т.д., а не написанием историй.Сила механизма прецедентов состоит в возможности масштабировать уровень
сложности и формальности описания в зависимости от реальных потребностей.2 См. раздел 6.19.
100 Часть II. Начальная фаза6.5. Прецеденты и функциональные требованияПрецеденты — это требования. В основном, это функциональные требования, ука¬
зывающие на то, что должна делать система. В контексте типов требований, опреде¬
ляемых моделью FURPS+, основное внимание уделяется функциональным требовани¬
ям. Однако остальные типы требований тоже могут быть связаны с прецедентами. В
рамках UP и большинства других современных методов прецеденты являются основ¬
ным механизмом, рекомендуемым для их определения и исследования.Схожая точка зрения, определяющая прецедент как пожелание или соглашение
относительно поведения системы, приводится в [37].Итак, прецеденты — это требования (хотя и не все требования). Некоторые счи¬
тают требованиями только список функций и свойств типа “система должна...”. На
самом деле это не так. Ключевая идея использования прецедентов как раз и состо¬
ит (обычно) в снижении роли списка требований в старом понимании этого слова.
Теперь в качестве функциональных требований выступают сами прецеденты. Более
подробно этот вопрос рассматривается ниже.6.6. Три типа исполнителейИсполнитель (actor) — это сущность, обладающая поведением. К числу исполни¬
телей может относиться и сама рассматриваемая система, если она вызывает службы
других систем.3 В прецеденте могут участвовать основные и вспомогательные (второ¬
степенные) исполнители. Исполнителями являются не только люди, но и организа¬
ции, машины и программы. Существует три типа внешних по отношению к разраба¬
тываемой системе исполнителей.■ Основной исполнитель (primary actor) — его задачи выполняются с использо¬
ванием системы. Примером основного исполнителя является кассир.• Зачем его идентифицировать? Чтобы определить цели пользователя, на осно¬
ве которых формулируются прецеденты.■ Вспомогательный исполнитель (supporting actor) — обслуживает систему (на¬
пример, предоставляет информацию). Примером вспомогательного исполните¬
ля является служба авторизации платежей.• Зачем его идентифицировать? Чтобы определить внешние интерфейсы и
протоколы.■ Закулисный исполнитель (offstage actor) — заинтересован в реализации пре¬
цедента, но не является основным или вспомогательным исполнителем.
Примером закулисного исполнителя является налоговая служба.• Зачем его идентифицировать? Чтобы удостовериться, что все интересы опреде¬
лены и удовлетворены. Интересы закулисных исполнителей обычно не очевид¬
ны и их легко упустить из виду, если не идентифицировать их в явной форме.3 Это модифицированное и усовершенствованное определение исполнителя, основан¬
ное на определении, принятом в более ранних версиях UML и UP [36]. В прежней версии
этого определения система никогда не включалась в число исполнителей. Все сущности,
включая разрабатываемую систему, могут играть различные роли.
Глава 6. Описание прецедентов 1016.7. Основные форматы прецедентовПрецеденты описываются в различных форматах. Выделяют несколько уровней
формализации описания прецедентов.■ Сжатый — аннотация в виде одного абзаца. Обычно она описывает только глав¬
ный успешный сценарий. Пример такого описания приведен выше для преце¬
дента Оформление продажи (Process Sale).• Этот формат применяется на стадии анализа требований для быстрого опре¬
деления задач и масштабов системы. Для подобного описания требуется не¬
сколько минут.■ Свободный — неформальный стиль описания. Описание прецедента занимает не¬
сколько абзацев и охватывает различные сценарии. Примером такого описания
является рассмотренный выше прецедент Возврат товара.• Этот формат применяют в тех же случаях, что и предыдущий.■ Развернутый — наиболее подробный стиль описания. При таком подходе деталь¬
но описываются все шаги и варианты развития сценария, а также предусловия
и результаты.• Этот формат применяют после определения основных задач системы, когда
множество прецедентов уже описаны в сжатом формате. В развернутом форма¬
те представляют порядка 10% наиболее важных для приложения прецедентов.Рассмотрим пример развернутого описания прецедента для системы NextGen.6.8. Пример развернутого описания
прецедента Оформление продажиРазвернутые описания прецедентов структурированы и содержат большое коли¬
чество деталей.При итеративной и эволюционной разработке на стадии анализа требований в
этом формате представляют порядка 10% жизненно важных прецедентов. Обычно
такое описание формируется на первом семинаре по анализу требований, после чего
сразу же начинается реализация этих прецедентов в системе.Для развернутого описания прецедентов существуют различные шаблоны форма¬
тирования. Однако, начиная с 1990-х годов прошлого столетия, чаще всего исполь¬
зуется шаблон, созданный автором популярной книги по моделированию на основе
прецедентов Алистером Кокбурном (Alistair Cockburn) и приведенный на Web-узле
alistair.cockburn.us. Этот стиль проиллюстрирован в следующем примере.Сначала рассмотрим сам шаблон.Раздел описания прецедентаКомментарийНазвание прецедентаОсмысленное название, определяющее основную функциюпрецедентаРамкиРазрабатываемая системаУровень“Задача, определенная пользователем” или “вспомогатель¬ная функция”
102 Часть II. Начальная фазаОкончание таблицыРаздел описания прецедентаКомментарийОсновной исполнительЛицо, инициирующее и реализующее работу сценарияЗаинтересованные лица и их требованияКто заинтересован в реализации этого сценария и чего он хочетПредусловияКакие условия должны быть выполнены для успешной реа¬
лизации данного сценарияРезультатЧто гарантируется при успешном завершении сценарияОсновной успешный сценарийТипичный ход событий, который приводит к успешному за¬
вершению сценарияРасширенияАльтернативные успешные или неуспешные сценарииСпециальные требованияНефункциональные требования, связанные с данным пре¬
цедентомСписок технологий и типов данныхМетоды ввода-вывода и форматы данныхЧастота использованияОпределяет сроки реализации и тестированияОткрытые вопросыВопросы, не решаемые реализацией данного прецедентаА теперь приведем пример описания прецедента на основе этого шаблона.Обратите внимание, что данный прецедент относится к системе, рассматриваемой в ка¬
честве основного примера в данной книге. Он отражает множество стандартных аспек¬
тов и вопросов.В данном примере приводится множество подробностей (возможно, излишних,
на первый взгляд). Однако это описание прецедента для реальной системы, охва¬
тывающее сложные требования и различные варианты развития сценария.Прецедент П1. Оформление продажиРамки. Приложение автоматизации торговли NextGen.Уровень. Задача, определенная пользователем.Основной исполнитель. Кассир.Заинтересованные лица и их требования.- Кассир. Хочет точно и быстро ввести данные, не допуская ошибок в платеже, поскольку не¬
достача вычитается из его зарплаты.- Продавец. Хочет получить свои комиссионные от продажи.- Покупатель. Хочет купить товары и быстро оформить покупку. Хочет получить подтверждение
факта покупки для возможного возврата товара.- Компания. Хочет аккуратно записать транзакцию и удовлетворить интересы покупателя.
Хочет удостовериться, что служба авторизации платежей зафиксировала все данные о плате¬
же. Заинтересована в обеспечении устойчивости к сбоям; хочет продолжать регистрировать
продажи, даже если серверные компоненты (например, служба удаленной проверки креди¬
тоспособности) недоступны. Хочет автоматически обновлять бухгалтерскую документацию и
вести складской учет.- Менеджер. Хочет быстро выполнять необходимые операции и легко решать задачи кассира.
Глава 6. Описание прецедентов 103- Государственные налоговые службы. Хотят получать налог от каждой продажи. Таких служб
может быть несколько, в том числе национальная и местная.- Служба авторизации платежей. Хочет получать цифровые запросы на авторизацию в кор¬
ректном формате и отвечать на эти запросы.Предусловия. Кассир идентифицирован и аутентифицирован.Результаты (Постусловия). Данные о продаже сохранены. Налоги корректно вычислены.
Бухгалтерские и складские данные обновлены. Комиссионные начислены. Чек сгенерирован.
Авторизация платежа выполнена.Основной успешный сценарий (или основной процесс)1. Покупатель подходит к кассовому аппарату POS-системы с выбранными товарами.2. Кассир открывает новую продажу.3. Кассир вводит идентификатор товара.4. Система записывает наименование товара и выдает его описание, цену и общую стоимость.
Цена вычисляется на основе набора правил.Кассир повторяет действия, описанные в пп. 3-4, для каждого наименования товара.5. Система вычисляет общую стоимость покупки с налогом.6. Кассир сообщает покупателю общую стоимость и предлагает оплатить покупку.7. Покупатель оплачивает покупку, система обрабатывает платеж.8. Система регистрирует продажу и отправляет информацию о ней внешней бухгалтерской си¬
стеме (для обновления бухгалтерских документов и начисления комиссионных) и системе
складского учета (для обновления данных).9. Система выдает товарный чек.10.Покупатель покидает магазин с чеком и товарами (если он что-то купил).Расширения (или альтернативные потоки)*а. Каждый раз при попытке менеджера отменить операцию выполняются следующие дей¬
ствия.1. Система переходит в режим обслуживания менеджера.2. Менеджер или кассир выполняют одну операцию в режиме обслуживания менеджера,
т.е. изменяют баланс, завершают продажу и т.п.3. Система возвращается в режим обслуживания кассира.*б. При каждом выходе системы из строя.Для ввода системы в строй и корректной обработки платежа нужно обеспечить восстанов¬
ление всех транзакций и событий с любого шага сценария.1. Кассир перезапускает систему, регистрируется и предлагает восстановить предыдущее
состояние.2. Система восстанавливает предыдущее состояние.2а. Система определяет аномалию, повлекшую сбой.1. Система уведомляет об ошибке кассира, регистрирует ошибку и переходит в на¬
чальное состояние.2. Кассир начинает новую продажу.1а. Покупатель или менеджер хотят досрочно прервать продажу.1. Кассир завершает операцию.
104 Часть II. Начальная фаза2. Система отображает состояние завершенной операции с общей стоимостью покупки.2а. Информация о продаже не найдена.1. Система сигнализирует об ошибке кассира.2. Кассир начинает новую операцию продажи и вводит все необходимые элементы.3. Кассир продолжает обслуживание клиента (вводит новые товары и обрабатывает платеж).
2а. Покупатель сообщает кассиру о льготах.1. Кассир проверяет наличие льгот и вводит шифр льготного покупателя.2. Система записывает статус покупателя, который будет использоваться при начислении
налоговых платежей.За. Неправильный идентификатор (идентификатор не найден в системе).1. Система уведомляет об ошибке и отменяет ввод данного наименования товара.2. Кассир реагирует на ошибку.2а. Существует числовой идентификатор товара.1. Кассир вручную вводит идентификатор товара.2. Система отображает описание товара и стоимость.2а. Неправильный идентификатор. Система сигнализирует об ошибке. Кассир
делает вторую попытку.26. Не существует числового идентификатора, но на упаковке указана цена товара.1. Кассир просит менеджера ввести информацию о покупке данного товара.2. Менеджер выполняет операцию.3. Кассир вводит стоимость товара.2в. Кассир обращается за справкой об идентификаторе товара и его стоимости к спра¬
вочной системе.2г. Кассир запрашивает информацию об идентификаторе и цене товара по телефону и
вручную вводит эти данные.36. В рамках одной категории существует несколько различных наименований товара и иден¬
тифицировать конкретное наименование не нужно (например, 5 пакетов леденцов).1. Кассир может ввести идентификатор категории товара и количество единиц.Зв. Требуется вручную ввести категорию и цену товара (например, при покупке цветов).1. Кассир вручную вводит категорию товара и цену.3-ба. Покупатель просит кассира отменить покупку одного из товаров.1. Кассир вводит идентификатор товара для удаления из продажи.2. Система отображает обновленную промежуточную стоимость.3-66. Покупатель просит кассира отменить продажу.1. Кассир отменяет продажу.3-бв. Кассир приостанавливает продажу.1. Система записывает сведения о продаже таким образом, чтобы они были доступны с лю¬
бого терминала POS-системы.2. Система печатает чек о приостановленной продаже.4а. Сгенерированная системой цена товара не устраивает покупателя (например, у него есть
дисконтная карта и он рассчитывает на более низкую цену товара).1. Кассир обращается к менеджеру.
Глава 6. Описание прецедентов 1052. Менеджер прерывает операцию.3. Кассир вводит команду об изменении цены.4. Система вычисляет новую цену.5а. Система выявляет сбой при взаимодействии с внешней службой вычисления налога.1. Система перезапускает службу с данного узла POS-системы и продолжает работу.1а. Система определяет, что служба не перезапускается.1. Система сигнализирует об ошибке.2. Кассир может вручную вычислить и ввести сумму налога либо отменить продажу.56. Покупатель сообщает о положенной ему скидке (например, для сотрудников данного
предприятия или постоянных покупателей).1. Кассир отправляет запрос на скидку.2. Кассир вводит идентификационные данные покупателя.3. Система представляет сумму скидки, вычисленную на основе дисконтных правил.5в. Покупатель сообщает об открытом в данном магазине кредите на фиксированную сумму
и просит оформить продажу с его помощью.1. Кассир отправляет запрос на оформление платежа с использованием открытого кредита.2. Кассир вводит идентификационную информацию о покупателе.3. Система снижает стоимость покупки (вплоть до 0) и уменьшает оставшуюся сумму кре¬
дита.6а. Покупатель сообщает, что хочет оплатить покупку наличными, но у него недостаточно денег.
1а. Покупатель использует альтернативный способ платежа.16. Покупатель просит кассира отменить продажу. Кассир отменяет продажу в системе.7а. Оплата наличными.1. Кассир вводит предложенную покупателем сумму.2. Система вычисляет положенную сдачу и открывает кассу с наличностью.3. Кассир складывает поученные деньги и выдает сдачу покупателю.4. Система регистрирует платеж наличными.76. Оплата по кредитной карточке.1. Покупатель вводит информацию о своей кредитной карточке.2. Система отображает необходимые данные.3. Кассир вводит подтверждение.За. Кассир отменяет платеж.1. Система возвращается в режим ввода товара.4. Система отправляет запрос на авторизацию платежа внешней системе службы авториза¬
ции платежей и запрашивает подтверждение платежа.4а. Система определяет сбой при взаимодействии с внешней системой.1. Система сигнализирует об ошибке кассиру.2. Кассир просит покупателя изменить тип платежа.5. Система получает информацию о подтверждении платежа и сообщает об этом кассиру.5а. Система получает информацию об отказе в выполнении платежа.1. Система сообщает об отказе кассиру.2. Кассир просит покупателя изменить тип платежа.
106 Часть II. Начальная фаза56. Превышен интервал ожидания.1. Система сообщает об этом кассиру.2. Кассир выполняет вторую попытку или просит покупателя изменить тип платежа.6. Система регистрирует платеж по кредитной карточке, включая информацию о подтверж¬
дении платежа.7. Система предоставляет механизм ввода подписи для платежа по кредитной карточке.8. Кассир просит покупателя подписать чек на оплату по кредитной карточке. Покупатель
подписывает чек.9. Кассир помещает подписанный чек в кассу.7в. Оплата чеком.7г. Оплата по дебитной карточке.7д. Кассир отменяет платеж.1. Система возвращается в режим ввода информации о товарах.7е. Покупатель предоставляет купоны.1. До обработки платежа кассир вводит информацию о каждом купоне, в соответствии с ко¬
торой система снижает стоимость покупки. Система регистрирует предъявленный купон
для нужд бухгалтерии.1а. Купон действует не для всех выбранных товаров.1. Система сигнализирует об ошибке кассиру.9а. Генерация чека.1. Система выводит формы и чеки для каждого товара.96. Покупатель просит выдать ему подарочный чек (без указания цены).1. Кассир вводит запрос на подарочный чек, и система выдает его.9в. В принтере закончилась бумага.1. Система сообщает о проблеме.2. Кассир добавляет бумагу.3. Кассир запрашивает новый чек.Специальные требования- Сенсорный экран с интерфейсом пользователя для большого плоского монитора. Текст дол¬
жен быть виден с расстояния один метр.- Отклик службы авторизации в 90% случаев приходит в течение 30 секунд.- Каким-то образом нужно обеспечить робастное восстановление информации в случае сбоя
при доступе к удаленным службам, таким как система складского учета.- Возможность локализации (представления на различных языках) отображаемого текста.- Возможность добавления новых бизнес-правил на шагах 3 и 7 в процессе функционирования
системы.Список технологий и типов данных*а. Менеджер прерывает продажу путем ввода специальной карточки или указания кода
авторизации с клавиатуры.За. Идентификатор товара считывается со штрихкода (при наличии последнего) лазерным
сканером или вводится с клавиатуры.
Глава 6. Описание прецедентов 10736. Идентификатор товара может определяться по схемам кодирования UPC, EAN, JAN
или SKU.7а. Информация об открытом кредите вводится с помощью считывающего устройства или с
клавиатуры.76. Подпись при оплате чеком ставится на бумажном документе. Однако ожидается, что в тече¬
ние двух лет большинство покупателей будут требовать цифровые устройства считывания
подписи.Частота использования: почти постоянно.Открытые вопросы- Изучить законодательство по налогообложению.- Исследовать вопрос восстановления удаленных служб.- Какая настройка потребуется для различных типов магазинов.- Должен ли кассир снимать кассу при выходе из системы.- Может ли пользователь сам использовать устройство считывания данных с карточки или это
должен делать кассир.Этот прецедент, скорее, является иллюстративным, чем исчерпывающим (хотя
и основывается на реальных требованиях к POS-системе). Тем не менее, он описан
достаточно подробно и позволяет составить реалистичное представление о развер¬
нутом формате описания прецедентов и их сложности. Этот пример может служить
моделью для многих других прецедентов.6.9. ПоясненияВводные элементы
Рамки* В этом разделе определяются границы разрабатываемой системы. Обычно преце¬
дент описывает использование одного программного (или программно-аппаратного)
продукта. В этом случае прецедент называется системным (system use case). В более
общем случае он описывает выполнение некоторой операции на уровне предприятия
с использованием нескольких программных систем. Однако подобные прецеденты в
данной книге не рассматриваются.УровеньОбычно прецеденты разделяют на пользовательские и вспомогательные. Пользо¬
вательский прецедент (user-goal level use case) описывает сценарии достижения цели
главного исполнителя. Вспомогательный прецедент (subfunction-level use case) описыва¬
ет вспомогательные действия, необходимые для достижения цели исполнителя.Главный исполнительОсновной исполнитель, вызывающий системные службы для достижения цели.
108 Часть II. Начальная фазаЗаинтересованные лица и их потребностиЭтот список играет более важную роль, чем это кажется на первый взгляд. С его
помощью можно понять, что должна делать система. Приведем цитату.“Система реализует соглашение между заинтересованными лицами. Поведение
системы описывается с помощью прецедентов... Прецедент, как соглашение о
поведении, включает все возможные аспекты поведения, связанные с удовлет¬
ворением запросов заинтересованных лиц” [37].Эта цитата дает ответ на вопрос, что нужно описывать в прецеденте. Там нужно
описывать все, что служит удовлетворению запросов заинтересованных лиц. Кроме
того, начиная описание прецедента с перечня заинтересованных лиц и их интересов,
можно более точно определить функции системы. Например, можно ли было вклю¬
чить в перечень ее функций обработку комиссионных продавца, если до этого не
определить его интересы? На самом деле автор книги в процессе начального анализа
упустил из виду этот аспект и вспомнил о нем только после составления списка заин¬
тересованных лиц. Этот пример еще раз подтверждает важность составления списка.Заинтересованные лица и их потребности- Кассир. Хочет точно и быстро ввести данные, не допуская ошибок в платеже, поскольку не¬
достача вычитается из его зарплаты.- Продавец. Хочет получить свои комиссионные от продажи.Предусловия и постусловияЭтот раздел можно опустить, если предусловия и постусловия являются очевид¬
ными. Не следует перегружать описание требований излишней информацией.Предусловия (preconditions) — это перечень предпосылок, которые всегда должны
выполняться до начала сценария прецедента. Предусловия не проверяются при реа¬
лизации прецедента. То есть, это условия, которые считаются истинными. Обычно в
качестве предусловия выступает успешный результат выполнения другого сценария,
например, загрузки или авторизации. Заметим, что в качестве предусловий перечис¬
ляются не все возможные истинные условия. Например, никто не упоминает в пред¬
условиях наличие напряжения в электросети. Предусловия — это те предпосылки, на
выполнение которых разработчик прецедента хочет обратить особое внимание.Результаты или постусловия (postconditions). Описывают, какие условия обяза¬
тельно должны выполняться в случае успешного завершения сценария. Эти результа¬
ты должны удовлетворять интересам всех заинтересованных лиц.Предусловия. Кассир идентифицирован и аутентифицирован.Результаты (постусловия). Данные о продаже сохранены. Налоги корректно вычислены.
Бухгалтерские и складские данные обновлены. Комиссионные начислены. Чек сгенерирован.Основной успешный сценарий (или основной процесс)Это пункт можно также назвать “сценарием успеха” или, более прозаично, основ¬
ным процессом. В нем описывается типичная последовательность действий, приво¬
Глава 6. Описание прецедентов 109дящая к успешному завершению сценария и удовлетворяющая потребности всех за¬
интересованных лиц. Заметим, что чаще всего в этом разделе нет никаких условий
или ветвей. И хотя вводить какие-либо условия не запрещается, их обычно выносят
в раздел расширений.СоветВыносите все условия или возможные варианты развития событий в раздел рас¬
ширений.В разделе основного сценария описываются три вида действий.1. Взаимодействие между исполнителями.42. Верификация (обычно со стороны системы).3. Изменение состояния системы (например, запись или модификация некоторых
сущностей).Первый шаг прецедента не всегда подпадает под эту классификацию. Он служит
триггером события начала сценария.Имена исполнителей принято начинать с заглавной буквы для облегчения их
идентификации. Повторяющиеся действия выделяются курсивом.Основной успешный сценарий1. Покупатель подходит к кассовому аппарату POS-системы с выбранными товарами.2. Кассир открывает новую продажу.3. Кассир вводит идентификатор товара.4....Кассир повторяет действия, описанные в пп. 3-4, для каждого наименования товара.5....Расширения (или альтернативные потоки)Этот раздел очень важен. Здесь указываются все остальные сценарии или ветви,
приводящие к успешному или неудачному завершению прецедента. Обратите внима¬
ние, что этот раздел больше и сложнее предыдущего. Так и должно быть.При описании прецедента основной успешный сценарий и его расширения долж¬
ны охватывать почти все интересы заинтересованных лиц. Некоторые интересы
лучше выразить в виде нефункциональных требований в дополнительной специфи¬
кации, а не в описании прецедента.Расширения — это ответвления от основного сценария. Например, при реализа¬
ции п. 3 основного сценария идентификатор товара может оказаться неправильным
либо по причине некорректного ввода, либо из-за его отсутствия в системе. В рас¬
ширении За сначала определяются условия, а затем реакция на них. Расширения для4 Заметим, что описываемая система сама является исполнителем, если рассматривает¬
ся аспект ее взаимодействия с другими системами.
110 Часть II. Начальная фазакаждого пункта основного сценария обозначаются последовательностью, состоящей
из номера этого пункта и буквы алфавита. Например, расширения для п. 3 будут ну¬
мероваться За, 36 и т.д.РасширенияЗа. Неправильный идентификатор.1. Система уведомляет об ошибке и отменяет ввод данного наименования товара.36. В рамках одной категории существует несколько различных наименований товараи идентифицировать конкретное наименование не нужно (например, 5 пакетов леденцов).1. Кассир может вести идентификатор категории товара и количество единиц.Описание расширения состоит из двух частей: условия и способа его обработки.Совет. Описывайте условия как факты, выявляемые системой или исполнителем.
Сравните следующие два пункта.5а. Система выявляет сбой при коммуникации с внешней службой вычисления налога.5а. Внешняя система вычисления суммы налога не работает.Первый пример предпочтительнее, поскольку в нем описан факт, который может
быть выявлен системой.Способ обработки возникшего условия можно описать в одном или нескольких
пунктах (как приведено ниже).3-ба. Покупатель просит кассира отменить покупку одного из товаров.1. Кассир вводит идентификатор товара для удаления из продажи.2. Система отображает обновленную промежуточную стоимость.По окончании обработки расширения по умолчанию выполняется возврат к
основному сценарию, если в расширении не предусмотрен другой ход событий (на¬
пример, завершение работы системы).Иногда некоторые расширения оказываются очень сложными, например платеж
по кредитной карточке. В этом случае расширение можно выделить в отдельный пре¬
цедент.Вот пример, демонстрирующий описание сбоя при реализации расширения.76. Оплата по кредитной карточке.1. Покупатель вводит информацию о своей кредитной карточке.2. Система отображает необходимые данные.3. Кассир вводит подтверждение.За. Кассир отменяет платеж.1. Система возвращается в режим ввода товара.4. Система отправляет запрос на авторизацию платежа внешней системе службы автори¬
зации платежей и запрашивает подтверждение платежа.4а. Система определяет сбой при взаимодействии с внешней системой.1. Система сигнализирует об ошибке кассиру.2. Кассир просит покупателя изменить тип платежа.
Глава 6. Описание прецедентов 111Если нужно описать условия, которые могут возникнуть в любой момент, то в обо¬
значении пункта можно использовать символ * (см. ниже).*б. При каждом выходе системы из строя.Для ввода системы в строй и корректной обработки платежа нужно обеспечить восстанов¬
ление всех транзакций и событий с любого шага сценария.1. Кассир перезапускает систему, регистрируется и предлагает восстановить предыдущее
состояние.2. Система восстанавливает предыдущее состояние.Альтернативные сценарииИногда при реализации прецедента возможны несколько сценариев. Например,
кассир может обратиться к автоматизированной справочной системе либо к другому
сотруднику по телефону. Второй сценарий иногда выделяют подчеркиванием, как в
следующем примере.2в. Кассир обращается за справкой об идентификаторе товара и его стоимости к спра¬
вочной системе.2г. Кассир запрашивает информацию об идентификаторе и цене товара по телефону и
вручную вводит эти данные.Предполагается, что прецеденты описываются с помощью гиперссылок, поэтому при
щелчке на подчеркнутом фрагменте текста можно перейти к требуемому описанию.Специальные требованияВ этот раздел заносятся нефункциональные требования, атрибуты качества или
ограничения, связанные с данным прецедентом. Сюда относятся характеристики
производительности, надежности, удобства использования и конструктивные огра¬
ничения (например, на устройства ввода-вывода).Специальные требования- Сенсорный экран с интерфейсом пользователя для большого плоского монитора. Текст дол¬
жен быть виден с расстояния один метр.- Отклик службы авторизации в 90% случаев приходит в течение 30 секунд.- Возможность локализации (представления на различных языках) отображаемого текста.- Возможность добавления новых бизнес-правил на шагах 3 и 7 в процессе функционирова¬
ния системы.Запись этих условий при описании прецедента — классический совет разработ¬
чиков унифицированного процесса. Однако на практике многие специалисты по¬
мещают эти требования в едином общем документе, например в дополнительной
спецификации. Тогда их удобнее читать и осмысливать, поскольку обычно они рас¬
сматриваются в общем контексте в процессе анализа архитектуры.
112 Часть II. Начальная фазаСписок технологий и типов данныхЗачастую при реализации проекта важно не что сделать, а как. Перечень исполь¬
зуемых технологий тоже приводится в описании прецедента. Типичным примером
такой ситуации являются технические ограничения, выдвигаемые заинтересованны¬
ми лицами для технологий ввода и вывода. Например, заказчик может потребовать,
чтобы POS-система поддерживала ввод данных кредитной карточки с клавиатуры и с
помощью считывающего устройства. Заметим, что здесь приводятся лишь примеры
проектных решений и ограничений, появляющихся на ранней стадии реализации
проекта. В целом, такой конкретизации следует избегать, однако иногда она бывает
неизбежна, особенно в отношении технологий ввода-вывода.Нужно также указать возможные варианты типов данных, например различные
кодировки идентификаторов товаров. Их тоже указывают в этом разделе (см. ниже).В этом разделе описывают различные действия для разных ситуаций.Список технологий и типов данныхЗа. Идентификатор товара считывается со штрихкода (при наличии последнего) лазерным ска¬
нером или вводится с клавиатуры.36. Идентификатор товара может определяться по схемам кодирования UPC, EAN, JAN или
SKU.7а. Информация об открытом кредите вводится с помощью считывающего устройства или с
клавиатуры.76. Подпись при оплате чеком ставится на бумажном документе. Однако ожидается, что в те¬
чение двух лет большинство покупателей будут требовать цифровые устройства считыва¬
ния подписи.Поздравляем: прецеденты описаны плохоДля описания прецедентов POS-системы Next Gen в течение нескольких итераций
созывались семинары по определению требований, постепенно количество преце¬
дентов увеличивалось, требования уточнялись и дорабатывались с учетом обратной
связи. В процессе описания прецедентов активно участвовали эксперты предметной
области, кассиры и программисты.Хорошо, но не очень. Спецификация требований создает лишь иллюзию коррект¬
ности. Можно с уверенностью утверждать, что прецеденты и другие требования в
этом документе не корректны. В описании не хватает важной информации и содер¬
жатся неверные утверждения. Подтвердить корректность описания требований мо¬
жет только их реализация в программном коде и его тестирование.Для решения этой проблемы мы не призываем вас следовать рекомендациям одно¬
проходного процесса разработки и приложить больше усилий к полному описанию
требований на начальных этапах разработки, хотя, безусловно, эту работу нужно вы¬
полнить максимально добросовестно. Однако этого не достаточно.Автор не призывает также приступать к кодированию без анализа и моделирова¬
ния. Существует некий промежуточный путь между каскадным процессом разработки
и неподготовленным программированием. Данная проблема решается за счет итера¬
тивности процесса разработки. При таком подходе описание прецедентов и другие
модели постоянно верифицируются на этапах программирования и тестирования, а
затем уточняются на новых итерациях разработки. Не следует описывать в деталях
все прецеденты до начала первой стадии разработки.
Глава 6. Описание прецедентов 1136.10. Другие форматы описания прецедентовНекоторые предпочитают оформлять прецеденты в виде двух колонок, обращая
внимание на факт взаимодействия исполнителей и системы. Такой формат впервые
был предложен Ребеккой Вирфс-Брок (Rebecca Wirfs-Brock) в работе [121] и поддер¬
жан Константином (Constantine) и Локвудом (Lockwood) в работе [31]. Вот как вы¬
глядит рассмотренное выше описание, представленное в виде двух колонок.Прецедент П1. Оформление продажиОсновной исполнитель: ...... как и ранее...Основной успешный сценарийДействие исполнителя1. Покупатель подходит к кассовому аппа¬
рату POS-системы с выбранными това¬
рами.2. Кассир открывает новую продажу.3. Кассир вводит идентификатор товара.Кассир повторяет действия, описанные в
пп. 3-4 для каждого наименования товара.6. Кассир сообщает покупателю общую сто¬
имость и предлагает оплатить покупку.7. Покупатель оплачивает покупку.Какой формат лучше?Однозначного ответа на этот вопрос не существует. Одни предпочитают исполь¬
зовать колонки, другие — нет. В приведенное описание можно добавлять новые раз¬
делы или удалять лишние. Заголовки разделов тоже можно изменять. Все эти частно¬
сти большой роли не играют. Главная задача — детально описать основной успешный
сценарий и его расширения в некоторой стандартной форме. Множество полезных
форматов описано в [37].Отклик системы4. Система записывает наименование това¬
ра и выдает его описание, цену и общую
стоимость. Цена вычисляется на основе
набора правил.5. Система вычисляет общую стоимость по¬
купки с налогом.8. Система обрабатывает платеж.9. Система регистрирует продажу и отправляет
информацию о ней внешней бухгалтерской
системе (для обновления бухгалтерских
документов и начисления комиссионных) и
системе складского учета (для обновления
данных). Система выдает товарный чек.
114 Часть II. Начальная фазаИз личного опытаЭто лишь опыт автора книги, а не рекомендация. В течение нескольких лет автор
использовал формат описания в виде двух колонок, поскольку он обеспечивает
наглядное представление общения с системой. Однако затем он перешел к обыч¬
ному формату, поскольку он более компактен и его легче форматировать. Эти два
преимущества для автора книги с лихвой перекрывают преимущества формата с
колонками. Кроме того, для облегчения восприятия можно описывать действия
исполнителя и системы в отдельных абзацах со своими номерами.6.11. Описание прецедентов, относящихся к
интерфейсу пользователя, в свободном стилеНовая и важная информация! Отпечатки пальцевИсследование целей, а не обязанностей и процедур позволяет сосредоточить вни¬
мание на основных требованиях. Например, на одном из семинаров кассир может
сказать, что одной из его целей является регистрация в системе. При этом он может
иметь в виду элементы интерфейса пользователя, соответствующие диалоговые окна,
ввод идентификатора и пароля. Однако все это — механизмы достижения цели, а не
сама цель. Изучая иерархию целей (отвечая на вопрос “какова цель этой задачи?”),
системный аналитик приходит к формулировке, независимой от механизма реализа¬
ции: “идентифицировать себя и выполнить аутентификацию” или на более высоком
уровне — “предотвратить утечку информации”.Такой процесс исследования позволяет получить новые и более эффективные ре¬
шения. Например, в настоящее время достаточно распространены и недорого стоят
клавиатура и мышь с устройствами считывания биометрической информации, в част¬
ности отпечатков пальцев. Если целью является идентификация и аутентификация,
то почему бы для ее достижения не использовать эффективное и быстрое средство
считывания биометрических данных с клавиатуры? Однако, отвечая на этот вопрос,
следует принимать во внимание удобство использования. В данном случае придется
установить профили типичных пользователей. А если их пальцы чем-то испачканы?
А если они травмированы?Базовый стиль описанияЭта идея была сформулирована в различных рекомендациях типа “не уделяйте
внимания вопросам интерфейса пользователя, сосредоточьте внимание на содер¬
жательной стороне вопроса” [37]. Подобные идеи и предложения наиболее полно
были изучены Лерри Константином (Larry Constantine) в контексте создания наибо¬
лее удачного интерфейса пользователя и исследования удобства использования про¬
граммных продуктов [31, 40]. Если описание не содержит подробной информации о
реализации пользовательского интерфейса, а основное внимание в нем сосредото¬
чено на содержательных моментах, то такой стиль описания Константин называет
базовым (essential).55 Этот термин происходит от термина “базовая модель” (essential model) из области систем¬
ного анализа [96].
Глава 6. Описание прецедентов 115Базовый стиль описания предполагает изложение на уровне намерений пользовате¬
ля и обязанностей системы, а не на уровне их конкретных действий. При таком стиле
описания не нужно углубляться в детали технологии и механизма реализации, осо¬
бенно при рассмотрении вопросов, связанных с интерфейсом пользователя.СоветОписывайте прецеденты в базовом стиле. Не уделяйте внимания интерфейсу
пользователя, а сосредоточьтесь на содержательной стороне вопроса.Все приведенные выше примеры прецедентов были выдержаны в базовом стиле
описания, в том числе прецедент Оформление продажи.Контрпримеры
Базовый стильДопустим, идентификация и аутентификация выполняются в рамках прецедентаУправление пользователями.^Администратор идентифицирует себя.2. Система выполняет аутентификацию.3....Для реализации этих намерений и обязанностей можно использовать широкий
спектр проектных решений: устройства считывания биометрической информации,
графический интерфейс пользователя и т.д.Конкретный стиль — избегайте его на ранних
этапах формулировки требованийСуществует и другой стиль описания прецедентов — конкретный (concrete). При
таком стиле описания проектные решения, относящиеся к пользовательскому интер¬
фейсу, внедряются в описание прецедента. В тексте описания могут, например, даже
содержаться копии экранов, описываться элементы управления и другие элементы
пользовательского интерфейса.1. Администратор вводит идентификатор и пароль в диалоговом окне.2. Система аутентифицирует администратора.3. Система отображает окно Изменение пользователей.4....Такое конкретное описание потребуется на следующих этапах проектирования
GUI, а не стадии анализа требований. В процессе формулировки требований “не уде¬
ляйте внимания вопросам интерфейса пользователя, сосредоточьте внимание на со¬
держательной стороне вопроса”.
116 Часть II. Начальная фаза6.12. Описания прецедентов должны
быть лаконичнымиЗахочется ли вам читать длинные перечни требований? Вряд ли. Поэтому описа¬
ния прецедентов должны быть лаконичными. Избегайте ненужных слов, старайтесь
сокращать каждое предложение.6.13. Описание прецедентов
в формате “черный ящик”Описание прецедента в формате “черный ящик” (black-box use cases) — это самый ти¬
пичный и рекомендуемый тип описания прецедентов. Они не описывают внутрен¬
нюю работу системы, ее компоненты или дизайн. Наоборот, системе вменяются
некоторые обязанности (responsibilities). Этот метафорический термин широко при¬
меняется в объектно-ориентированном проектировании: программные элементы
имеют обязанности и взаимодействуют с другими элементами со своими обязанно¬
стями.Определяя обязанности системы через прецеденты типа “черный ящик”, можно
указать, что должна делать система (функциональные требования), не расписывая,
как это делать (не выполняя проектирование). Вообще, термины “анализ” и “про¬
ектирование” зачастую сводятся к вопросам “что” и “как”. Это важные вопросы в
хорошей программной разработке. В процессе анализа требований нужно избегать
принятия решений “как”, а описывать лишь внешнее поведение системы как черного
ящика. Позднее, на этапе проектирования, создается решение, удовлетворяющее раз¬
работанной спецификации.Стиль черного ящикаДругой стильСистема регистрирует покупкуСистема записывает сведения о покупке в базу данных.Или, еще хуже:система генерирует оператор SQL insert для данной продажи...6.14. Примите точку зрения исполнителяРассмотрим определение прецедента, приведенное в RUP.Прецедент — это набор сценариев использования, в котором каждый экзем¬
пляр сценария представляет собой последовательность действий, выполняе¬
мых системой для достижения результата, ощутимого для конкретного испол¬
нителя [112].Выражение “ощутимый результат” несколько туманно, но, по мнению Якобсона,
очень важно, поскольку определяет два важных аспекта анализа требований.■ В процессе анализа требований нужно сконцентрироваться на целях и задачах
пользователей или исполнителей.■ Необходимо понять, что поведение системы должно быть ощутимо для пользо¬
вателя.
Глава 6. Описание прецедентов 117На первый взгляд, требование обеспечения ощутимого результата может пока¬
заться очевидным. Однако в сфере программного обеспечения известно множество
неудачных проектов, которые провалились из-за невыполнения реальных задач поль¬
зователей. К такому отрицательному результату может привести подход к описанию
системных требований в виде списка свойств и функций системы, поскольку он не
заставляет заинтересованных лиц рассматривать требования в более широком кон¬
тексте для достижения некоторого ощутимого результата или некоторой цели. В от¬
личие от этого подхода, в контексте прецедентов свойства и функции системы ори¬
ентированы на достижение цели.6.15. Как выделять прецедентыПрецеденты предназначены для удовлетворения потребностей основных испол¬
нителей. Поэтому для выделения прецедентов используется следующая процедура.1. Определите рамки системы: является ли она программным приложением, аппа¬
ратно-программным комплексом, включает ли в себя своих пользователей или
всю организацию?2. Идентифицируйте основных исполнителей, потребности (цели) которых удо¬
влетворяются с помощью системы.3. Для каждого исполнителя определите его задачи.4. Определите прецеденты, удовлетворяющие потребности каждого исполнителя,
и присвойте им имена в соответствии с задачами. Обычно основные прецеден¬
ты соответствуют задачам пользователей, за одним исключением, о котором
речь пойдет ниже.Конечно, при итеративной и эволюционной разработке не все цели и прецеден¬
ты можно полно и корректно идентифицировать на начальных стадиях. Это эволю¬
ционный процесс.Шаг 1. Определение рамок системыДля данного прецедента разрабатываемой системой является сама POS-система.
Все, что находится за ее пределами, включая кассира, службу авторизации платежей
и т.д., в эти рамки не включается.Для определения рамок системы следует, в первую очередь, указать, что к ней
не относится, т.е. определить внешних основных и вспомогательных исполнителей.
Йосле идентификации внешних исполнителей рамки системы очерчиваются более
четко. Например, возлагается ли на систему полная ответственность за авторизацию
платежей? Нет, эту задачу выполняет внешний исполнитель — служба авторизации
платежей.Шаги 2 и 3. Определение основных исполнителей и задачНельзя однозначно указать последовательность определения исполнителей и за¬
дач. Обычно на семинаре по определению требований методом мозгового штурма
идентифицируются и те и другие артефакты. Иногда исполнители определяются по¬
сле формулировки задач, а иногда наоборот.
118 Часть II. Начальная фазаРекомендация. В процессе мозгового штурма основное внимание следует уделить
определению основных исполнителей, поскольку это расширит возможности для
дальнейшего исследования.Вопросы, возникающие при определении исполнителей и задачПри определении основных исполнителей и задач пользователей следует отве¬
тить на следующие вопросы, чтобы не упустить из виду некоторые неочевидные мо¬
менты.1. Кто запускает и выключает систему?2. Кто является системным администратором?3. Кто осуществляет управление пользователями и безопасностью?4. Относится ли время к числу исполнителей, другими словами, должна ли систе¬
ма выполнять какие-либо действия в ответ на события времени?5. Существует ли процесс мониторинга, благодаря которому система перезапуска¬
ется в случае сбоя?6. Кто контролирует деятельность и производительность системы?7. Как выполняется обновление программного обеспечения?8. Кто анализирует журналы регистрации? Можно ли обеспечить удаленный до¬
ступ к ним?9. Могут ли в качестве исполнителей выступать внешние программы или автома¬
тические системы?10. Кого следует уведомлять при ошибках или сбоях в системе?Как составить перечень исполнителей и их задачСуществует два подхода к решению этой задачи.1. При построении диаграммы прецедентов имена прецедентов можно рассматри¬
вать как задачи системы.2. Можно сначала составить перечень исполнителей, уточнить его, а затем стро¬
ить диаграмму прецедентов.При использовании второго подхода список исполнителей должен быть разделом
артефакта “Видение”. Рассмотрим следующую таблицу.Исполнитель ЗадачиИсполнитель ЗадачиКассир Оформляет продажиОформляет кредиты
Выполняет возврат товара
Регистрирует выручкуМенеджер Включает систему
Выключает системуСистемный ад- Добавляет пользователейминистраторСистема ана¬
лиза торговой
деятельностиИзменяет параметры пользователей
Удаляет пользователей
Управляет безопасностью
Управляет системными таблицамиАнализирует информацию о прода¬
жах и оценивает производительность
Глава 6. Описание прецедентов 119Система анализа торговой деятельности (Sales Activity System) — это удаленное
приложение, которое достаточно часто будет запрашивать данные от каждого узла
POS-системы по сети.Прецеденты и задачиИсполнители имеют свои задачи (или потребности), для решения которых они
используют систему. Поэтому при описании прецедентов необходимо идентифици¬
ровать исполнителей и их задачи, которые должны быть решены в результате созда¬
ния системы. При таком подходе несколько смещаются акценты аналитиков. Вместо
вопроса “Каковы задачи системы?” возникает вопрос “Кто является исполнителем и
каковы их задачи?”. Чтобы отобразить эту взаимосвязь, имя прецедента должно соот¬
ветствовать названию задачи. Например, задаче электронного оформления продажи
должен соответствовать прецедент Оформление продажи.Таким образом, ключевая идея состоит в том, чтобы для выделения прецедентов
исследовать задачи исполнителей.Допустим, мы собрались на семинаре для формулировки требований. На этом се¬
минаре основной вопрос можно формулировать двумя способами.■ Что делает система?■ Каковы цели и задачи исполнителей?Более предпочтительным является второй способ.Ответы на первый вопрос, скорее, отражают текущие решения и процедуры, а
также сложность этих процедур.Ответы на второй вопрос, особенно в сочетании с исследованием целей более вы¬
сокого уровня (“в чем состоит главная задача?”), открывают видение новых и более
эффективных решений, акцентируют внимание на получении ощутимого результата
и позволяют глубже понять основные потребности заинтересованных лиц в контек¬
сте обсуждаемой системы.Кто является основным исполнителем: кассир или покупательПочему основным исполнителем для прецедента Оформление продажи является
кассир, а не покупатель?Ответ определяется рамками разрабатываемой системы, как показано на рис. 6.2.
Если предприятие или торговую организацию рассматривать как агрегатную систе¬
му, то для нее основным исполнителем должен являться покупатель, задача которо¬
го — приобретение товаров или услуг. Однако с точки зрения самой POS-системы (ко¬
торая определяет рамки системы для данного прецедента), основным исполнителем
является кассир, задача которого — обслуживание продаж.Покупатель тоже является исполнителем, но в контексте POS-системы NextGen
он не относится к основным исполнителям. Главным исполнителем является кассир,
поскольку система предназначена для автоматизации его функциональных обязанно¬
стей. Интерфейс пользователя системы не предназначен для покупателя, а оптимизи¬
рован с учетом задач кассира. Покупатель не знает, как пользоваться этой системой.
Другими словами, система разрабатывается для кассира, а не для покупателя.
120 Часть II. Начальная фазаНалоговаяинспекцияЦель: получить
налоги с продажПокупательЦель: купить товарыо продажах
и производительностиРис. 6.2. Основные исполнители и их задачи при изменении рамок системыЕсли рассмотреть другую систему — Web-узел продажи билетов, — то легко убедить¬
ся, что она рассчитана на использование покупателем. Такая система заменяет служ¬
бу заказа билетов по телефону. Поэтому основным исполнителем подобной системы
является не торговый агент, а покупатель.Определение исполнителей и задач путем анализа событийДля определения исполнителей, их задач и прецедентов можно также использо¬
вать внешние события. Что это означает? Зачастую к одному и тому же уровню EBP
или прецеденту, например, относится целая группа событий.Внешнее событиеИнициаторЗадача/ПрецедентВвод информации о наименовании товара
Ввод информации о платежеКассирКассир или покупательОформление продажи
Оформление продажиШаг 4. Определение прецедентовКак правило, каждой задаче пользователя соответствует один прецедент. Его имя
должно соответствовать названию задачи, например, задаче оформления продажи
должен соответствовать прецедент Оформление продажи.Как правило, имя прецедента начинается с существительного, описывающего
действие.Типичным исключением из правила соответствия задач и прецедентов является
прецедент, решающий четыре задачи — создание, восстановление, обновление и уда¬
ление. Обычно такой прецедент называется Управление <чем-либо>. Например, за¬
Глава 6. Описание прецедентов 121дачи “изменение информации о пользователях”, “удаление пользователей” и т.д. ре¬
шаются в рамках прецедента Управление пользователями.6.16. Как выделить полезные прецедентыКакой из следующих пунктов можно считать прецедентом?■ Переговоры с поставщиком■ Обработка возврата товара■ Регистрация■ Перемещение фишки по игральной доскеМожно сказать, что все это прецеденты на разных уровнях детализации, выделен¬
ные в зависимости от рамок системы, исполнителей и задач. Мы еще вернемся к это¬
му вопросу после рассмотрения элементарных бизнес-процессов.Вместо вопроса “Что такое корректный прецедент?” целесообразно задать себе
вопрос: “На каком уровне следует рассматривать прецеденты в процессе анализа тре¬
бований к приложению?”. Существует три критерия для выделения прецедентов.■ Критерий одобрения руководством.■ Критерий ЕВР.■ Критерий размера.Критерий одобрения руководствомЕсли в ответ на вопрос руководителя “Чем вы занимались целый день?” вы ответи¬
те “Регистрировался в системе”, вряд ли это вызовет одобрение вашего шефа.Это означает, что прецедент Регистрация в системе не удовлетворяет критерию
одобрения руководством, поскольку напрямую не связан с функциональными обязан¬
ностями. Его можно рассматривать в качестве прецедента на более низком уровне, а
не концентрировать на нем внимание на этапе анализа требований.Это не означает, что для выделения всех прецедентов необходимо получать одо¬
брение руководства. Аутентификация пользователя, хотя и не удовлетворяет данному
критерию, является важным и сложным компонентом системы.Критерий EBPТермин элементарный бизнес-процесс (EBP — Elementary Business Processes) заимство¬
ван из области исследования бизнес-процессов6 и определяется следующим образом.“Элементарный бизнес-процесс — это задача, выполняемая одним человеком в
одном месте в одно время в ответ на некоторое бизнес-событие, добавляющая
измеряемое бизнес-значение и переводящая данные в некоторое устойчивое
состояние, например, подтверждение платежа по кредитной карточке или рас¬
поряжение брокеру при изменении цен” (источник неизвестен).6 Термин EBF аналогичен термину пользовательская задача (user task), применяемому в
области изучения удобства использования. Однако в той предметной области его значе¬
ние является менее жестким.
122 Часть II. Начальная фазаСоветВ процессе анализа требований к компьютерному приложению следует сосредо¬
точить внимание на уровне элементарных бизнес-процессов.Критерий EBP аналогичен критерию одобрения руководством, поскольку тоже
формулируется в терминах ценности с точки зрения решения основных задач.Это определение можно воспринимать слишком буквально. Тогда возникает во¬
прос: могут ли в сценарии прецедента участвовать два человека? Скорее всего, да.
Однако общая идея этого определения верна. Прецедент — это не один маленький
шаг, такой, например, как удаление товара или печать документа. Основной сценарий
прецедента обычно включает пять-десять шагов. Описываемый сценарий выполняет¬
ся не в течение нескольких дней или сеансов, как, например, переговоры с постав¬
щиками. Это задача, выполняемая в течение одного сеанса. Реализация прецедента
может длиться от нескольких минут до нескольких дней. Как и при определении уни¬
фицированного процесса, основное внимание уделяется получению ощутимого (из¬
меримого) результата и переходу системы и данных в устойчивое состояние.Критерий размераОбычно описание прецедентов охватывает не единственное действие испол¬
нителя, а состоит из нескольких шагов, представленных на 3-10 страницах текста.
Типичной ошибкой является рассмотрение прецедентов на слишком низком уровне,
когда сценарий выполняется за один шаг, например Ввод идентификатора товара.
Поэтому слишком короткое описание прецедента может служить сигналом о непра¬
вильной идентификации прецедента.Пример: применение критериев■ Переговоры с поставщиком.• Гораздо шире, чем ЕВР. Этот прецедент лучше моделировать на уровне пред¬
приятия, а не системных прецедентов.■ Обработка возврата товара.• Соответствует всем трем критериям.■ Регистрация.• Руководитель вряд ли будет счастлив, если его подчиненные занимаются этим
целый день!■ Перемещение фишки по игральной доске.• Описывает единственный шаг, поэтому не удовлетворяет критерию размера.Обоснованные отклоненияНесмотря на то, что основные прецеденты приложения должны удовлетворять
указанным выше критериям, возможны некоторые исключения.Зачастую полезно создавать отдельные прецеденты более низкого уровня, пред¬
ставляющие подзадачи или подпоследовательности действий в рамках основного пре-
Глава 6. Описание прецедентов 123цедента. То есть, могут существовать прецеденты, не соответствующие элементарным
бизнес-процессам, а функционирующие на более низком уровне. Например, подзада¬
ча или расширение “Оплата по кредитной карточке” может быть представлена в не¬
скольких основных прецедентах. Поэтому ее желательно выделить в отдельный пре¬
цедент (не удовлетворяющий условиям элементарного бизнес-процесса) и связать с
несколькими основными прецедентами, чтобы избежать дублирования информации.Прецедент Аутентификация пользователя, хотя и не удовлетворяет критерию
одобрения руководителем, является достаточно сложным и требует внимательного
анализа.6.17. Диаграммы прецедентовВ языке UML существует система обозначений для диаграммы прецедентов,
иллюстрирующей имена прецедентов, исполнителей и взаимосвязи между ними
(рис. 6.3).Рис. 6.3. Фрагмент диаграммы прецедентов
124 Часть II. Начальная фазаДиаграммы прецедентов и их взаимосвязей имеют второстепенное значение при
работе над прецедентами. Прецеденты — это текстовые документы. Работать над
прецедентами — значит составлять текстовые описания.Обычно новички в области моделирования прецедентов начинают с составления
диаграмм прецедентов и их взаимоотношений, а не с составления текстовых описа¬
ний. Однако специалисты по написанию прецедентов мирового класса, к числу ко¬
торых относятся Андерсон (Anderson), Фаулер (Fowler), Кокбурн (Cockburn) и др.,
основное внимание уделяют составлению текстовых описаний, а не диаграмм. В та¬
ком ракурсе диаграмма лишь иллюстрирует способы использования системы внешни¬
ми исполнителями.СоветСтройте простые диаграммы прецедентов в соответствии со списком исполните¬
лей и их задач.Диаграмма прецедентов — это отличное изображение системного контекста, посколь¬
ку она отображает границы системы, внешние для системы понятия и способы исполь¬
зования системы. Она подытоживает поведение системы и ее исполнителей. Фрагмент
простой диаграммы прецедентов для системы NextGen показан выше на рис. 6.3.Система обозначений для диаграммы прецедентовНа рис. 6.4 показаны некоторые обозначения для диаграммы прецедентов.
Обратите внимание на блок с надписью «исполнитель». Так в UML обозначается
стереотип (stereotype) или ключевое слово (keyword) — механизм выделения категорий
элементов. Имя стереотипа заключается в двойные угловые кавычки.При построении контекстной
диаграммы прецедентов
нужно ограничиться
прецедентами уровня задач
пользователяДля изображения
компьютерной
системы использовано
другое обозначениеОсновные
исполнители слеваВспомогательные
исполнители справаРис. 6.4. Предлагаемые обозначения
Глава 6. Описание прецедентов 125Заметим, что некоторые предпочитают выделять внешних исполнителей иначе,
чем показано на рис. 6.5.NextGen«система»СлужбаавторизацииплатежейСлужбаавторизацииплатежей«исполнитель»СлужбаавторизацииплатежейРазные обозначения ■
для внешних
исполнителей, в роли
которых выступают
компьютерные системы.
Эти обозначения можно
использовать для изоб¬
ражения как людей, так
и компьютерных систем.
Если компьютерные
системы изображены
в виде прямоугольников,
их легче отличить от дру¬
гих типов исполнителейРис. 6.5. Другое обозначение исполнителейПредупреждениеЕще раз повторим, что основное внимание при работе над прецедентами следует
уделять написанию текстовых документов, а не составлению диаграмм. Если в органи¬
зации слишком много времени (несколько часов, а то и дней) уделяется составлению
диаграммы прецедентов и обсуждению их взаимосвязей, то из виду будут упущены
другие более важные моменты.6.18. Диаграммы видов деятельностиВ UML существует еще один вид диаграмм, предназначенных для визуализа¬
ции потоков выполнения и бизнес-процессов. Это диаграммы видов деятельности.
Поскольку прецеденты являются составной частью анализа процессов, для них тоже
полезно строить диаграммы видов деятельности, наглядно представляющие сложные
потоки выполнения со многими участниками и параллельными процессами.6.19. Дополнительные преимущества
описания прецедентовОписания прецедентов призваны выделить основных исполнителей, их цели и за¬
дачи. Описания прецедентов обеспечивают простую и понятную форму представле¬
ния этой информации.Кроме того, прецеденты позволяют заменить детальные списки низкоуровневых
свойств (которые обычно составлялись при использовании традиционного метода
формулировки требований). Эти списки были сгруппированы по функциональному
назначению и выглядели примерно следующим образом.
126 Часть II. Начальная фазаИдентификатор СвойствоСвойство 1.9 Система будет позволять вводить новые идентификаторыСвойство 2.4 Система будет регистрировать платежи по кредитной карточке в бухгалтерской системеКак следует из названия книги [60], основным мотивом описания прецедентов
является определение требований в контексте задач (целей) и сценариев использова¬
ния системы. Это очень хорошо, поскольку позволяет углубить понимание системы.
При модификации существующих систем, например системы управления движением,
приходится переформулировать прежние списки требований в виде описания преце¬
дентов. Это позволяет лучше сгруппировать и понять требования.Однако прецеденты — это не единственные артефакты формулировки требова¬
ний. Некоторые нефункциональные требования, правила и другие элементы лучше
описать в дополнительной спецификации.Списки высокоуровневых свойств
системы вполне допустимыДостаточно часто функциональные свойства системы описываются в кратких спи¬
сках свойств высокого уровня в рамках документа “Видение”. Это вполне оправдан¬
но. В отличие от списка низкоуровневых свойств, перечисленных на 50 страницах,
список основных свойств системы должен включать не более нескольких десятков
элементов. В нем, например, как показано ниже, могут быть перечислены лишь функ¬
циональные свойства системы, не упомянутые при описании прецедентов.Список свойств системы- Регистрация продаж.- Авторизация платежей (кредитных, дебетных, чековых).- Системное администрирование для управления пользователями, безопасностью, таблицами
кодов и констант и т.п.Когда нужен подробный список свойств?Иногда прецедентов действительно недостаточно. Для некоторых систем нужно
разработать детальный список свойств. Например, серверы приложений, системы
управления базами данных и другие базовые системы нужно рассматривать в терми¬
нах свойств (“В следующей версии необходима поддержка Web-служб”). Прецеденты
не годятся для разработки таких приложений.6.20. Пример: игра “Монополия”Единственным существенным прецедентом в программной системе “Монополия”
является Игра Монополия (несмотря на то, что он не удовлетворяет критерию одо¬
брения руководством). Поскольку эта игра происходит в режиме компьютерной эму¬
ляции, за которой следит один человек, он является наблюдателем, а не участником
игры.
Глава 6. Описание прецедентов 127На данном примере мы удостоверимся,
что описание прецедентов не всегда явля¬
ется наилучшим способом идентификации
требований. Описывать правила игры в
формате прецедентов неестественно и не¬
целесообразно. Правила игры, в первую
очередь, относятся к правилам предметной
области (которые иногда называют бизнес-
правилами). В рамках унифицированного
процесса правила предметной области яв¬
ляются частью дополнительной специфика¬
ции, в которой могут содержаться ссылки
на официальные документы или Web-узлы.Кроме того, описание прецедентов может содержать дополнительную ссылку на до¬
кумент, описывающий правила предметной области.Приведем диаграмму прецедентов для системы “Монополия” (рис. 6.6).Текст описания данного прецедента существенно отличается от описания преце¬
дентов POS-системы NextGen, поскольку игра реализована в режиме эмуляции.Прецедент П1. Игра “Монополия”Рамки. Приложение “Монополия”.Уровень. Задача, определенная пользователем.Основной исполнитель. Наблюдатель.Заинтересованные лица и их требования.- Наблюдатель. Хочет следить за процессом игры.Основной успешный сценарий (или основной процесс).1. Наблюдатель инициализирует игру и вводит количество игроков.2. Наблюдатель запускает игру.3. Система отображает ход игры (см. правила предметной области и словарь терминов).ШагЗ повторяется до выявления победителя либо до прекращения игры наблюдателя.Расширения (или альтернативные потоки)*а. При каждом выходе системы из строя.Для восстановления от сбоев система ведет журнал записи всех ходов.1. Наблюдатель перезапускает систему.2. Система восстанавливает предыдущее состояние и продолжает эмуляцию.3. Наблюдатель продолжает следить за игрой.Специальные требования- Обеспечить работу системы в графическом и текстовом режиме.Рис. 6.6. Диаграмма прецедентов для игры
“Монополия”
128 Часть II. Начальная фаза6.21. Прецеденты в рамках итеративной разработкиПрецеденты играют жизненно важную роль при реализации унифицированного
процесса и многих других итеративных методов, поскольку вся разработка в рамках
этого подхода осуществляется под управлением прецедентов (use-case driven develop¬
ment). Это означает следующее.■ Функциональные требования в основном формулируются при описании преце¬
дентов (в модели прецедентов). Остальные требования (если таковые существу¬
ют) являются либо техническими (например, список функций), либо второсте¬
пенными.■ Прецеденты — важный этап итеративного планирования. На каждой итерации
реализуются некоторые сценарии или целые прецеденты. Поэтому описания
прецедентов вносят существенный вклад в оценивание результата.■ Разработка приложения состоит в реализации прецедентов. То есть, группа раз¬
работчиков продумывает способы взаимодействия объектов или архитектуру
подсистем для реализации прецедентов.■ Описание прецедентов зачастую отражается на организации руководства поль¬
зователей.■ Функциональное и системное тестирование соответствует сценариям прецедентов.■ Для большинства сценариев важных прецедентов, реализующих типичные за¬
дачи приложения, в интерфейсе пользователя могут создаваться ярлыки или
специальные кнопки.Прецеденты и спецификация требований
в рамках итеративного процессаВ этом разделе мы вернемся к основной идее UP и итеративной разработки.
Рассмотрим временно рамки, выделяемые на формулировку требований на каж¬
дой итерации. В табл. 6.1 представлен пример (не претендующий на рекомендацию)
определения требований в процессе реализации стратегии UP.Обратите внимание, что группа технической разработки приступает к созданию
ядра системы в тот момент, когда детализированы лишь 10% требований, далее сле¬
дует намеренная задержка, и формулировка требований откладывается до конца пер¬
вой итерации стадии развития.В этом состоит ключевое отличие от однопроходного процесса — промышленная
разработка ядра системы начинается достаточно быстро, задолго до полного завер¬
шения формулировки требований.Обратите внимание, что в конце первой итерации стадии развития проводится
второй семинар по формулировке требований, по окончании которого 30% преце¬
дентов описаны подробно. При таком планировании можно учесть обратную связь и
оценки реализованной части системы. Обратная связь поступает от пользователей,
специалистов по тестированию и позволяет “познать непознанное”. То есть, в про¬
цессе разработки системы очень быстро возникают вопросы, требующие немедлен¬
ного решения.В рамках UP для облегчения описания прецедентов организуют специальный се¬
минар, время и место проведения которого проиллюстрированы на рис. 6.7.
Глава 6. Описание прецедентов 129Таблица 6.1. Пример формулировки требований на начальных итерациях разработки проектаКомментарии по поводу формулировки требованийДисциплинаАртефактНачало
1 неделяРазвитие 1
4 неделиРазвитие 2
4 неделиРазвитие 3
3 неделиРазвитие 4
3 неделиТребованияМодельпреце¬дентовДвухдневный
семинар по
формулировке
требований.
Для боль¬
шинства
прецедентов
определяются
имена и созда¬
ются краткие
описания.
Только 10%
прецедентов
описываются
подробноВ конце этой
итерации прово¬
дится двухднев¬
ный семинар по
формулировке
требований.При этомучитываютсярезультатывыполненнойработы, 30%прецедентовописываютсяподробноВ конце этойитерациипроводитсядвухдневныйсеминар поформулировкетребований.При этомучитываютсярезультатывыполненнойработы, 50%прецедентовописываютсяподробноТо же самое,
70% пре¬
цедентов
описываются
подробно80-90% пре¬
цедентов
описываются
подробно.
Только не¬
большая часть
прецедентов
реализуется на
стадии разви¬
тия, реализа¬
ция остальных
переносится
на стадию кон¬
струированияПроектиро¬ваниеМодельпроекти¬рованияПроектирование
для небольшого
числа архитек¬
турно важных
требований с
высокой степе¬
нью рискаТо же самоеТо же самоеТо же самое.
Все архитек¬
турно важные
элементы с
высокой сте¬
пенью риска
должны быть
спроектиро¬
ваны к этому
моментуРеализацияМодель
реализа¬
ции (код)РеализацияпроектногорешенияТо же самое.5% окончатель¬
ной системы
построеноТо же самое.
10% окон¬
чательной
системы по¬
строеноТо же самое.
15% оконча¬
тельной систе¬
мы построеноУправлениепроектомПланразра¬боткиДостаточно
общая оценка
требуемых
затрат и
ресурсовОценки начина¬
ют конкретизи¬
роватьсяНесколькобольше...Несколькобольше...Общая дли¬
тельность про¬
екта, основные
этапы, затраты
и ресурсы оце¬
нены достаточ¬
но точно5 Зак. 3357
130 Часть II. Начальная фазаКогдаI Один раз на начальной фазе. Придерживайтесь
i принципа краткости; не старайтесь определить
| или уточнить все требования.\\ Несколько раз в течение этапа развития fГдеНа семинаре
по определению
требованийЯнварь/Феврёль|Две смежные проекцииПрецедент: Оформление продажи Прецедент: Возврат товараОсновной успешный сценарий:
1....2....3....Расширения:Основной успешный сценарий:
1....2....3....Расширения:Системный Покупательаналитик f tКонечный Разработчикпользователь ^Архитектор
программной
системы .Кто'В процессе определения требований
должны принимать участие разные
категории заинтересованных лиц,
включая пользователей и разработчиков.
Они помогают описывать прецеденты.Руководитель семинара — системный
аналитик, который отвечает за определение
требований./ / Как: средства
1 Программные:Для описания прецедентов используйте средства
формулировки требований из Интернет, интегриро¬
ванные с популярным текстовым процессором.Для построения диаграмм прецедентов используйте
CASE-средства UML.Создайте Web-узел проекта и определите гиперссылкиi на все прецеденты.\• Аппаратные: используйте два проектора со специальными
видеокартами, позволяющими вдвое расширить область
экрана или отобразить два окна текстового процессора.Рис. 6.7. Рекомендации по организации семинаров
Глава 6. Описание прецедентов 131Временные рамки создания артефактов UPВ табл. 6.2 приводятся некоторые артефакты UP и примерный график их созда¬
ния. К разработке модели прецедентов нужно приступать на начальной стадии, при
этом 10% прецедентов желательно описать подробно. Основная часть прецедентов
постепенно описывается на стадии развития (в этот же период готовится дополни¬
тельная спецификация), поэтому к завершению этой фазы обычно формируется реа¬
листичное представление о сроках реализации проекта.Таблица 6.2. Пример планирования сроков реализации артефактов UP
(н - начало, р - развитие)ДисциплинаАртефактИтерация-^НачалоИРазвитиеЕ1..ЕпКонструи¬рованиеС1..СпПередачаТ1..Тп“Бизнес-Модель предметной областинмоделирование”“Требования”Модель прецедентовнРВидение системынРДополнительная спецификациянРСловарь терминовнР“Проектирование”Модель проектированиянР“Описание архитектуры”нПрецеденты начальной фазыРассмотрим подробнее табл. 6.1.На начальной стадии не все прецеденты описываются детально. Для описания
прецедентов целесообразно организовать двухдневный семинар. В первой половине
первого дня можно определить задачи и круг заинтересованных лиц, а также обсу¬
дить, какие задачи относятся к проекту, а какие выходят за его рамки. С помощью
компьютерного проектора можно составить и демонстрировать таблицу исполните¬
лей и их задач. Можно приступить к построению диаграммы прецедентов. В тече¬
ние нескольких часов вполне реально определить порядка 20 задач пользователей (и
соответствующих им прецедентов), в том числе прецеденты Оформление продажи,
Возврат товара и т.д. За это время большинство интересных, сложных прецедентов
с высоким уровнем риска должны быть описаны в сжатом формате. На описание каж¬
дого такого прецедента понадобится около 2 минут. Разработчики могут приступить
к составлению высокоуровневой схемы функциональности системы.После этого 10-20% прецедентов, представляющих сложные функции или высо¬
кую степень риска, нужно описать подробно. При этом разработчики лучше оценят
сложность проекта, его рамки, выявят проблемы, возникающие в процессе разра¬
ботки. Самыми важными прецедентами являются, пожалуй, Оформление продажи и
Возврат товара.Прецеденты на стадии развитияРассмотрим следующие столбцы табл. 6.1.
132 Часть II. Начальная фазаФаза развития включает несколько итераций фиксированной длительности (ска¬
жем, четыре недели), в течение которых реализуются наиболее рискованные, зна¬
чимые и архитектурно важные части системы, а также идентифицируется и прояс¬
няется большая часть требований. Благодаря наличию обратной связи разработчики
лучше понимают требования, постепенно уточняют и конкретизируют их. На каждой
итерации желательно провести двухдневный семинар. Однако на каждом семинаре
не нужно обсуждать все прецеденты. Их нужно упорядочить по приоритетности и
сначала рассматривать самые важные прецеденты.На каждом следующем семинаре нужно дорабатывать и уточнять основные требо¬
вания. На начальных итерациях процесс изменения требований может происходить
достаточно интенсивно. Однако в дальнейшем он стабилизируется. В итеративном
процессе происходит постепенная доработка наиболее важных частей системы.На каждом семинаре список задач пользователей и прецедентов постепенно уточ¬
няется. По окончании фазы развития большинство прецедентов должно быть описа¬
но или переписано в развернутом формате (примерно 80-90%). Если для POS-систе-
мы выделено 20 прецедентов, то как минимум 15 наиболее сложных и рискованных
из них должны быть определены полностью.Заметим, что на стадии развития разработка части системы доводится до про¬
граммной реализации. Поэтому по окончании этой фазы команда разработчиков си¬
стемы NextGen будет иметь не только достаточно полно определенные прецеденты,
но и качественный выполняемый код.Прецеденты на стадии конструированияЭтап конструирования состоит из некоторого числа итераций фиксированной
длительности (например, 20 итераций по 2 недели каждая), в течение которых основ¬
ное внимание уделяется доработке системы, поскольку наиболее принципиальные
вопросы уже решены на стадии развития. На этом этапе тоже некоторое внимание
уделяется описанию прецедентов, однако значительно меньшее, чем на стадии раз¬
вития. К этому моменту большая часть функциональных и нефункциональных тре¬
бований должна быть постепенно стабилизирована. Это не означает необходимости
замораживания требований и завершения исследований. Однако теперь степень мо¬
дификации требований от итерации к итерации значительно снижается.Пример: прецеденты начальной фазы проекта NextGenКак видно из предыдущих разделов, на начальной стадии не все прецеденты опи¬
сываются детально. Модель прецедентов на этом этапе может быть разработана на
следующем уровне детализации.В развернутом формате В свободном формате Краткое описаниеОформление продажи Вычисление арендной платы Регистрация выручкиВозврат товара Анализ торговой деятельности Управление пользователямиУправление безопасностью Запуск системыЗавершение работы
Управление системными
таблицами
Глава 6. Описание прецедентов 1336.22. ИсторияИдея описания функциональных требований в виде прецедентов впервые была
сформулирована главным разработчиком UML и UP Айваром Якобсоном в 1986 году
[72]. Эта идея оказалась очень популярной и легко прижилась среди разработчиков.
Несмотря на попытки многих исследователей внести вклад в развитие этой области,
наиболее существенным вкладом стали идеи Алистера Кокбурна (ученика Якобсона),
описанные в работе [37].6.23. Дополнительные ресурсыНаиболее популярным руководством по описанию прецедентов является книга
[37], переведенная на несколько языков. Эта книга настолько популярна, что ее мож¬
но поставить первой в списке рекомендованной литературы. Данная глава основыва¬
ется на основных положениях этой книги.В книге Patterns for Effective Use Cases Адолфа (Adolph) и Брэмбла (Bramble) приво¬
дится много полезных советов по организации процесса описания прецедентов (под¬
бору команды, методологии, структурированию и редактированию описаний).Идентифицировать прецеденты лучше всего в процессе групповой работы на се¬
минаре по определению требований. Вопросам организации семинаров посвящена
работа Requirements by Collaboration: Workshops for Defining Needs Эллен Готтесдинер (Ellen
Gottesdiener).Стоит упомянуть еще одну ценную работу Use Case Modeling Биттнера (Bittner) и
Спенса (Spence), написанную двумя опытными специалистами, постигшими на своем
опыте премудрости применения прецедентов в итеративном жизненном цикле.Самой популярной статьей в Интернет, посвященной описанию прецедентов, яв¬
ляется работа [36], которую можно найти по адресу www.usecases.org.Еще одной полезной книгой является [60]. Ее основным “лейтмотивом” (как
следует из самого названия) является мысль о том, что прецеденты — это не допол¬
нительный артефакт дисциплины определения требований, а основная “движущая
сила” процесса анализа требований.
Другие требованияБыстро, дешево, качественно: выберите любые два.Автор неизвестенОсновные задачи■ Разработать дополнительную спецификацию, словарь терминов, до¬
кумент “Видение” и бизнес-правила.■ Сопоставить свойства системы с прецедентами.■ Определить атрибуты качества.ВведениеДля определения требований одного описания прецедентов недостаточно. Необхо¬
димо определить и другие виды требований, что мы и сделаем в этой главе. Если вы
хотите пропустить эту главу, поскольку речь в ней идет не об аспектах объектно-ори¬
ентированного анализа и проектирования, а о дополнительных вопросах определе¬
ния требования, то можете сразу же перейти к следующей главе.Почему данная глава включена в книгу, хотя она и не относится к объектно-ори¬
ентированному анализу и проектированию? Дело в том, что она позволяет лучше
понять рассматриваемый в книге пример приложения и ознакомиться с вариантом
описания сложных требований.Что дальше? После описания прецедентов в данной главе рассматриваются другие артефакты,
предназначенные для описания требований в контексте процесса UP. В следующей
главе определяется объем работы для итерации 1/ \т * МоделированиеЭволюционные п Другие Требования ~* Прецеденты * Л предметнойтребования к требования итерации 1 области_С • о о
136 Часть II. Начальная фазаДругие артефакты требованийПрецеденты не являются исчерпывающим описанием системы.Дополнительная спецификация (supplementary specification) описывает другие виды
требований, в частности к отчетам, документированию, поддержке, лицензированию
и т.п.В словарь терминов (glossary) включаются термины и определения. Он также может
служить словарем данных.Документ “Впдение” (Vision) определяет ведение проекта. Он описывает важней¬
шие идеи, положенные в основу разработки системы.Бизнес-правила (business rule) — это устойчивые правила или политики, применяе¬
мые в предметной области, например правила налогообложения.7.1. Насколько полны приводимые примеры?Задачей этой книги является изучение объектного проектирования, анализа тре¬
бований в контексте описания прецедентов и объектно-ориентированного анализа, а
не изучение проблематики POS-систем или разработка конкретной системы1.Поэтому основной пример этой книги будет упомянут только в некоторых разде¬
лах, чтобы сохранить последовательность изложения материала, выделить основные
моменты и обеспечить быстрое продвижение вперед.7.2. Нужно ли детально анализировать требования
на начальной стадии разработки?Ответ на этот вопрос — нет. Унифицированный процесс разработки — это итера¬
тивный и эволюционный метод, предполагающий написание качественного кода и
его тестирование на начальных стадиях работы над проектом, задолго до полного
определения и анализа всех требований. Более того, требования определяются с уче¬
том обратной связи, полученной в результате программирования и тестирования.Однако исследования показывают, что очень важно выделить “горячую десятку”
высокоуровневых требований в самом начале работы. На начальной фазе стоит уде¬
лить время формулировке нефункциональных требований (в частности, к произво¬
дительности или надежности), поскольку они во многом определяют архитектурные
решения.Надежная спецификация - противоречивое словосочетаниеПриведенные ниже примеры требований могут вызвать иллюзию полноты и реа¬
листичности. Неспециалисты по разработке программных систем могут решить, что
на основе этих требований можно надежно спланировать проект и оценить необхо¬
димые затраты. Разработчикам из собственного опыта должно быть ясно, насколько
ненадежной является спецификация. Из литературы известно (например, [84, 117]),
что определяемые на ранних стадиях требования в пятидесяти процентах случаев ни¬
когда не используются в системе.1 Для нас важно не определить все требования, а описать процесс их определения.
Глава 7. Другие требования 137Ценность документа “Видение” и “Дополнительная спецификация” состоит в фор¬
мировании первого приближения требований к системе, определении главных идей
проекта. Однако эти документы нельзя считать надежной спецификацией. Реальные
требования можно сформулировать только после написания кода, его тестирования
и получения обратной связи от пользователей системы.Этот раздел не призывает отказаться от анализа и продумывания решений. Не
следует сразу же приступать к кодированию. Однако автор советует выделить общие
требования к системе, как можно раньше приступить к программированию, а значит,
как можно скорее получить обратную связь от пользователей.7.3. Нужно ли помещать документацию
на Web-узле проекта?Конечно, нужно. Приведенные в данной книге примеры и прецеденты являются
статическими и не предполагают последующих изменений. При разработке реальных
проектов всю документацию следует хранить на Web-узле, а не плодить статические
документы. Проектная документация может содержать гиперссылки, а также объ¬
екты, созданные не в текстовом редакторе или редакторе для электронных таблиц.
Например, многие документы можно хранить в инфраструктуре Wiki2.7.4. Пример NextGen: фрагмент
дополнительной спецификацииДополнительная спецификацияДаты внесения измененийВерсияДатаОписаниеАвторЧерновой начальный вариант10 января, 2031Первый черновой вариант. Будет
уточнен на стадии развитияКрэг ЛарманВведениеВ этом документе описаны все требования к POS-системе NextGen, не вошедшие в описание
прецедентов.Функциональность(Имеющая отношение ко многим прецедентам)Регистрация событий и обработка ошибокВсе ошибки регистрируются на постоянном носителе.Подключаемые бизнес-правилаНеобходимо обеспечить возможность настройки функциональности системы в различных точках
сценариев нескольких прецедентов (эти точки нужно определить) на основе заданных правил.
БезопасностьНеобходимо выполнять аутентификацию всех пользователей.2 Для знакомства с технологией Wiki обратитесь по адресу http://en.wikipedia.org/wiki/
WikiWiki.
138 Часть II. Начальная фазаУдобство использования
Человеческие факторыПользователь POS-системы будет работать с большим монитором, поэтому необходимо сле¬
дующее.• Текст должен быть виден с расстояния 1 м• Нужно избегать мерцающих цветовБыстрая, простая и корректная обработка информации — вот главные принципы системы авто¬
матизации торговли, поскольку пользователь хочет поскорее совершить покупку. В противном
случае ему не понравится этот магазин (и продавец).Кассир зачастую смотрит не на экран компьютера, а на покупателя или товары, поэтому пред¬
упреждающие сообщения нужно сопровождать звуковыми сигналами, а не только графически
отображать на экране.НадежностьВозможность восстановления информацииПри сбоях в работе внешних систем (службы авторизации платежей, бухгалтерской системы
и т.д.) нужно обеспечить возможность локальной обработки данных (их сохранение и последу¬
ющую передачу внешним системам). Этот вопрос требует более детальной проработки.ПроизводительностьКак указывалось выше, покупатель хочет сделать покупку как можно скорее. Задержка этого
процесса может быть связана с внешней службой авторизации. Наша задача — выполнить ав¬
торизацию не более чем за 1 минуту в 90% случаев.Возможности поддержки
Адаптация системыРазличные пользователи POS-системы NextGen могут устанавливать свои бизнес-правила для
обработки данных о продажах. Поэтому в нескольких заранее определенных точках сценария
(например, при инициализации новой продажи или при добавлении нового наименования то¬
вара) нужно обеспечить возможность подключения бизнес-правил.КонфигурированиеСетевые конфигурации различных пользователей POS-системы могут отличаться. Могут ис¬
пользоваться архитектуры “тонкого” и “толстого” клиентов, двухуровневые и многоуровневые
архитектуры и т.д. Кроме того, конфигурация ресурсов каждого клиента может изменяться
со временем, отражая производственные потребности и потребности в производительности.
Следовательно, система должна быть настраиваемой и отражать потребности пользователей.
Этот вопрос требует тщательной дополнительной проработки, изучения степени гибкости и
способов ее достижения.ОграниченияРуководство проекта NextGen настаивает на применении технологии Java, поскольку это улуч¬
шит возможности по поддержке системы и ее переходу на различные платформы, а также обе¬
спечит простоту разработки.Приобретаемые компоненты• Система вычисления налоговых платежей. Разрабатываемая система должна поддерживать
работу с подключаемыми внешними системами различных стандартов для разных стран.Бесплатные компоненты на основе открытого кодаВ целом, рекомендуется максимальное использование в этом проекте компонентов на основе
открытого кода в рамках Java-технологии.
Глава 7. Другие требования 139Несмотря на то, что пока преждевременно определять проектные решения, предлагаются сле¬
дующие варианты.• Каркас регистрации Jlog• ...ИнтерфейсыВажные интерфейсы и аппаратные средства• Сенсорный монитор (воспринимаемый операционной системой как обычный монитор; при¬
косновения обрабатываются как события мыши).• Лазерный сканер для считывания штрихкодов (обычно подключаемый к специальной клави¬
атуре; считанный код обрабатывается как последовательность нажатия клавиш).• Устройство для печати чеков.• Устройство считывания данных с кредитной/дебетной карточки.• Устройство считывания подписи (не в первой версии системы).Программные интерфейсыДля большинства внешних систем (вычисления налоговых платежей, системы складского уче¬
та, бухгалтерской системы и т.д.) необходимо обеспечить возможность подключения через
различные интерфейсы.Бизнес-правилаИмяПравилоВозможность измененияИсточникПРАВ1Правила вычисления скидок (примеры).
Работник компании — скидка 20%.
Привилегированный покупатель — 10%
Владелец “золотой” карточки — 15%Высокая вероятность из¬
менения. Каждая торговая
организация устанавливает
свои скидкиПолитика торго¬
вых организацийПРАВ2Правила вычисления торговых скидок
(на уровне транзакций). Применяются к
общей стоимости покупки (без вычета
налога). Примеры:- 10% общей стоимости покупки, если
стоимость превышает $100;- 5% по понедельникам;-10% для всех продаж с 10 до 15 часов
ежедневно;- 50% для всех продаж с 9 до 10 часов
сегодняВысокая вероятность из¬
менения. В каждой торговой
организации используются
свои правила, которые могут
изменяться ежедневно и
ежечасноПолитика торго¬
вых организацийПРАВЗПравила вычисления торговых скидок на
товары (на уровне наименований това¬
ров). Примеры:-10% на все тракторы на этой неделе;- при покупке двух единиц товара —
третья бесплатноВысокая вероятность из¬
менения. В каждой торговой
организации используются
свои правила, которые могут
изменяться ежедневно и
ежечасноПолитика торго¬
вых организацийВопросы законодательстваРекомендуется использование бесплатных компонентов на основе открытого кода, если их
разрешено использовать в коммерческих программных продуктах.Необходимо учитывать все необходимые налоги. Правила налогообложения могут изменяться
достаточно часто.
140 Часть II. Начальная фазаИнформация из предметной области
Ценовая политикаПомимо описанных выше правил ценообразования, каждому товару могут соответствовать
две цены: исходная и постоянная сниженная цена. Указанная цена товара (без вычисления по¬
ложенных скидок) соответствует постоянной сниженной цене, если таковая имеется. Однако
организации сохраняют исходную цену даже при наличии постоянной сниженной для бухгал¬
терской отчетности.Обработка платежей по кредитной и дебетной карточкеЕсли электронные платежи по кредитной или дебетной карточке подтверждены службой авто¬
ризации платежей, то за них несет ответственность эта служба, а не сам покупатель. Следова¬
тельно, для каждого платежа продавец должен зафиксировать получение денежных сумм от
службы авторизации. Обычно перевод денег за все выполненные в текущий день платежи на
счет торговой организации выполняется в ночное время, при этом за каждую транзакцию служ¬
ба взимает небольшой взнос.Вычисление налоговНалоги могут вычисляться по сложным схемам, и суммы отчислений могут часто изменяться на
правительственном уровне. Поэтому желательно возложить задачу вычисления налоговых пла¬
тежей на отдельную программу. Налоги могут взиматься городскими, региональными властями
или на уровне государства. Некоторые ставки налогов могут зависеть от категории покупателя
или назначения товара (например, товары для детей или фермеров).Идентификаторы товаров (UPC, EAN, SKU, штрихкоды и сканеры)Система NextGen должна поддерживать различные типы идентификаторов товаров. Наиболее
популярными системами идентификации товаров являются UPC (Universal Product Codes), EAN
(European Article Numbering) и SKU (Stock Keeping Units). Японская система JAN (Japanese
Article Number) является вариантом европейской версии EAN.В системе SKU идентификаторы товаров назначаются произвольным образом торговыми ор¬
ганизациями.Системы UPC и EAN имеют свои стандарты и регулируемые компоненты. Хорошее описание
ЭТИХ систем можно найти ПО адресам www.adamsl.com/pub/rus-sadam/upccode.html,
www.uc-council.org и www.ean-int.org.7.5. Дополнительная спецификация (комментарии)В дополнительной спецификации содержатся требования, ограничения и другая
информация, не вошедшая в описание прецедентов или словарь терминов, включая
атрибуты качества и специальные требования.Заметим, что нефункциональные требования, связанные с прецедентами, должны
быть представлены в описаниях прецедентов в разделе “Специальные требования”, од¬
нако некоторые предпочитают также включать их в дополнительную спецификацию.В дополнительную спецификацию можно включать следующие элементы.■ Требования согласно модели FURPS+ — функциональные, требования к удобству
использования, надежности, производительности и возможности поддержки.■ Отчеты.■ Ограничения на аппаратные и программные средства (операционные и сете¬
вые системы и т.д.).
Глава 7. Другие требования 141■ Ограничения, накладываемые на процесс разработки (например, процесс или
средства разработки).■ Другие ограничения проектирования или реализации.■ Международные соглашения (единицы измерения, языки и т.д.).■ Документация (пользовательская, руководство по установке и администрирова¬
нию) и справочная информация.■ Соглашения о лицензировании или другие юридические соглашения.■ Разбиение на пакеты.■ Стандарты (технические, обеспечения качества и безопасности).■ Физические требования к окружению (например, температурный режим экс¬
плуатации или ограничения на вибрацию).■ Операционные требования (например, способ обработки ошибок, частота ар¬
хивации).■ Бизнес-правила, относящиеся к данному приложению.■ Информация из предметной области (например, о полном цикле обработки
платежа по кредитной карточке).Атрибуты качестваНекоторые требования называются атрибутами качества (quality attribute) системы
[10]. К ним относятся удобство использования, надежность и т.д. Заметим, что это
качественные характеристики системы, а не самих атрибутов, которые необязатель¬
но должны обеспечивать высокое качество соответствующего процесса. Например,
возможности поддержки (качественная характеристика) могут быть низкими, если
данный программный продукт не предназначен для долгосрочной эксплуатации.Атрибуты качества (а значит, и дополнительная спецификация, в которой они
описываются) относятся к сфере интересов системного архитектора, поскольку (как
будет видно из главы 33) архитектурный анализ и проектирование подразумевают иденти¬
фикацию и обоснование атрибутов качества в контексте функциональных требований.Предположим, что одним из атрибутов качества системы NextGen должна быть ее
абсолютная надежность при сбоях внешних систем. С точки зрения архитектора, это
требование накладывает отпечаток на крупномасштабные проектные решения.Где описывать функциональность: в прецедентах
или дополнительной спецификацииНекоторые функции или свойства сложно описать в формате прецедентов. В 90-х
годах прошлого столетия автор работал в компании, занимающейся созданием агент¬
ных платформ и программного обеспечения среднего уровня на Java. В последующих
версиях (как и для большинства серверных программных продуктов) разработчики
не описывали функциональность в терминах прецедентов, поскольку это не имело
смысла. Они мыслили в терминах свойств (feature), например, “добавить поддержку
технологии EJB Entity Bean 1.0”.
142 Часть II. Начальная фазаУнифицированный процесс допускает определение требований в формате специ¬
фикации.Идеологи унифицированного процесса советуют (но не настаивают) использовать
описание прецедентов для определения функциональности. При этом такой формат
не всегда подходит для описания свойств системы.Бизнес-правилаБизнес-правила или правила предметной области определяют процессы в пред¬
метной области. Это требования не к конкретному приложению, а ко всем прило¬
жениям для данной предметной области. Типичными бизнес-правилами являются
политика компаний, а также физические или государственные законы. Более узкие
правила, относящиеся к данному приложению, например, правила вычисления ски¬
док, могут быть описаны в дополнительной спецификации.Информация из предметной областиЗачастую очень важно внести в дополнительную спецификацию некоторую ин¬
формацию из предметной области, имеющую отношение к разрабатываемой системе
(продажам и бухгалтерскому учету, геофизических свойствах потоков нефти, воды
или газа и т.д.) и позволяющую разработчикам глубже понять происходящие процес¬
сы. В этот раздел можно включать ссылки на литературу, мнения экспертов, форму¬
лы, законы и другие ссылки. Например, в раздел информации из предметной обла¬
сти можно включить начальные сведения о схемах кодирования UPC и EAN а также
штрихкодах, необходимые команде разработчиков системы NextGen.7.6. Пример для системы NextGen:
видение (фрагмент)Видение
Даты внесения измененийВерсияДатаОписаниеАвторЧерновой начальный вариант10 января, 2031Первый черновой вариант. Будет
уточнен на стадии развитияКрэг ЛарманВведениеНам видится надежное приложение автоматизации розничной торговли следующего поколения
(POS-система NextGen), обеспечивающее гибкую поддержку различных бизнес-правил, меха¬
низмы поддержки различных терминалов и интерфейсов пользователя, а также интеграцию с
различными внешними вспомогательными системами.Анализ в этом примере носит иллюстративный характер.
Глава 7. Другие требования 143Позиционирование
Экономические предпосылкиСуществующие программные продукты не обеспечивают настройку на потребности различных
пользователей, в частности добавление различных бизнес-правил или поддержку разных се¬
тевых архитектур (например, на основе “толстого” или “тонкого” клиента, двух-, трех- или че¬
тырехуровневые архитектуры). Кроме того, они плохо масштабируются. Ни одна из известных
систем не обеспечивает автоматический переход из интерактивного в автономный режим при
сбоях внешних систем. Отсутствует простая возможность интеграции с внешними системами.
Существующие системы не поддерживают новые терминальные технологии. Негибкость суще¬
ствующих систем открывает новую нишу на рынке программного обеспечения POS-систем.Формулировка проблемыТрадиционные POS-системы не обладают гибкостью, неустойчивы к сбоям и не обеспечивают
интеграцию с внешними системами. Это приводит к проблемам с оформлением продаж, несо¬
ответствию программного обеспечения экономическим потребностям предприятий, невозмож¬
ности точной и своевременной обработки данных и поддержки планирования. Эти проблемы
касаются кассиров, менеджеров по продажам, системных администраторов и руководителей
предприятий.Место системыУказать, для кого предназначена система, описать ее свойства и отличия от продуктов конку¬
рирующих организаций.Заинтересованные лицаНеобходимо определить> для кого предназначена система и каковы проблемы заинтересованных лиц.
Демографические особенности рынка...Заинтересованные лица, не являющиеся пользователями системы...Пользователи системы...Основные задачи высокого уровня и проблемы заинтересованных лицНеобходимо объединить информацию из списка исполнителей и задач, а также из раздела описания
прецедентов, отражающего потребности заинтересованных лиц.Однодневный семинар по определению требований с приглашением специалистов по предмет¬
ной области и заинтересованных лиц позволит выделить следующие основные цели и проблемы.Цель высокого
уровняПриоритетПроблемы и замечанияТекущиерешенияБыстрая, робастная и
интегрированная об¬
работка информации
о продажахВысокийС увеличением нагрузки скорость падает.
При выходе из строя компонентов не¬
возможно обрабатывать информацию о
продажах.Не хватает свежей и точной информации
от бухгалтерской и других систем из-за
отсутствия интеграции с существующи¬
ми бухгалтерскими системами, систе¬
мами складского учета и т.д. Усложняет
анализ и планирование.Невозможно настраивать бизнес-
правила с учетом особых требований.
Сложно добавлять новые типы термина¬
лов или интерфейсы пользователейСуществующие
POS-продукты
обеспечивают ба¬
зовую обработку
информации о
продажах, но не
решают все воз¬
никающие про¬
блемы
144 Часть II. Начальная фазаЗадачи уровня пользователяСюда можно включить список исполнителей и их задач, разработанный в процессе моделирования
прецедентов, либо более сжатую информацию.Пользователи (и внешние системы) используют данную систему в таких целях.• Кассир. Оформляет продажи, возврат товаров, регистрирует выручку.• Системный администратор. Управляет пользователями, безопасностью и системными та¬
блицами.• Менеджер. Осуществляет запуск и завершает работу системы.• Система анализа торговой деятельности. Анализирует данные о продажах.• ...Окружение...ОбзорПерспективы продуктаСистема NextGen обычно будет устанавливаться в магазинах, при использовании мобильных
терминалов они будут располагаться вблизи сети магазинов, либо внутри магазинов. Система
будет обслуживать пользователей и взаимодействовать с другими системами, как показано на
рис. Видение 1.Диаграмма строится на основе диаграммы прецедентов.Контекстные диаграммы можно строить в различных форматах с разной степенью детализации, но
все они отражают взаимодействие внешних исполнителей с системой.Кассир«исполнитель»
Система анализа
торговой
деятельностиСистемныйадминистратор«исполнитель»
Служба
авторизации
платежейВызываетслужбы-ИPOS-система
NextGenВызываетслужбы«исполнитель»у - ■ ►БухгалтерскаясистемаМенеджермагазина«исполнитель»
Система
складского
учета«исполнитель»
Система вычис¬
ления налоговых
платежей«исполнитель»
Система
учета
кадровРис. Видение 1. Контекстная диаграмма POS-системы NextGenПреимущества системыПодобно перечню исполнителей и их задач, в этой таблице указаны задачи, их решения и преимуще¬
ства, однако на более высоком уровне, чем при описании прецедентов.Здесь описывается основное значение и отличительные свойства продукта.
Глава 7. Другие требования 145СвойствоПреимущества для заинтересованных лицСистема будет обеспечивать всю основную
функциональность, необходимую торговым ор¬
ганизациям, включая обработку информации
о продажах, авторизацию платежей, оформле¬
ние возврата товаров и т.д.Быстрая работа торговых точек в автоматическом
режимеАвтоматическое выявление сбоев, переход в
автономный режим работыВозможность продолжения торговли при выходе
из строя внешних компонентовПодключаемые в различных точках сценария
бизнес-правилаГибкая настройка бизнес-логикиИнтерактивное взаимодействие с внешними
системами на основе стандартных протоколовСвоевременное и точное оформление продаж,
подготовка бухгалтерской документации и дан¬
ных складского учета, поддержка планированияПредположения и зависимости...Стоимость и ценообразование...Лицензирование и установка...Основные свойства системыКак было упомянуто выше, свойства системы описываются сжато путем перечисления основныхфункций.• Оформление продаж.• Авторизация платежей (по кредитной или дебетной карточке, чеком).• Системное администрирование и управление пользователями, безопасностью, таблицами
констант и кодов и т.д.• Автоматический переход в автономный режим работы при выходе из строя внешних си¬
стем.• Транзакции в реальном времени на основе промышленных стандартов с внешними систе¬
мами, включая бухгалтерскую систему, систему складского учета, учета человеческих ре¬
сурсов, вычисления налогов, службы авторизации платежей.• Определение и выполнение настраиваемых бизнес-правил в фиксированных точках выпол¬
нения сценариев.•Другие требования и ограниченияОграничения для процесса проектирования, удобства использования, надежности, производи¬
тельности, перечень документации и т.д. описаны в дополнительной спецификации и моделипрецедентов.7.7. Видение (комментарий)Очень хорошо, когда новому участнику проекта можно просто сказать: “Прочти
страницу 7 документа “Видение” на Web-узле проекта”. Очень удобно иметь краткое
описание проекта, чтобы сформировать единую позицию для его разработчиков.Документ “Видение” не должен быть длинным. Не следует пытаться описать все
требования в деталях. Он лишь должен обобщать модель прецедентов и дополни¬
тельную спецификацию.
146 Часть II. Начальная фазаОсновные высокоуровневые цели
и потребности заинтересованных лицВ этом разделе указываются задачи и проблемы более высокого уровня, чем при
описании прецедентов, а также нефункциональные цели, затрагивающие несколько
различных прецедентов, например следующие.■ Необходимо обеспечить бесперебойное оформление продаж.■ Необходимо обеспечить возможность корректировки бизнес-правил.Каковы основные проблемы и цели?В процессе определения высокоуровневых требований и целей большое внимание
уделяется групповой работе. Вот некоторые приемы групповой работы, облегчающие
процесс изучения проблемы и определения основных задач: построение диаграмм
Парето, многовариантное голосование, точечное голосование, номинальный груп¬
повой процесс, мозговой штурм и группировка по признаку подобия. Информацию
об этих и других приемах можно почерпнуть из Интернет. Автор предпочитает при¬
менять несколько перечисленных методик в процессе одного семинара для изучения
общих проблем и требований с разных точек зрения.Системные свойстваПрецеденты — не единственный способ выражения функциональных требований.
Это объясняется несколькими причинами.■ Их описания слишком подробны. Заинтересованные лица зачастую хотят ви¬
деть краткий перечень важных функций. Прецедентов должно быть не более
пятидесяти.■ Имена прецедентов могут не отражать важные свойства, представляющие ин¬
терес для пользователей. Уровень детализации при определении прецедентов
может не соответствовать уровню формулировки основных целей приложения.
Например, в описание прецедента Оформление продажи может входить функ¬
ция автоматической авторизации платежей. Тогда из списка имен прецедентов
не будет ясно, что система автоматически выполняет авторизацию платежей.■ Некоторые важные функции системы легче выразить в краткой форме без
привязки к именам прецедентов или задачам элементарных бизнес-процессов.
Например, на первом семинаре по определению требований для системы
NextGen один из участников может сказать: “Система должна обеспечивать пе¬
редачу данных существующим внешним системам бухгалтерского и складского
учета, а также обмен данными с системой вычисления налоговых платежей”.Следовательно, помимо прецедентов, функции системы можно выразить через ее
свойства, а точнее системные свойства (system features), представляющие собой высо¬
коуровневые, краткие утверждения, описывающие функции системы. Более строго в
контексте UP системное свойство определяется как “наблюдаемая извне и обеспечи¬
ваемая системой функция, которая напрямую удовлетворяет потребности заинтере¬
сованного лица” [81].
Глава 7. Другие требования 147Свойства — это то, что может делать система. Свойства можно облечь в следую¬
щую лингвистическую форму (и использовать ее в качестве теста).Система будет выполнять <свойство Х>.Например, система будет выполнять авторизацию платежей.Свойства отличаются от различных нефункциональных требований и ограниче¬
ний, например: “Система должна работать в операционной системе Linux и поддер¬
живать интерфейс с сенсорным экраном”. Обратите внимание, что это утверждение
не удовлетворяет требованиям лингвистического теста.Как сформировать список свойствВ большинстве случаев краткие высокоуровневые описания играют важную роль.Вот пример описания свойств высокого уровня для большого проекта, одним из
элементов которого является POS-система.К основным свойствам относятся следующие.■ Службы POSШ Управление запасами■ Торговля через Web■ ...Зачастую системные свойства организуют в двухуровневую иерархию, однако в до¬
кументе “Видение” сложная иерархия приводит к необходимости излишней детализа¬
ции. В этом документе описывается лишь основная функциональность, без ее пред¬
ставления в виде длинного списка деталей. Вот разумный пример детализации.К основным свойствам относятся следующие.■ Службы POS• Оформление продаж• Авторизация платежей• ...■ Управление запасами• Автоматическое переупорядочение• ...Сколько системных свойств нужно включить в документ “Видение”?СоветВ документ “Видение” желательно включать менее 10 свойств. Если их больше,
попробуйте сгруппировать некоторые из них и сформулировать на более высо¬
ком уровне абстракции.
148 Часть II. Начальная фазаДругие требования в документе “Видение”В документе “Ведение” системные свойства вкратце отражают функциональные
требования, которые более детально изложены в описании прецедентов. В этом до¬
кументе можно также отразить другие требования (например, к надежности и удоб¬
ству в использовании), которые более подробно описаны в разделе “Специальные
требования” модели прецедентов и в дополнительной спецификации. Однако здесь
возникает риск неоправданного дублирования.СоветСтарайтесь избегать дублирования требований в дополнительной спецификации
и документе “Видение”. Лучше сформулировать их только в дополнительной спе¬
цификации, а в документе “Видение” сделать ссылку на эти описания.Видение или прецеденты - что раньше?О порядке разработки артефактов говорить неуместно. Различные артефакты, от¬
носящиеся к требованиям, создаются параллельно. Тем не менее, можно порекомен¬
довать такую последовательность разработки.1. Создайте краткий черновой вариант документа “Видение”.2. Идентифицируйте задачи пользователей и соответствующие прецеденты.3. Опишите некоторые прецеденты и приступите к разработке дополнительной
спецификации.4. На основе полученной информации уточните документ “Видение”.7.8. Пример системы NextGen:
словарь терминов (фрагмент)Словарь терминов
Даты внесения измененийВерсияДатаОписаниеАвторЧерновой начальный вариант10 января, 2031Первый черновой вариант. Будет
уточнен на стадии развитияКрэг Ларман
Глава 7. Другие требования 149ОпределенияТерминОпределениеФорматПравиловерификацииСинонимТоварПродаваемый продукт или услугаАвторизацияплатежаПодтверждение гарантии оплаты от
внешней службы авторизации плате¬
жейЗапрос наавторизациюплатежаНабор элементов, отправляемых по
электронной почте службе авториза¬
ции платежей, обычно в виде массива
символов. К этим элементам относят¬
ся: идентификатор магазина, номер
счета покупателя, сумма платежа и
временная меткаUPCДвенадцатизначный числовой код для
идентификации продукта. Обычно он
представляется в виде штрихкода.
Более подробная информация со¬
держится ПО адресу http:\\www.uc-
council.orgДвенадцати¬
значный код,
состоящий из
нескольких
частейКод должен
содержать не
более двенад¬
цати цифрUniversalProductCode7.9. Комментарии: словарь терминовВ простейшем варианте словарь терминов (glossary) представляет собой список важ¬
ных понятий и их определение. Очень часто возникает ситуация, когда технический
или другой термин используется заинтересованными лицами в несколько различных
значениях. Такие противоречия необходимо разрешить для облегчения общения и
однозначной формулировки требований.СоветНачинайте разработку словаря терминов на ранних этапах выполнения проекта.Словарь терминов в роли словаря данныхВ рамках UP словарь терминов также играет роль словаря данных (data dictio¬
nary) — документа, содержащего информацию о данных, т.е. метаданные (metadata).
На начальной стадии проекта словарь терминов включает лишь основные термины и
их описание, а на стадии развития его можно превратить в словарь данных.К атрибутам терминов относятся следующие.■ Синонимы■ Описание■ Формат (тип, длина, единицы измерения)■ Взаимосвязи с другими элементами■ Диапазон значений■ Правила проверки корректности
150 Часть II. Начальная фазаОбратите внимание, что диапазон значений и правила проверки корректности в
словаре терминов соответствуют требованиям к поведению системы.Сложные терминыВ словарь терминов заносятся не только простейшие понятия, такие как “цена
товара”. В него необходимо включать и сложные элементы, например “продажа” (это
понятие включает в себя другие элементы, такие как дата и место продажи), а также
аббревиатуры, используемые для описания передачи данных между исполнителями
в рамках одного прецедента. Например, рассмотрим следующий фрагмент описания
прецедента Оформление продажи.Система отправляет запрос на авторизацию платежа внешней службе авториза¬
ции платежей и запрос на подтверждение платежа.Термин “запрос на авторизацию платежа” обозначает набор данных, содержание
которых необходимо пояснить в словаре терминов.7.10. Пример для системы NextGen: бизнес-
правила (правила предметной области)Правила предметной области
Даты внесения измененийВерсияДатаОписаниеАвторЧерновой начальный вариант10 января, 2031Первый черновой вариант. Будет
уточнен на стадии развитияКрэг ЛарманБизнес-правила(См. также правила для данного приложения в дополнительной спецификации.)IDПравилоЧастота измененияИсточникПРАВ1Для платежей по кредитной карточке
требуется подписьПодпись покупателя будет нужна, но че¬
рез 2 года большинство пользователей
захотят применять цифровое устройство
для ввода подписи, а через пять лет мо¬
жет понадобиться поддержка уникаль¬
ной цифровой закодированной подписи,
введенной в настоящее время в СШАПолитика
практиче¬
ски всех
служб ав¬
торизации
платежейПРАВ2Правила вычисления налоговых
платежей. С продаж отчисляются на¬
логи. Правила налогообложения из¬
ложены в официальных документахВысокая вероятность изменения.
Законы налогообложения изменяются
ежегодно на правительственном уровнеЗаконПРАВЗПри возврате товара, купленного по
кредитной карточке, возврат денег
осуществляется не наличными, а пу¬
тем перевода на кредитную карточкуНизкая вероятность измененияПолитика
компаний
авториза¬
ции пла¬
тежей
Глава 7. Другие требования 1517.11. Бизнес-правила (комментарии)Правша предметной области (domain rule) [60, 109] определяют процессы, проис¬
ходящие в предметной области. Это требования не к конкретному приложению, а ко
всем приложениям для данной предметной области. Типичными примерами правил
предметной области являются политика компаний, а также физические или государ¬
ственные законы.Эти правила зачастую называются бизнес-правилами (business rule), но этот термин
нельзя назвать удачным, поскольку большинство программных систем решает не про¬
блемы бизнеса, а совершенно другие задачи, например, моделируют погоду или про¬
цессы логистики. Правила предметной области в системе прогнозирования погоды
связаны с физическими законами и сложными математическими моделями, оказыва¬
ющими влияние на требования к приложению.Правила предметной области удобно выделить и записать в отдельном документе
в рамках унифицированного процесса, получившем название “Бизнес-правила”.Бизнес-правила влияют на другие требования к системе, обычно определяемые
прецедентами, поскольку они проясняют многие неясные при описании прецедентов
моменты. Например, если при описании прецедента Оформление продажи кому-то
взбредет в голову осуществлять платежи по кредитной карточке без подписи покупа¬
теля, то такая возможность будет пресечена наличием бизнес-правила, учитывающе¬
го требования служб авторизации платежей (ПРАВ1).7.12. Эволюция требований в итеративном
процессе разработкиКак уже многократно повторялось (это очень важный момент, о котором часто за¬
бывают), итеративные методы, включая UP, не предполагают выполнения детального
анализа на начальной стадии выполнения проекта. Требования к системе изменяются
со временем в результате тестирования разработанных элементов системы. Поэтому
обратная связь с пользователями во многом влияет на изменение спецификации.Как и в предыдущей главе, в табл. 7.1 представлены примеры артефактов и вре¬
мя их создания в рамках процесса UP. Начало разработки артефактов, связанных с
определением требований, приходится на начальную фазу и продолжается на стадии
развития.Начальная фазаЗаинтересованные лица должны решить, стоит ли проводить серьезные исследо¬
вания, т.е. приступать к этапу развития. На начальной стадии в документе “Видение”
описываются идеи, позволяющие принять решение о целесообразности продолже¬
ния работы над проектом.Поскольку основная работа по определению требований приходится на фазу раз¬
вития, то на начальном этапе дополнительная спецификация только начинает раз¬
рабатываться. В ней освещаются важные качественные показатели (например, воз¬
можность восстановления данных системы при выходе из строя внешних служб),
определяющие основные риски в процессе разработки системы.Создание артефактов можно начать на семинаре по определению требований.
152 Часть II. Начальная фазаТаблица 7.1. Пример планирования сроков реализации артефактов UP
(н — начало, р — развитие)ДисциплинаАртефактИтерациямНачалоИРазвитиеЕ1..ЕпКонструи- Передача
рование Т1..Тп
С1..СпБизнес-моделированиеМодель предметной областинТребованияМодель прецедентовнРВидение системынРДополнительная спецификациянРСловарь терминовнРБизнес-правиланРПроектированиеМодель проектирования
Описание архитектурыннРМодель данныхнРФаза развитияНа стадии развития уточняется видение системы на основе обратной связи от
пользователей и разработчиков различных частей системы. При этом на нескольких
итерациях разработки проводятся семинары по определению требований.В процессе итеративной разработки требования все более проясняются и зано¬
сятся в дополнительную спецификацию.К моменту завершения фазы развития завершается и работа над описанием пре¬
цедентов, составлением дополнительной спецификации и документа “Видение”, кото¬
рые теперь отражают основные свойства и другие требования. Это не означает, что
по завершении фазы развития дополнительную спецификацию и документ “Видение”
нужно заморозить и не изменять в дальнейшем. Напомним, что основным “лейтмо¬
тивом” итеративной разработки и UP является возможность постоянной адаптации
системы.Поясним эту мысль подробнее. По завершении фазы развития целесообразно со¬
гласовать с заинтересованными лицами задачи следующего этапа проекта и разрабо¬
тать соглашение (возможно, письменное) относительно требований и графика их
реализации. В какой-то момент (в рамках UP — по завершении фазы развития) необ¬
ходимо точно знать “что, когда и сколько”. В этом смысле формальное соглашение о
требованиях к системе является нормальным и целесообразным. Необходимо также
определить процесс управления изменениями (одна из лучших идей UP), предполага¬
ющий формальное рассмотрение и одобрение вносимых изменений, а не хаотичную
и бесконтрольную модификацию.Поэтому приходим к следующим выводам.■ В рамках итеративной разработки и UP в детально проработанную специфика¬
цию требований могут вноситься незначительные изменения. Эти изменения
могут затрагивать свойства системы, обеспечивающие ее конкурентоспособ¬
ность или улучшающие функциональность.i
Глава 7. Другие требования 153■ В рамках итеративной разработки основное внимание уделяется получению
обратной связи от заинтересованных лиц и реализации проекта в нужном на¬
правлении. Благодаря этому заинтересованные лица не могут “умыть руки” и
ожидать в стороне реализации “замороженного” набора требований в окон¬
чательном программном продукте. При “замораживании” требований система
вряд ли будет отражать реальные потребности заинтересованных лиц.Фаза конструированияНа этапе конструирования основные требования (как функциональные, так и не¬
функциональные) остаются стабильными, но это не означает, что они не могут незна¬
чительно изменяться. Однако дополнительная спецификация и документ “Ведение”
не претерпевают существенных изменений.7.13. Дополнительные ресурсыВ большинстве книг по архитектуре программных систем описывается процесс
анализа требований и атрибутов качества приложения, поскольку эти атрибуты
оказывают влияние на архитектуру системы. Примером такой литературы является
[10].Бизнес-правила подробно описываются в [109]. В этой книге подробно изложена
обширная теория формулировки бизнес-правил, однако предложенный метод не свя¬
зан с другими современными приемами анализа требований, такими как прецеденты
или итеративная разработка.В рамках UP работа над документами “Видение” и “Дополнительная специфика¬
ция” относится к дисциплине определения требований и начинается на семинарах
по определению требований наряду с анализом прецедентов. Хорошей книгой по ор¬
ганизации семинаров является Requirements by Collaboration: Workshops for Defining Needs
Эллен Готтесдинер (Ellen Gottesdiener).В Интернет содержится множество ресурсов, посвященных процессу RUP, и ша¬
блонов для создания артефактов, описанных в данной главе. В частности, подобные
шаблоны можно найти по адресу readyset.tigris.org.
ЧастьIIIПервая итерация фазы
развития — основыВ этой части...Глава 8. Итерация 1 — основыГлава 9. Модели предметной областиГлава 10. Системные диаграммы последовательностейГлава 11. Описание операцийГлава 12. Итеративный переход от анализа требований
к проектированиюГлава 13. Логическая архитектура и диаграммы пакетов UMLГлава 14. Переход к объектному проектированиюГлава 15. Диаграммы взаимодействия на UMLГлава 16. Диаграммы классов UMLГлава 17. GRASP: проектирование объектов на основе
распределения обязанностейГлава 18. Примеры объектного проектирования на основе
шаблонов GRASPГлава 19. Области видимостиГлава 20. Преобразование проектного решения в программный код
Глава 21. Разработка на основе тестирования и рефакторинг
Итерация 1 — основыТвердое и жесткое ломается. Гибкое торжествует.Тао Те Чинг (Тао Те Ching)Основные задачи■ Определить первую итерацию стадии развития.■ Обосновать содержание последующих глав этой части.■ Описать ключевые понятия начальной фазы и стадии развития.ВведениеВ этой главе анализируются требования для первой итерации разработки рассма¬
триваемых в книге примеров систем, а затем кратко обсуждаются особенности на¬
чальной фазы и стадии развития. Анализ требований важен для понимания следую¬
щих глав книги, посвященных этой итерации. В остальной части главы описываются
сведения, необходимые для понимания итеративного процесса разработки.Что дальше?ПрецедентыО После определения остальных требований (кроме прецедентов) в данной главе
рассматриваются виды деятельности для итерации 1. Следующая глава посвящена
построению объектно-ориентированной модели предметной области, которая
иллюстрирует наиболее важные понятия из предметной области/\ДругиетребованияТребования
итерации 1МоделированиепредметнойобластиСистемныедиаграммыпоследова¬тельностей
158 Часть III. Первая итерация фазы развития — основы8.1. Требования и акценты первой итерации:
основные вопросы ООА/ПНа первой итерации стадии развития рассматриваемых примеров основное вни¬
мание уделяется фундаментальным вопросам ООА/П и построения объектной систе¬
мы. Конечно же, для построения программной системы необходимо рассмотреть и
множество других вопросов, таких как разработка базы данных, исследование удоб¬
ства использования и проектирование интерфейса пользователя. Однако эти вопро¬
сы выходят за рамки основ ООА/П и применения UML.Итерации в книге и в реальном проектеИтерация 1 процесса разработки рассматриваемых в книге примеров систем но¬
сит учебный характер и не соответствует первой итерации разработки реального
проекта. Здесь не рассматриваются архитектурно важные вопросы или моменты,
связанные с устранением максимальных рисков. В унифицированном процессе
сначала решаются жизненно важные для проекта задачи. Однако в контексте кни¬
ги для лучшего понимания фундаментальных принципов ООА/П и UML мы нач¬
нем с более простых вопросов.POS-система NextGenНиже перечислены требования для первой итерации POS-системы NextGen.■ Реализация базового сценария прецедента Оформление продажи — ввод наиме¬
нований товара и оплата наличными.■ Реализация прецедента Запуск системы, поскольку он необходим для инициа¬
лизации основного сценария этой итерации.■ Никакие сложные сценарии не реализуются, зато простой успешный сценарий
доводится до программной реализации.■ Взаимодействие с внешними службами, такими как база данных продуктов и си¬
стема вычисления налогов, не реализуется.■ Сложные правила ценообразования не применяются.Проектируются и реализуются также некоторые элементы интерфейса пользова¬
теля и базы данных. Однако эти вопросы раскрываются без детализации.Игра “Монополия”Приведем требования для первой итерации разработки приложения “Монополия”.■ Реализация базового сценария прецедента Играть в игру Монополия: игроки
перемещаются по клеточкам доски.■ Реализация прецедента Запуск системы, поскольку он необходим для инициа¬
лизации основного сценария этой итерации.■ В игре могут принимать участие от двух до восьми игроков.
Глава 8. Итерация 1 — основы 159■ Игра состоит из последовательности раундов. В течение раунда каждый игрок
делает один ход и перемещается по часовой стрелке на количество клеток, рав¬
ное сумме очков, выпавших на двух кубиках.■ Игра длится в течение двадцати раундов.■ После вбрасывания кубиков на экране появляется имя игрока и выпавшие зна¬
чения. После перемещения игрока на заданное количество ячеек отображается
имя игрока и конечная клетка перемещения.■ На первой итерации не учитываются деньги, не выявляется победитель, не про¬
изводится покупка или продажа недвижимости и не решаются другие вопросы
данной игры.■ Все клетки поименованы. Каждый игрок начинает свой путь с поля Старт.
Следующие клетки пронумерованы по порядку: Поле 1, Поле 2, ..., Поле 39.■ Игра функционирует в режиме эмуляции. От пользователя требуется ввести
лишь количество игроков.Дальнейшая функциональность будет наращиваться на последующих итерациях.Особенности инкрементальной разработкиЗаметим, что требования к первой итерации являются подмножеством полного на¬
бора требований или прецедентов. Например, требования к первой итерации раз¬
работки приложения NextGen являются упрощенной версией полного прецедента
оформления продажи. Они описывают простой сценарий с оплатой наличными.Отметим также, что при итеративной разработке сразу не анализируются все тре¬
бования к разрабатываемой системе. Детально рассматриваются только вопросы, от¬
носящиеся к реализации одного прецедента.В этом состоит основная идея итеративных методов разработки, таких как UP
или ХР. Полноценное кодирование и тестирование выполняются для подмножества
требований, а сама разработка начинается до завершения процесса анализа требова¬
ний. В этом состоит основное отличие итеративных методов от каскадного процесса
разработки.Инкрементальная разработка одного и того же
прецедента в течение нескольких итерацийЗаметим, что на первой итерации реализуются не все требования прецедента
Оформление продажи. Зачастую работа над различными сценариями одного и того
же прецедента выполняется в течение нескольких итераций (рис. 8.1). В то же время
короткие, простые прецеденты могут быть полностью реализованы в течение одной
итерации.
160 Часть III. Первая итерация фазы развития — основы/ / / / /123/Прецедент Прецедент Прецедент
Оформление Оформление Оформление
продажитпродажиПрецедентОформлениекредитаРегистрациясвойствПрецедент или свойство
слишком сложны для полной
реализации на одной
короткой итерацииТаким образом, различные
части сценариев должны
быть распределены
по различным итерациямРис. 8.1. Реализация прецедента в течение нескольких итераций8.2. Начальная фаза и стадия развитияПредположим, мы завершили начальную фазу разработки и приступили к стадии
развития.Что сделано на начальной стадииНа начальную фазу проекта POS-системы NextGen выделялась неделя. Созданные
на этой стадии артефакты должны быть краткими и неполными, поскольку этот этап
длится очень недолго.Начальная фаза — это короткий шаг к стадии развития. На этой стадии нужно
лишь уяснить для себя основные риски, масштаб задачи, ее реалистичность и решить,
стоит ли приступать к серьезным исследованиям, т.е. к этапу развития. В предыдущих
главах были рассмотрены не все виды деятельности, выполняемые на начальной ста¬
дии. Основное внимание уделялось лишь вопросам определения требований. К числу
видов деятельности и артефактов начальной фазы относятся следующие.■ Краткий семинар по определению требований.■ Выделение основных исполнителей, задач и прецедентов.■ Описание большинства прецедентов в сжатом формате. Полное описание
10-20% прецедентов для более глубокого понимания масштаба и сложности за¬
дачи.■ Идентификация наиболее важных требований, связанных с высокими рисками.■ Разработка первой версии документов “Видение” и “Дополнительная специфи¬
кация”.
Глава 8. Итерация 1 — основы 161■ Составление списка рисков.• Например, руководство проекта очень хочет получить демонстрационную
версию продукта к началу выставки POSWorld в Гамбурге, т.е. за 18 месяцев.
Однако без более глубокого исследования нельзя даже примерно оценить не¬
обходимые для этого ресурсы.■ Технические прототипы, обеспечивающие обоснование концепции, а также
другие исследования достижимости конкретных требований (корректно ли ра¬
ботает Java Swing с сенсорными экранами?).■ Разработка прототипа интерфейса пользователя для выявления функциональ¬
ных требований.■ Формулировка рекомендаций по использованию компонентов на стадии разви¬
тия (что нужно приобрести, разработать или повторно использовать).• Например, может понадобиться приобрести пакет вычисления налоговых
платежей.■ Разработка высокоуровневой примерной архитектуры и предложений по исполь¬
зованию компонентов.• Это не детальное описание архитектуры, претендующее на корректность или
окончательный вариант. Это лишь краткие размышления относительно на¬
чальной точки исследований на стадии развития. Например: “Будем исполь¬
зовать клиентское приложение Java без сервера приложений, а в качестве
базы данных выберем Oracle...”. На стадии развития эти идеи могут быть под¬
держаны или отвергнуты.■ Разработка плана первой итерации.■ Составление списка необходимых средств.Фаза развитияФаза развития (elaboration) — это первая последовательность итераций, в течение
которых решаются следующие задачи.■ Реализуются и тестируются базовые архитектурные элементы.■ Изучается и стабилизируется большая часть требований.■ Обосновываются и устраняются основные риски.На этой стадии команда разработчиков выполняет серьезные исследования ба¬
зовых элементов архитектуры, их реализацию (написание программного кода и его
тестирование), определяет для себя большинство требований и снимает вопросы,
связанные с наиболее высокими рисками. В контексте UP термин “риск“ имеет эко¬
номическое значение. То есть, на ранних этапах реализации проекта должны разра¬
батываться сценарии, достаточно важные, но не обязательно сопряженные с техни¬
ческим риском.Фаза развития зачастую состоит из 2-4 итераций, каждая из которых длится от
двух до шести недель. Время каждой итерации жестко фиксировано. Если поставлен¬
ные задачи сложно выполнить к назначенному сроку, то некоторые требования пере¬
носятся на последующие итерации, чтобы данная итерация завершилась вовремя и в
результате был получен устойчивый и протестированный код.6 Зак. 3357
162 Часть III. Первая итерация фазы развития — основыФаза развития — это не стадия проектирования или подготовки к реализации, как
было принято в рамках каскадного процесса (в стиле “водопада”).На этой стадии создаются не прототипы, а полностью разрабатывается некото¬
рый фрагмент системы. В некоторых описаниях UP для представления части систе¬
мы используется термин архитектурный прототип (architectural prototype), который
может быть неверно истолкован. В данном случае прототип — это не эксперименталь¬
ный образец, а рабочее подмножество окончательной системы. Эту часть системы
также называют исполняемой архитектурой (executable architecture), или архитектурной
основой (architectural baseline).Коротко о фазе развитияК фазе развития относятся: построение базовой архитектуры, разрешение высо¬
ких рисков, определение большинства требований и оценка общего графика реа¬
лизации и необходимых ресурсов.Приведем некоторые основные идеи и рекомендации по реализации стадии раз¬
вития.■ Планирование кратких итераций, связанных с основными рисками.■ Раннее начало программирования.■ Адаптивное проектирование, реализация и тестирование основных элементов
архитектуры.■ Раннее, частое и реалистичное тестирование.■ Адаптация системы на основе обратной связи от специалистов по тестирова¬
нию, пользователей и разработчиков.■ Подробное описание большинства прецедентов и других требований, проведе¬
ние серии семинаров, по одному на каждой итерации.Какие артефакты реализуются на стадии развития?В табл. 8.1 приводится примерный список артефактов, разработка которых может
начинаться на этапе развития. Некоторые из этих артефактов подробнее рассма¬
триваются в последующих главах, в частности модель предметной области и модель
проектирования. В эту таблицу не включены артефакты, начало разработки которых
приходится на начальную фазу. Заметим, что их создание не завершается на одной
итерации, а продолжается в течение нескольких итераций.Таблица 8.1. Пример артефактов фазы развитияАртефакт КомментарийМодель предметной области Она представляет собой визуализацию понятий предметнойобласти, напоминающую статическую модель сущностей
предметной областиМодель проектирования Это набор диаграмм, описывающих логику проектного реше¬ния. Сюда относятся диаграммы программных классов, диа¬
граммы взаимодействия объектов, диаграммы пакетов и т.д.
Глава 8. Итерация 1 — основы 163
Окончание табл. 8.1АртефактКомментарийОписание программной архитектурыЭто документ, в котором рассмотрены основные архитектур¬
ные моменты и способы их реализации. В нем приводятся
основные идеи проектного решения и обосновывается их
целесообразность для данной системыМодель данныхВключает схему базы данных и стратегию отображения
объектов в необъектное представлениеПрототипы интерфейса пользователяОписание интерфейса пользователя, способов навигации и т.д.Вы не поняли, что такое фаза развития, если...■ Для большинства проектов она длится дольше, чем несколько месяцев.■ Она содержит лишь одну итерацию (за редким исключением).■ Большинство требований определено до начала фазы развития.■ На этом этапе не затрагиваются базовые архитектурные элементы и элементы
с высокими рисками.■ В результате реализации этой фазы не получен реальный выполняемый код.■ Эта фаза рассматривается в основном как стадия формулировки требований,
предшествующая стадии реализации.■ Делаются попытки разработки полного и точного проектного решения до на¬
чала программирования.■ Обратная связь и адаптация задействованы минимально, пользователи редко
привлекаются для оценки системы.■ Отсутствует раннее и реалистичное тестирование.■ Архитектура системы разработана до начала программирования.■ Эта фаза рассматривается как этап проверки концепции, а не как этап реализа¬
ции ядра системы.Если налицо подобные признаки, значит, разработчики не понимают назначения
стадии развития и придерживаются устаревшего каскадного подхода к разработке.8.3. Планирование следующей итерацииПланирование и управление проектом — очень важные, но глобальные задачи.
Некоторые основные моменты этих видов деятельности будут рассмотрены в этой
главе, а более детальное их описание приводится в главе 40.Требования и итерации систематизируются в соответствии с рисками, границами
и критичностью.■ Риск (risk) — это техническая сложность или другой фактор, например отсут¬
ствие информации о необходимых затратах или ресурсах.■ Границы (coverage) — на начальных итерациях нужно определить все основные
части системы, т.е. выполнить реализацию множества компонентов “не вглубь,
а вширь”.
164 Часть III. Первая итерация фазы развития — основы■ Критичность (criticality) — требуется реализовать функции, имеющие важное
значение для системы.Эти критерии используются для распределения работы по итерациям. Прецеденты
или их отдельные сценарии ранжируются с целью определения приоритетов при ре¬
ализации. На начальных итерациях реализуются прецеденты с высоким рейтингом.
Некоторые требования выражаются как высокоуровневые свойства системы, не свя¬
занные с прецедентами, например служба регистрации событий. Такие требования
тоже ранжируются.Ранжирование выполняется перед началом первой итерации, затем перед нача¬
лом второй и т.д. Такой план является адаптивным, а не зафиксированным на началь¬
ной стадии проекта. Требования обычно группируют следующим образом.ПриоритетТребование(прецедент или свойство)КомментарийВысокийОформление продажиСамый высокий приоритетРегистрацияСложно добавить позднееСреднийПоддержка пользователейВлияет на безопасностьНизкийНа основе такого ранжирования можно выделить архитектурно важные сценарии
прецедента Оформление продажи, которые необходимо реализовать на начальных
итерациях. Этот список не полон, в нем нужно отразить и остальные требования.
Кроме того, на каждой итерации в явном или неявном виде реализуется прецедентЗапуск системы.
Модели предметной областиЭто очень хорошо на практике, но теоретически оно никогда не будет работать.Неизвестный управленецОсновные задачи■ Идентифицировать классы понятий (концептуальные классы), соот¬
ветствующие требованиям текущей итерации.■ Создать исходную модель предметной области.■ Определить соответствующие атрибуты и ассоциации.ВведениеМодель предметной области — это самая важная модель объектно-ориентирован¬
ного анализа.1 Она отображает основные (с точки зрения моделирующего) классы
понятий (концептуальные классы) предметной области. В этой главе описывается
процесс объектно-ориентированного анализа и проектирование с помощью системы
обозначений UML. Базовые понятия являются тривиальными, но по ходу изложения
будут даны полезные рекомендации, касающиеся построения модели, самостоятель¬
ное изучение которых может занять недели и месяцы. В этой главе приводятся на¬
чальные сведения о создании моделей предметной области. Более подробно вопросы
моделирования предметной области освещаются в главе 32.1 Прецеденты — это важные артефакты этапа анализа требований, но на самом деле они не
являются объектно-ориентированными. Они концентрируют внимание разработчиков на про¬
цессах, происходящих в предметной области.
166 Часть III. Первая итерация фазы развития - основыЧто дальше?ДругиетребованияПосле определения работ для итерации 1 в данной главе исследуется частичная
модель предметной области. В следующей главе рассматриваются операции
для системы, которая описана в сценариях прецедентов, сформулированных
в процессе проектирования на данной итерации/\Требования
итерации 1МоделированиепредметнойобластиСистемныедиаграммыпоследова¬тельностей—о—ОписанияоперацийКак и все артефакты унифицированного процесса разработки, модель предмет¬
ной области является необязательной. Основные артефакты этой модели показаны
на рис. 9.1.Бизнес-модели-рованиеПример взаимодействия артефактов UP
Модель предметной области\Sale1 1..*SalesLineltemquantitydateJКонцептуальны классы -
термины, атрибуты
понятий, ассоциации'Объекты предметной
области, атрибуты
и ассоциации, состояние
которых изменяется\Опреде-требо-ванийМодель прецедентов iОформление продаж1. Покупатель подходит3. Кассир вводит
идентификатор товара.
4....ПрецедентыОперация:enterltem(...)Постусловия:ДиаграммыописанияоперацийпоследовательностейСловарьУточнение
некоторых
терминов
из предметной
областиКонцептуальные
классы из модели
предметной
области
в процессе
проектирования
определяют
имена некоторых
программных
классовМодель проектированияПроекти¬рованиеV:Register:ProductCatalog:Saleenterltem
(itemID, quantity)spec = getProductSpec( itemID )addLineItem( spec, quantity )Puc. 9.1. Пример взаимосвязи артефактов UP
Глава 9. Модели предметной области 167Каждой итерации соответствует своя модель предметной области, отражающая
реализуемые на данном этапе сценарии прецедентов. Таким образом, модель пред¬
метной области эволюционирует в процессе разработки системы. Модель предмет¬
ной области связана с моделью проектирования, особенно программными объекта¬
ми, относящимися к уровню предметной области. Основные понятия этой модели
отражаются в словаре терминов.9.1. ПримерНа рис. 9.2 представлен фрагмент модели предметной области в виде диаграммы
классов. Из рисунка ясно, что с точки зрения предметной области концептуальными
классами (conceptual class) являются Payment (Платеж) и Sale (Продажа). Как вид¬
но из диаграммы, эти понятия связаны между собой, и понятию Sale соответствуют
определенная дата и время.Рис. 9.2. Фрагмент модели предметной области - визуальный словарьДиаграмма классов в обозначениях UML обеспечивает концептуальную перспек¬
тиву модели.Идентификация набора концептуальных классов — основная задача объектно-ори¬
ентированного анализа. На начальных итерациях построение модели предметной об¬
ласти у опытного разработчика может занять всего лишь несколько часов, но на по¬
следующих этапах, когда требования к системе определяются более четко, уточнение
модели предметной области потребует значительно больше времени.СоветИзбегайте попыток построить полную модель предметной области на начальных
этапах разработки. Такой стиль был присущ каскадному процессу разработки, когда
модель предметной области строилась на этапе анализа без учета обратной связи.
168 Часть III. Первая итерация фазы развития — основы9.2. Что такое модель предметной областиОсновной составляющей объектно-ориентированного анализа или исследования
является декомпозиция проблемы на отдельные классы понятий (концептуальные
классы) или объекты.Модель предметной области — это визуальное представление концептуальных классов
или объектов реального мира в терминах предметной области [50, 94]. Такие модели
называют также концептуальными моделями (именно этот термин был принят в первом
издании этой книги), моделями объектов предметной области, или объектными моделями
анализа.2Основная идеяМодель предметной области представляет классы понятий реального мира, а не
программные компоненты. Это не набор диаграмм, описывающих программные
классы или программные объекты с их обязанностями.В контексте UP модель предметной области3 — это один из артефактов, создаваемых
в рамках дисциплины бизнес-моделирования. Более точно: модель предметной области
в рамках UP является конкретизацией более общего понятия модели бизнес-объектов (busi¬
ness object model — BOM), обеспечивающей представление понятий, играющих важную
роль в данной предметной области [112]. Таким образом, подобная модель описыва¬
ет понятия одной предметной области, например, связанные с розничной торговлей.
В более сложных случаях модель ВОМ является мультидисциплинарной моделью и
описывает предметную область, включающую множество подобластей.На языке UML модель предметной области представляется в виде набора диаграмм
классов, на которых не определены никакие операции. Модель предметной области
может отображать следующее.■ Объекты предметной области или концептуальные классы.■ Ассоциации между концептуальными классами.■ Атрибуты концептуальных классов.Почему модель предметной области
называют визуальным словаремОбратимся еще раз к рис. 9.2. На нем представлены некоторые понятия или кон¬
цептуальные классы предметной области и связи между ними. На самом деле здесь
показаны абстракции (abstraction) концептуальных классов, поскольку с каждой про¬
дажей, реестром и другим понятием связано множество свойств и характеристик.2 Они также связаны с моделями взаимоотношений концептуальных сущностей, отображаю¬
щими только концептуальное представление предметной области, однако интерпретируемыми
в более широком смысле как модели данных для разработки баз данных. Модели предметной
области — это не модели данных.3 В данном случае термин модель предметной области начинается с прописной буквы, чтобы
акцентировать внимание на том, что это официальная модель, определенная в рамках UP, а не
просто обычное понятие.
Глава 9. Модели предметной области 169Данная модель отображает обобщенное представление или абстракцию и не учиты¬
вает неинтересные (с точки зрения моделирующего) детали.Представленную на диаграмме (в системе обозначений UML) информацию можно
также выразить в виде словесного описания, терминов словаря и т.д. Однако элемен¬
ты и их взаимосвязи легче представить на этом визуальном языке, поскольку одним
из преимуществ человеческого интеллекта является хорошая способность обработки
визуальной информации.Таким образом, модель предметной области можно рассматривать как визуальный
словарь важных абстракций или словарь предметной области.Концептуальная модель — это не модель
программных компонентовКак видно из рис. 9.3, модель предметной области — это результат визуализации
понятий реального мира в терминах предметной области, а не программных элемен¬
тов, таких как классы Java или C# (рис. 9.4). Следовательно, в модели предметной об¬
ласти не используются следующие элементы.■ Артефакты программирования наподобие окон или базы данных, если только
разрабатываемая система не является моделью программного средства, напри¬
мер моделью графического интерфейса пользователя.■ Обязанности или методы4.SaleВизуализация реального ^
понятия из предметной
области.Это не программный классdateTimeРис. 9.3. Модель предметной области отображает по¬
нятия реального мира, а не программные классы<9✓SalesDatabaseПрограммный ^
артефакт, а не часть
модели предметной
областиo SaleПрограммныйdateо* класс, а не частьtimeмодели предметнойобластиprint()Рис. 9.4. Модель предметной области не отображает программные артефакты или классы4 В объектном моделировании обязанности обычно связаны с программными компонента¬
ми. Методы — это тоже сугубо программные понятия. Однако модель предметной области опи¬
сывает понятия реального мира, а не программные компоненты. Обязанности рассматривают¬
ся на стадии проектирования и не являются частью данной модели.
170 Часть III. Первая итерация фазы развития — основыДва традиционных значения термина
“модель предметной области”В UP и в данной главе рассматривается концептуальная перспектива объектов
реального мира, а не их программная реализация. Однако в некоторых языках про¬
граммирования, особенно в языках, возникших на заре развития объектно-ориенти¬
рованного подхода в 1980-е годы (например, SmallTalk), термин “модель предметной
области” относят к программным объектам уровня предметной области. Этот уровень
расположен ниже уровня представления и интерфейса пользователя. К нему отно¬
сятся программные объекты, представляющие понятия предметной области и соот¬
ветствующую бизнес-логику. Объекты этого уровня называют объектами предметной
области, программный класс Board с методом getSquare ().Какое определение является более корректным? Наверное, оба. Этот термин ис¬
пользуется в различных сообществах специалистов и означает разные понятия.Автору приходилось быть свидетелем путаницы, возникающей из-за использова¬
ния данного термина в разных контекстах без объяснения его значения.В данной книге, чтобы не было недоразумений, вместо термина “модель предмет¬
ной области”, относящегося к описанию программных объектов, будет использовать¬
ся словосочетание “уровень объектов предметной области”.Концептуальные классыМодель предметной области иллюстрирует концептуальные классы или словарь
предметной области. Неформально: концептуальный класс — это представление идеи
или объекта. Если говорить более строго, то концептуальный класс можно рассма¬
тривать в терминах символов, содержания и расширения [94] (рис. 9.5).■ Символы (symbol) — слова или образы, представляющие концептуальный класс.■ Содержание (intension) — определение концептуального класса.■ Расширение (extension) — набор примеров, к которым применим концептуаль¬
ный класс.Например, рассмотрим концептуальный класс для события осуществления по¬
купки. Его можно обозначить символом Sale. Содержанием этого понятия является
“представление события осуществления покупки в определенный день и определен¬
ное время”. В качестве расширения можно рассматривать все примеры покупок (дру¬
гими словами, все множество покупок).Модели предметной области и данныхМодель предметной области не является моделью данных (data model), к которой по
определению относятся данные, сохраняемые на постоянном носителе, поскольку не¬
известно, нужно ли сохранять в базе данных информацию о классах. Концептуальные
классы могут вообще не содержать атрибутов и играть в предметной области чисто
поведенческую, а не информационную роль.
Глава 9. Модели предметной области 171Sale О--datetimeОбозначениепонятия"Продажа представляет
событие, связанное
с приобретением товаров.
С ним ассоциируются
дата и время.”СущностьпонятияРасширениепонятияРис. 9.5. Концептуальному классу соответствуют символ, содержание и расширение9.3. Зачем создавать модель предметной областиХотелось бы поделиться с читателями историей, которую я многократно рас¬
сказывал своим слушателям. В начале 1990-х годов я работал в группе специалистов
по созданию информационной системы для похоронного бюро на языке Smalltalk в
Ванкувере (можете себе представить модель предметной области). Я не имел ника¬
кого представления о процессах, поэтому постарался построить модель предметной
области, чтобы лучше познакомиться с основными понятиями и словарем.Мы также захотели создать объекты уровня предметной области на языке Smalltalk.
Таким образом, мы потратили несколько часов на создание модели предметной обла¬
сти с единственной целью идентифицировать ключевые понятия, не заботясь о ее
программной реализации. Затем эти термины, такие как “сервис”, мы использовали
в качестве имен программных классов уровня предметной области, реализованных
на языке Smalltalk.Такое подобие имен объектов позволяет уменьшить брешь между ментальным
представлением предметной области и его программной реализацией.Приближение программной реализации к реальному
прототипу с помощью объектного моделированияКлючевая идея объектного подхода состоит в том, чтобы имена программных
классов уровня предметной области соответствовали названиям ключевых понятий
модели предметной области. Эта идея проиллюстрирована на рис. 9.6. Она позволя¬
ет сократить разрыв между нашими ментальными и программными моделями. Такой
подход является не просто философским принципом. Он имеет практическое значе¬
ние. Например, исходный код программы, написанный в 1953 году, имеет примерно
следующий вид.10000101010000011010101010100001010101000001010101010. . .
172 Часть III. Первая итерация фазы развития — основыКак специалист в области компьютерных наук, читатель должен понимать, что
этот код работает. Однако он бесконечно далек от основных концепций предмет¬
ной области. Это существенно усложняет модификацию и поддержку программ.
Объектное моделирование позволяет сократить этот разрыв.Объектная технология обеспечивает элегантность проектирования, а также про¬
стое расширение и масштабирование систем. Этот тезис подтверждается при изуче¬
нии всего материала книги. Однако сокращение этого разрыва является полезным,
но второстепенным преимуществом. Гораздо важнее возможность управления слож¬
ностью и обеспечения простоты изменения и расширения программной системы.Модель предметной области в рамках UPПонятия предметной области с точки зрения заинтересованных лицВ модели предметной ^области Payment — это понятие,
а в модели проектирования
Payment представляет собой
программный класс. Эти
сущности отличны друг от друга,
однако первая из них оказывает
влияние на имя и определение
второй.Такой подход позволяет
сократить разрыв между
ментальными и программными
моделями.Это одна из наиболее важных
идей объектной технологииPayment( \1 Оплачивает 1SaleV )' amountdatetimeВлияют
на имена
объектовPaymentО amount: MoneygetBalance(): Money1 Оплачивает 1
К МSaledate: DatestartTime:TimegetTotal():MoneyМодель проектирования в рамках UPПри создании программных классов разработчик объектно-
ориентированной системы учитывает понятия из предметной области.Таким образом, удается сократить разрыв между представлением
заинтересованных лиц о понятиях предметной области
и представлением этих понятий в программном обеспеченииРис. 9.6. Сокращение разрыва в представлениях при использовании объектного моделирования9.4. Как создать модель предметной областиДля создания модели предметной области на данной итерации выполните следу¬
ющие действия.1. Выделите концептуальные классы (следуя приведенным ниже рекомендациям).2. Отобразите их в модели предметной области в виде классов на диаграмме
UML.3. Добавьте необходимые ассоциации и атрибуты (см. ниже разделы “Ассоциации”
и “Атрибуты”).
Глава 9. Модели предметной области 1739.5. Как выделить концептуальные классыОсновная проблема построения модели предметной области состоит в выделении
концептуальных классов.Три стратегии идентификации концептуальных классовВ следующих разделах представлены три способа выявления концептуальных
классов.1. Повторное использование или модификация существующих моделей. Это са¬
мый первый, наилучший и обычно, простейший подход, с которого автор всег¬
да старается начать процесс выделения концептуальных классов. В литературе
описаны модели многих предметных областей и модели данных, которые мож¬
но трансформировать в модели предметной области. Такие модели существуют
для области финансов, здравоохранения и т.п.2. С использованием списка категорий концептуальных классов.3. На основе выделения существительных.Первый метод является наилучшим, но в данной книге он не будет описываться
подробно ввиду его очевидности. Второй метод тоже является достаточно полез¬
ным.Метод 2: использование списка категорий
концептуальных классовПриступая к созданию модели предметной области, целесообразно составить спи¬
сок кандидатов на роль концептуальных классов. В табл. 9.1 содержится множество
стандартных категорий, которые обычно имеют важное значение. В этом перечне
они приводятся в произвольном порядке и не упорядочены по степени важности.
Примеры взяты из предметной области системы торговли, резервирования авиаби¬
летов и игры “Монополия”.Таблица 9.1. Список категорий концептуальных классовКатегория концептуальных классовПримерыТранзакцииSale (Продажа), Payment (Платеж),Рекомендации: эти классы особенно критичны,
поскольку зачастую описывают финансовые опера¬
ции, поэтому процесс выделения концептуальных
классов следует начать именно с нихReservation (Резервирование)Элементы транзакцийРекомендации: транзакции зачастую состоят из
элементовSalesLineltem (Элемент продажи)Товары или службы, связанные с транзакциями илиItem (Элемент),их элементамиFlight (Рейс),Рекомендации: транзакции выполняются над неко¬
торыми элементами (товарами или службами)Seat (Место)
174 Часть III. Первая итерация фазы развития — основыОкончание табл. 9.1Категория концептуальных классовПримерыМеста записи транзакцийRegister (Реестр),Рекомендации: очень важная категорияFlightManifest (Расписание полетов)Роли людей или организации, связанные с транзак¬Cashier (Кассир),циями. Исполнители прецедентовCustomer (Покупатель),Рекомендации: необходимо знать, кто участвуетstore (Магазин),в транзакцииMonopolyPlayer (Игрок)
Pilot (Пилот)
Passenger (Пассажир)Места транзакцийstore (Магазин),
Airport (Аэропорт),
Plane (Самолет),
Seat (Место)Важные события, для которых необходимо хранитьSale (Продажа), Payment (Платеж),время и местоMonopolyGame (Монополия),
Flight (Полет)Физические объектыRegister (Реестр),Рекомендации: такие объекты обычно соответству¬Airplane (Самолет),ют программным системам, предназначенным дляItem (Товар),управления или моделированияBoard (Доска),Die (Игральная кость)Описание объектовProductDescription (Спецификация товара),
FlightDescription (Описание полета)КаталогиProductCatalog (Каталог товаров),Рекомендации: описание зачастую приводится
в каталогеFlightCatalog (Каталог рейсов)Контейнеры других объектов (физических илиStore (Магазин), Bin (Бункер),информационных)Airplane (Самолет), Board (Доска)Содержимое контейнеровItem (Элемент),Square (Клетка на доске),
Passenger (Пассажир)Другие системы, внешние по отношению к даннойCreditAuthorizationSystem (Система авто¬системеризации кредитных платежей),AirTrafficControl (Система управления
движением)Записи финансовой, трудовой, юридическойReceipt (Чек), Ledger (Гроссбух),и другой деятельностиMaintenanceLog (Журнал обслуживания)Финансовые инструментыLineOfCredit (Кредитная линия),
Cash (Наличные), Check (Чек)руководства, документы, статьи, книги, на которые DailyPriceChangeList (Бюллетень ежеднев-
ссылаются в процессе работы ного изменения цен),RepairManual (Руководство по восстановлению)
Глава 9. Модели предметной области 175Метод 3: определение концептуальных классов
на основе выделения существительныхЕще один полезный (и очень простой) прием идентификации концептуальных
классов на основе лингвистического анализа предлагается в [1]. Он состоит в выде¬
лении существительных из текстовых описаний предметной области и их выборе в
качестве кандидатов в концептуальные классы или атрибуты.5СоветЭтот метод следует применять с осторожностью. Между существительными и
концептуальными классами нет взаимно однозначного соответствия, а слова есте¬
ственного языка могут иметь по несколько значений.Тем не менее это информация к размышлению. Для реализации подобного под¬
хода удобно использовать развернутые описания прецедентов, например основной
сценарий прецедента Оформление продажи.Основной успешный сценарий (или основной процесс)1. Покупатель подходит к кассовому аппарату POS-системы с выбранными товарами.2. Кассир открывает новую продажу.3. Кассир вводит идентификатор товара.4. Система записывает наименование товара и выдает его описание, цену и общую стои¬
мость. Цена вычисляется на основе набора правил.Кассир повторяет действия, описанные в пп. 3-4 для каждого наименования товара.5. Система вычисляет общую стоимость покупки с налогом.6. Кассир сообщает покупателю общую стоимость и предлагает оплатить покупку.7. Покупатель оплачивает покупку, система обрабатывает платеж.8. Система регистрирует продажу и отправляет информацию о ней внешней бухгалтерской
системе (для обновления бухгалтерских документов и начисления комиссионных)и системе складского учета (для обновления данных).9. Система выдает товарный чек.10. Покупатель покидает магазин с чеком и товарами (если он что-то купил).Расширения (или альтернативные потоки)7а. Оплата наличными1. Кассир вводит предложенную покупателем сумму.2. Система вычисляет положенную сдачу и открывает кассу с наличностью.3. Кассир складывает поученные деньги и выдает сдачу покупателю.4. Система регистрирует платеж наличными.5 В настоящее время лингвистический анализ существенно усложнился. Его часто называют
моделированием естественного языка [95].
176 Часть III. Первая итерация фазы развития — основыМодель предметной области — это визуализация важных понятий из словаря пред¬
метной области. Откуда брать необходимые термины? Из описания прецедентов. Эти
описания — богатый источник для идентификации существительных.Одни из этих существительных могут быть представлены в виде концептуальных
классов, другие могут представлять концептуальные классы, не имеющие отношения
к данной итерации (например, “бухгалтерская система” или “комиссионные”), а тре¬
тьи — в виде атрибутов этих концептуальных классов. Более подробная информация
о различиях между концептуальными классами и атрибутами содержится в следую¬
щем разделе и следующей главе.Недостатком данного подхода является выразительность естественного языка.
Для описания одного и того же концептуального класса или атрибута могут исполь¬
зоваться различные существительные, и в то же время некоторые существительные
могут иметь по несколько значений. Тем не менее этот подход рекомендуется исполь¬
зовать в сочетании с методом выбора понятий по списку категорий.9.6. Пример выделения концептуальных классовКандидатуры на роль концептуальных классов
для предметной области торговлиПользуясь списком категорий и методом анализа словесного описания, мы соста¬
вили список кандидатур на роль концептуальных классов для предметной области роз¬
ничной торговли. Он соответствует требованиям и принятым упрощениям для основ¬
ного сценария прецедента Оформление продажи, реализуемого на первой итерации.Sale CashierCashPayment CustomerSalesLineltem StoreItem ProductDescriptionRegister ProductCatalogLedgerHe существует понятия “правильный” список. Это просто произвольный набор
абстракций и понятий из словаря предметной области, которые, по мнению разра¬
ботчика модели, являются важными. Тем не менее, если для выделения концептуаль¬
ных классов использовать описанные выше стратегии, то различные специалисты по
моделированию составят примерно одинаковые списки.На практике обычно сразу строят диаграмму концептуальных классов UML (рис. 9.7).RegisterItemStoreSaleSalesLineltemCashierCustomerLedgerCashProductProductPaymentCatalogDescriptionРис. 9.7. Начало построения диаграммы предметной области для приложения NextGen
Глава 9. Модели предметной области 177Вопросы добавления атрибутов и ассоциаций рассматриваются в последующих
разделах.Концептуальные классы в предметной
области игры “Монополия”На основе списка категорий и выделения существительных можно сформулиро¬
вать перечень кандидатур на роль концептуальных классов для первой итерации сце¬
нария Игра в Монополию (рис. 9.8). В этом модельном примере основное внимание
сконцентрировано на важных физических объектах предметной области.9.7. Построение диаграммы классов в рамках
гибкого процесса разработкиОбратите внимание на стиль построения диаграмм классов UML на рис. 9.8.
Изображения классов справа и снизу не ограничены. Это дает возможность наращи¬
вать содержимое классов путем добавления элементов. На рисунке изображения клас¬
сов расположены по несколько в ряд для обеспечения компактности. При построе¬
нии диаграммы классов на доске в одной строке следует размещать один класс.9.8. Автоматизированное построение модели
в рамках гибкого подхода к разработкеНа начальных стадиях развития проекта можно упустить важные концептуальные
классы и выявить их позднее на этапе проектирования или программирования. В кон¬
тексте гибкого подхода к разработке целью построения модели предметной области
является быстрое понимание и получение грубого приближения ключевых понятий.
В процессе моделирования не ставится задача точно отразить состояние предметной
области, поскольку сами модели “живут” не долго (обычно их рисуют на доске, а в
скором времени стирают). С этой точки зрения модель не требует поддержки или
обновления. Однако это не значит, что модель не нужно усовершенствовать.
178 Часть III. Первая итерация фазы развития — основыЕсли вы хотите поддерживать модель в актуальном состоянии, то следует перери-
сгаать ее с доски с помощью специальных компьютерных средств построения моде¬
ли либо сразу же строить модель на компьютере и отображать ее для своих коллег
с помощью проектора. Однако сразу задайте себе вопрос: кто и зачем будет исполь¬
зовать обновленную модель? Если вы не находите практического ответа на этот во¬
прос, не огорчайтесь. Зачастую важные понятия предметной области отражаются в
программном обеспечении на уровне логики приложения, а модель предметной обла¬
сти, построенная в процессе объектно-ориентированного анализа, в виде отдельного
артефакта не нужна.9.9. Элементы отчета: включать ли
понятие “товарный чек” в модельТоварный чек — это документ, принимающий участие в продаже товара и его опла¬
те. Он может рассматриваться как концептуальный класс из предметной области.
Возникает вопрос: нужно ли его включать в модель предметной области?Для ответа на этот вопрос необходимо учитывать следующие факторы.■ Товарный чек — это своеобразный отчет о сделанной покупке. В принципе в
модель предметной области не следует включать объекты отчета, поскольку вся
содержащаяся в них информация получена из других источников. Это является
одной из причин исключения понятия “чек” из модели предметной области.■ Товарный чек выполняет конкретную роль при реализации бизнес-правил:
обычно он обеспечивает право на возврат товара. Этот фактор говорит в поль¬
зу включения товарного чека в модель предметной области.Поскольку возврат товара не рассматривается на данной итерации разработки,
понятие Receipt (Товарный чек) не включается в модель предметной области. Оно
будет включено в модель системы на той итерации разработки, на которой будет ре¬
ализовываться прецедент Возврат товара.9.10. Имена и модели: стратегия построения картПри построении моделей предметной области применяется та же стратегия, что
и при создании карт.СоветМодель предметной области следует создавать согласно принципам картографии.■ Использовать применяемые на данной территории названия. Например, при раз¬
работке модели библиотеки в качестве понятия, означающего потребителя, следу¬
ет выбрать Borrower (Читатель), т.е. использовать терминологию библиотекарей.■ Исключать несущественные детали. Например, в модели предметной области,
создаваемой на первой итерации разработки игры “Монополия”, карточки не ис¬
пользуются. Поэтому на этой итерации в модель не включается элемент Card
(Карточка).■ Не добавлять объекты, которые отсутствуют на данной территории.
Глава 9. Модели предметной области 179Этот принцип называют также стратегией использования словаря предметной области
[34].9.11. Как моделировать “нереальный” мирПредметная область некоторых приложений имеет очень слабое отношение к
реальному миру. Примерами таких приложений могут быть системы телекоммуни¬
каций. Для подобных систем тоже можно создавать модели предметной области, но
для этого требуется высокая степень абстракции и отход от стандартных принципов
разработки.Например, в качестве концептуальных классов, связанных с предметной облас¬
тью системы телекоммуникаций, могут выступать Message (Сообщение), Connection
(Соединение), Dialog (Диалог), Road (Маршрут) и Protocol (Протокол).9.12. Типичная ошибка при выделении
концептуальных классовВозможно, наиболее типичной ошибкой при создании модели предметной обла¬
сти является причисление некоторого объекта к атрибутам, в то время как он дол¬
жен относиться к концептуальным классам. Чтобы избежать этой ошибки, следует
придерживаться простого правила.СоветЕсли некоторый объект X в реальном мире не является числом или текстом, зна¬
чит, это скорее концептуальный класс, чем атрибут.Например, является ли store (магазин) атрибутом объекта Sale (Продажа) или
отдельным концептуальным классом Store?SaleИЛИ...?SaleStorestorephoneNumberВ реальном мире магазин не является числом или текстом, он представляет ре¬
альную сущность, организацию, занимающую некоторое место. Следовательно, Store
нужно рассматривать в качестве концептуального класса.В качестве другого примера рассмотрим предметную область системы резервиро¬
вания авиабилетов. Нужно ли рассматривать место назначения как атрибут destina¬
tion понятия Flight (Полет) или как отдельное понятие Airport (Аэропорт)?Flightили...?FlightAirportdestinationname
180 Часть III. Первая итерация фазы развития - основыВ реальном мире аэропорт места назначения не является ни текстом, ни числом:
это массивный объект, занимающий определенное пространство. Следовательно, в
модели предметной области он должен быть представлен понятием Airport.9.13. Когда использовать классы описанийКласс описания (description class) содержит информацию о свойствах некоторо¬
го объекта. Например, класс ProductDescription может содержать описание цены,
внешнего вида и свойств объекта Item. Такой принцип проектирования классов опи¬
сывается шаблоном Item-Descriptor (Элемент-Описание) [33].Зачем использовать классы описанийРассматриваемые в данном разделе вопросы, на первый взгляд, могут показать¬
ся достаточно частными. Однако необходимость использования классов описаний
возникает для множества различных предметных областей. На этом и будет сделан
основной акцент.Примем следующие допущения.■ Термин Item (Товар) представляет физический товар в магазине, а значит, он
может иметь серийный номер.■ Понятию Item соответствуют описание, цена и идентификатор, которые более
нигде не записываются.■ Каждый сотрудник магазина страдает амнезией.■ При каждой продаже реального физического товара удаляется соответствую¬
щий программный экземпляр Item.Что произойдет при выполнении следующего сценария при сделанных предпо¬
ложениях?В магазине повысился спрос на новую разновидность вегетарианских горячих
бутербродов ObjectBurger. Идет бойкая торговля, и при продаже каждого объекта
ObjectBurger экземпляр Item удаляется из памяти компьютера.Однако возникает проблема, связанная с тем, что никто не может ответить на во¬
прос “Сколько стоит ObjectBurger?”, поскольку его цена связана с каждым экземпля¬
ром, который удаляется из памяти в случае его продажи.Заметим также, что при программной реализации описанной модели происхо¬
дит дублирование данных, и память используется неэффективно, поскольку описа¬
ние, цена и идентификатор товара связаны с каждым экземпляром одного и того же
товара.Описанная проблема иллюстрирует необходимость использования понятий,
представляющих собой описание (иногда называемое спецификацией) других
объектов. Для решения этой проблемы необходимо ввести концептуальный класс
ProductDescription (Описание товара), содержащий информацию о товаре.
Понятие ProductDescription не совпадает с понятием Item, а представляет собой
лишь описание этого товара (рис. 9.9).Конкретный экземпляр Item представляет собой физический объект, имеющий се¬
рийный номер. При этом объект ProductDescription серийного номера не имеет.
Глава 9. Модели предметной области 181Переходя от концептуальной модели к программной реализации, заметим, что
даже после продажи всех единиц товара и удаления из памяти всех программных эле¬
ментов Item понятие ProductDescription остается в памяти компьютера.Классы описаний обычно используются при описании предметной области, свя¬
занной с продажами, товарами или услугами. Они также часто используются при опи¬
сании производства, для обозначения отличий одних производимых товаров от дру¬
гих. Эти понятия идентифицируются одними из первых, поскольку являются очень
типичными.Itemdescriptionpriceserial number
itemIDХужеProductDescriptiondescription
price
itemIDОписываетItemЛучшеserial numberPuc. 9.9. Описания других понятий. Символ * означает “множественную” связь и указывает
на то, что одно понятие ProductDecription может описывать много (*) понятий ItemКогда требуются классы описанийСоветКласс описания (например, ProductDescription) вводится в таких случаях.■ Существует необходимость описания элементов или служб независимо от суще¬
ствования конкретных экземпляров этих объектов.■ Если удаление экземпляров описываемых им понятий (например, Item) при¬
водит к потере важной информации в связи с некорректной ассоциацией этой
информации с удаляемым экземпляром.■ Если при наличии понятия устраняется дублирование информации.Описания объектов для предметной области авиаполетовВ качестве следующего примера рассмотрим авиакомпанию, которая пострадала в
связи с крушением одного из ее самолетов. Предположим, что все рейсы этой авиа¬
компании отменены на шесть месяцев до завершения расследования причин авиака¬
тастрофы. Предположим также, что после отмены рейсов все программные объекты
Flight (Полет) были удалены из памяти компьютера.
182 Часть III. Первая итерация фазы развития — основыЕсли сведения о полетах связаны только с экземплярами объектов Flight, кото¬
рые представляют конкретные рейсы, выполняемые в конкретное время, то после
крушения самолета в авиакомпании не останется никакой информации об осущест¬
вляемых ею рейсах.Для решения этой проблемы необходимо ввести понятие Flight Description
(Описание полета), описывающее абстрактный рейс без привязки к дате и времени
(рис. 9.10).Рис. 9.10. Описания объектовОбратите внимание, что последний пример относится к услугам (полетам), а не
к товарам (вегетарианским горячим бутербродам). Описания услуг играют не менее
важную роль.В качестве следующего примера рассмотрим телекоммуникационную компанию
по продаже пакетов услуг мобильной телефонной связи наподобие “бронзовый”, “зо¬
лотой” и т.д. Такой компании необходимо описание пакета (некоторый текст, описы¬
вающий стоимость минуты разговора, поддержку выхода в Интернет, стоимость этой
услуги и т.д.). Его нужно хранить отдельно от реально проданных пакетов (например,
пакет “золотой” продан Крэгу Ларману 1 января 2047 года за $55 в месяц). С точки
зрения маркетологов, для описания этой услуги понятие MobileCommunicationsPac
kageDescription нужно определить еще до начала продаж реальных пакетов.9.14. АссоциацииВ процессе разработки модели предметной области необходимо идентифицировать
связи (ассоциации) между концептуальными классами, удовлетворяющие информацион¬
ным требованиям разрабатываемых на текущей итерации сценариев, а также выделить
те из них, которые способствуют лучшему пониманию модели предметной области.
Глава 9. Модели предметной области 183Ассоциация (association) — это отношение между классами (или точнее, экземпля¬
рами этих классов), отражающая некоторое значимые и полезные связи между ними
(рис. 9.11).В языке UML ассоциации описываются как “семантические взаимосвязи между
двумя или несколькими классификаторами и их экземплярами”.АссоциацияО"'"*Записывает текущуюSale11Рис. 9.11. АссоциацииПоиск ассоциацийЗаслуживающие внимания ассоциации обычно содержат знания о взаимосвязи
между объектами, которые должны сохраняться в течение некоторого периода. Этот
период может измеряться в миллисекундах или годах в зависимости от конкретного
контекста. Другими словами, о связи между какими объектами нужно помнить?Например, нужно ли помнить о том, что экземпляры объекта SalesLineltem
(Элемент продажи) ассоциированы с экземпляром объекта Sale (Продажа)?
Очевидно да, поскольку в противном случае будет невозможно восстановить данные
о продаже, распечатать товарный чек или вычислить итоговую сумму.Возникает еще один вопрос: нужно ли сохранять информацию о связи между те¬
кущим экземпляром объекта Sale и Ledger (Главная книга) для удобства бухгалтер¬
ского учета?Ответы на эти вопросы зависят от реальной ситуации в предметной области, а не
просто диктуются потребностями программной системы.При реализации игры “Монополия” необходимо помнить о том, какому игроку
принадлежит каждое поле. Нужно также помнить о том, какие поля содержатся на
конкретной доске.С другой стороны, нет необходимости помнить о том, что сумма набранных оч¬
ков при бросании игральных костей определяет количество шагов при перемещении
фишки. Это правило действует, однако вряд ли стоит запоминать значения всех сде¬
ланных ходов. Аналогично, кассир может просмотреть описание товара, но нет не¬
обходимости запоминать каждый конкретный факт такого просмотра.СоветВ модель предметной области целесообразно включать следующие ассоциации.■ Ассоциации, знания о которых нужно сохранять в течение некоторого перио¬
да (важные ассоциации).■ Ассоциации, производные от содержащихся в списке стандартных ассоциа¬
ций.
184 Часть III. Первая итерация фазы развития - основыПочему следует сокращать количество ассоциацийСледует избегать добавления лишних ассоциаций в модель предметной области.
Обращаясь к дискретной математике, несложно провести следующие вычисления.
Если имеется граф с 2Vузлами, то между ними можно установить iV*(iV-l)/2 ассоциа¬
ций, а это может быть достаточно большое число. Если модель предметной области
содержит 20 классов, то их можно связать с помощью 190 линий ассоциаций. Многие
линии связей такой диаграммы будут просто вносить визуальный шум и ухудшать ее
наглядность. Поэтому при добавлении ассоциаций нужно придерживаться принципа
минимализма. Для выделения важных ассоциаций следует руководствоваться крите¬
риями, приведенными в этой главе.Будут ли ассоциации реализованы в программном кодеЛинии ассоциаций в модели предметной области не описывают потоки данных,
внешние ключи баз данных, переменные экземпляров или связи между объектами в
программной реализации. Такие ассоциации следует рассматривать лишь в концепту¬
альном ракурсе — как связь в реальной предметной области.Многие из этих связей будут реализованы в программном обеспечении (как в мо¬
дели проектирования, так и в модели данных). Однако модель предметной области —
это не модель данных. Добавляемые к ней ассоциации позволяют лишь лучше понять
взаимосвязи между объектами, но не отражают структуры данных.Обозначение ассоциаций в языке UMLАссоциация обозначается проведенной между классами линией, с которой связа¬
но определенное имя, начинающееся с большой буквы (рис. 9.12).На концах линии, которая обозначает ассоциацию, могут содержаться выраже¬
ния, определяющие количественную связь между экземплярами классов.Обычно ассоциация является двунаправленной. Это означает, что от одного объек¬
та любого типа возможен логический переход к другому объекту. Такой переход яв¬
ляется абсолютно абстрактным. Он не определяет тип взаимосвязей между програм¬
мными сущностями.Дополнительная стрелка рядом с именем ассоциации указывает, в каком направле¬
нии нужно читать ее имя. Она не определяет направление видимости или перемеще¬
ния. Если такая стрелка отсутствует, то имена ассоциаций следует читать с использо¬
ванием общепринятых соглашений, а именно — слева направо и сверху вниз. Однако
в языке UML в явной форме это правило отсутствует (рис. 9.12).ВниманиеСтрелка направления чтения не имеет семантического значения. Она лишь указы¬
вает направление чтения диаграмм.
Глава 9. Модели предметной области 185- “Стрелка направления чтения”.- Она не означает ничего другого,
кроме направления чтения имени
ассоциации.- Зачастую опускается.Рис. 9.12. Система обозначения ассоциаций в языке UMLКак именовать ассоциации в UMLСоветИмена ассоциаций базируются на формате ИмяТипа-ГлагольнаяФраза-ИмяТипа, где
глагольная фраза представляет собой последовательность, которая читается и яв¬
ляется значимой в контексте модели.Не следует использовать простые имена ассоциаций типа Имеет (Has) или
Использует (Uses), поскольку это не проясняет взаимосвязи между объектами пред¬
метной области. Приведем примеры.■ Sale Paid-by CashPayment (Sale Оплачивается CashPayment)• Плохой пример (не улучшающий понимание) Sale Uses CashPayment (Sale
Использует CashPayment)■ Player Is-on Square (Player Находится-на Square)• Плохой пример (не улучшающий понимание) Player Has Square (Player
Имеет Square)Имена ассоциаций должны начинаться с прописной буквы, поскольку ассоциация
обычно представляет классификатор связей между экземплярами. В языке UML имя
классификатора начинается с прописной буквы. Для имен ассоциаций принято ис¬
пользовать два формата.■ Records-Current (с дефисом)■ RecordsCurrent (без дефиса)РолиКаждый конец ассоциации называется ролью (role). Роль дополнительно может
иметь следующие характеристики.
186 Часть III. Первая итерация фазы развития — основы■ Кратность■ Имя■ Направление связиВ следующем разделе будет рассмотрена кратность.КратностьКратность (multiplicity) определяет, сколько экземпляров класса А может быть ас¬
социировано с одним экземпляром класса В (рис. 9.13).Кратность ролиРис. 9.13. Кратность ассоциацииНапример, один экземпляр класса Store (Магазин) может быть ассоциирован с
несколькими (ни с одним или с несколькими, что отображается символом *) экзем¬
плярами класса Item.Некоторые примеры кратных ассоциаций представлены на рис. 9.14.Нуль или больше;
“много”Один или большеОт одного до сорокаРовно 5Ровно 3,5 или 8Рис. 9.14. Значения кратностиЗначение кратности определяет, сколько экземпляров одного класса может быть
корректно связано с экземпляром другого класса в некоторый конкретный момент,
а не на всем промежутке времени. Например, некий подержанный автомобиль че¬
рез определенные промежутки времени может быть многократно продан одному и
тому же продавцу подержанных автомобилей. Однако в каждый конкретный момент
этот автомобиль продан только одному владельцу. Автомобиль не может быть про¬
дан нескольким владельцам одновременно. Аналогично, в странах, подчиняющихся
Глава 9. Модели предметной области 187законам моногамии, каждый человек в конкретный момент может состоять в браке
только с одним супругом, хотя в течение длительного промежутка времени он может
вступать в брак неоднократно.Значение кратности зависит от интересов разработчика модели и программы, по¬
скольку ограничения предметной области должны быть отражены в программном
обеспечении. На рис. 9.15 приводится пример подобной ситуации с разъяснениями.или0..1ОКакую кратность использовать: “Г или “0..Г?Ответ зависит от целей, преследуемых в процессе моделирования. Обычно на практике
кратность обусловлена ограничениями из предметной области, которые нужно учитывать
в программе, если эта связь отражена в программных объектах или базе данных. Например,
определенный товар может быть куплен или списан, и, следовательно, он больше не будет
храниться в магазине. С этой точки зрения логично использовать кратность “0..Г, однако...Внимательно ли вы продумали этот аспект? Если эта связь реализована в программе, то
необходимо обеспечить связь экземпляра каждого программного объекта item с определенным
экземпляром store. В противном случае в программных компонентах возникает сбой или потеря
данных.В этом фрагменте модели предметной области не представлены программные объекты, однако
в ней указана кратность связей (ограничения), отражающая особенности реальной предметной
области. С этой точки зрения более предпочтительным значением может оказаться “1"Рис. 9.15. Значение кратности является контекстно-зависимымРумбах [111] приводит еще один прекрасный пример объектов Person (Человек) и
Company (Компания), связанных ассоциацией Works-for (Работает на). Отображение
того факта, что один экземпляр объекта Person “работает” на один или несколько эк¬
земпляров объекта Company, зависит от контекста модели. Отдел налогообложения
будет больше интересовать значение много, тогда как профсоюз, возможно, — значе¬
ние один. Поэтому выбор на практике обычно зависит от заказчика программного
обеспечения.Несколько ассоциаций между двумя классамиМежду двумя классами может быть установлено несколько ассоциаций. И в этом
нет ничего необычного. В рассматриваемой нами POS-системе или игре “Монополия”
нет соответствующего примера, однако из предметной области системы управления
полетами в качестве подобного примера можно привести отношение между объекта¬
ми Flight (Полет) и Airport (Аэропорт) (рис. 9.16). Ассоциации Flies-to (Летит в)
и Flies-from (Летит из) являются принципиально различными и должны отобра¬
жаться отдельно.
188 Часть III. Первая итерация фазы развития - основы*Летит в1Flight*Летит из1AirportРис. 9.16. Несколько ассоциацийПоиск ассоциаций с помощью списка
стандартных ассоциацийПриступим к добавлению ассоциаций с использованием списка, представленного
в табл. 9.2.В нем указаны стандартные категории, которыми обычно не следует пренебре¬
гать, особенно в коммерческих информационных системах. Примеры ассоциаций
взяты из предметных областей резервирования авиабилетов, розничной торговли и
игры “Монополия”.Таблица 9.2. Список стандартных ассоциаций
Категория ПримерыА является транзакцией, которая свя¬
зана с другой транзакцией ВА является элементом транзакцииА является товаром или услугой для
транзакции ВА является ролью, связанной с тран¬
закцией ВА является физической или логической
частью ВА физически или логически содержит¬
ся в ВА является описанием ВА известен/зарегистрирован/записан/
включен в ВА является членом ВА является организационной единицей В
А использует, управляет или владеет ВА следует за ВCashPayment-Sale (Платеж наличными-Продажа)
Reservation-Canceliation (Заказ билета-Отмена заказа)SalesLineltem-Sale (Элемент продажи-Продажа)Item-SalesLineltem (Элемент-Элемент продажи)Flight-Reservation (Рейс-Резервирование)Си s tome г- Pay me nt (Покупатель-Платеж)
Passenger-Ticket (Пассажир-Билет)Drawer-Register (Устройство печати торговых чеков-Реестр)
Seat-Airplane (Место-Самолет)Square-Board (Клетка-Доска)Register-Store (Реестр-Магазин)Item-Shelf (Товар-Полка)Square-Board (Клетка-Доска)Passenger-Airplane (Пассажир-Самолет)ProductDescription-item (Описание товара-Товар)
FlightDescription-Flight (Описание полета-Полет)Sale-Register (Продажа-Реестр)Piece-Square (Объект-Клетка)Reservation-FlightManifest (Заказ билета-Декларация)Cashier-Store (Кассир-Магазин)Player-MonopolyGame (Игрок-Игра “Монополия”)
Pilot-Airline (Пилот-Авиарейс)Department-Store (Отдел-Магазин)Maintenance-Airiine (Служба поддержки-Авиарейс)Cashier-Register (Кассир-Реестр)Player-Piece (Игрок-Объект)Pilot-Airplane (Пилот-Самолет)SalesLineltem-SalesLineltem (Наименование товара-
Следующее наименование товара)
city-city (Город-Город)Square-Square (Клетка-Клетка)
Глава 9. Модели предметной области 1899.15. Примеры: ассоциации в моделях
предметных областейPOS-система NextGenВ показанной на рис. 9.17 модели предметной области представлен набор концеп¬
туальных классов и ассоциаций, являющихся кандидатами на включение в POS-при¬
ложение. Ассоциации предварительно были выбраны из списка ассоциаций-кандида-
тов и выделены на основе критерия важности. Чтобы лучше понять представленную
на рисунке диаграмму, следует обратиться к приведенному выше списку. Приведем
примеры.■ Транзакция, связанная с другими транзакциями, — Sale Paid-by CashPayment
(Sale Оплачивается CashPayment).■ Элементы транзакции — Sale Contains SalesLineltem (Sale Содержит
SalesLineltem).■ Товар для транзакции — SalesLineltem Records-sale-of Item (SalesLineltem
Записывает-факт-продажи Item).Записывает продажу0..1Содержится вLedgerSalesLineltemProductCatalogЗаписывает
счета дляСодержит11.ProductDescriptionStoreИспользуетсяХранитРегистрируетзавершенную11Содержит1..**SaleRegisterОбрабатывается0..11111CashPaymentCustomerCashierОписываетItem1..*Рис. 9.17. Фрагмент модели предметной области POS-системы NextGen
190 Часть III. Первая итерация фазы развития - основыИгра “Монополия”Обратимся к рис. 9.18. Ассоциации на этой диаграмме тоже выбраны по крите¬
рию значимости и на основе стандартного списка ассоциаций. Приведем примеры.■ А содержится в В — Board Contains Square (Board Содержит Square).■ А владеет В — Players Owns Piece (Players Владеет Piece).■ А известен в В — Piece Is-on Square (Piece Находится-на Square).■ А является членом В — Player Member-of (or Plays) MonopolyGame (Player
Является членом (или Играет-в) MonopolyGame).Рис. 9.18. Фрагмент модели предметной области для игры “Монополия”9.16. АтрибутыНеобходимо идентифицировать атрибуты концептуальных классов, которые удо¬
влетворяют информационным требованиям разрабатываемых в текущий момент сце¬
нариев. Атрибут (attribute) — это логическое значение данных объекта.Когда следует отображать атрибутыВ модель предметной области включаются те атрибуты, для которых определены
соответствующие требования (например, прецеденты) или для которых необходимо
хранить определенную информацию.Например, в товарном чеке (представляющем собой отчет о некоторой продаже)
обычно указываются дата и время, а также название магазина, его адрес и идентифи¬
катор кассира. Следовательно, приходим к следующему.■ Для класса Sale (Продажа) требуется атрибут dateTime (дата/время).■ Для класса Store (Магазин) требуются атрибуты name (название) и address (адрес).■ Для класса Cashier (Кассир) требуется атрибут id.
Глава 9. Модели предметной области 191Обозначение атрибутов в языке UMLАтрибуты помещаются во второй раздел условного обозначения класса (рис. 9.19).
Дополнительно может быть указан также тип атрибута либо другая необязательная
информация.SaledateTime/ total : Money о Атрибутыо-ПроизводныйатрибутРис. 9.19. Класс и его атрибутыДополнительные обозначенияПолный синтаксис для описания атрибутов на языке UML имеет следующий вид.область_видимости имя: тип кратность=значение_по_умолчанию {строка_свойств)Подробная диаграмма классов на языке UML приводится в главе 16 и в приложении.
Некоторые типичные примеры обозначения атрибутов показаны на рис. 9.20.SaleMathPerson- dateTime : Date- / total : Money+ pi : Real = 3.14 {readonly}firstNamemiddelName : [0..1]
lastName Pv-\Атрибуты ^Атрибут из открытой области ^из закрытойвидимости с инициализирующимобластизначением, который доступенвидимости"только для чтения"Необязательное |
значениеРис. 9.20. Обозначения атрибутов в языке UMLКак правило, в большинстве моделей атрибуты относятся к закрытой области ви¬
димости, и перед их именами ставится знак “минус” (-). Поэтому в данной книге яв¬
ный символ обозначения области видимости опускается.Самой типичной строкой свойств для атрибута является {readonly}.Кратность используется для указания количества объектов, заполняющих атрибут
коллекции. Например, во многих случаях в программной системе обязательно указыва¬
ется имя и фамилия человека, а отчество — необязательно. Выражение middleName:
[0..1] означает, что значение этого атрибута является необязательным.Где указывать требования к атрибутамЗаметим, что запись middleName : [0. .1] представляет собой требование или
правило предметной области, встроенное в модель предметной области. Хотя модель
предметной области обычно описывает лишь концептуальную перспективу, в нее за¬
частую включаются элементы программной перспективы. Так, например, запись
192 Часть III. Первая итерация фазы развития — основыmiddleName: [0..1] свидетельствует о том, что в интерфейсе пользователя и базе
данных можно не задавать поле отчества. В некоторых случаях такую форму записи
используют только в моделях предметной области. Однако зачастую модели предмет¬
ной области не поддерживаются в актуальном состоянии в процессе развития систе¬
мы и не присматриваются к ним на более поздних стадиях проектирования.Поэтому автор рекомендует описывать требования к атрибутам в словаре терми¬
нов, который в свою очередь служит словарем данных. Потратив несколько часов на
общение с экспертами в предметной области и построение соответствующей модели,
следует выделить пятнадцать минут и перенести важные требования к атрибутам в
словарь терминов.Можно также интегрировать модели UML со словарем данных с помощью спе¬
циальных программных средств, тогда все атрибуты автоматически отобразятся как
элементы словаря.Производные атрибутыАтрибут total (итого) класса Sale можно вычислить на основе информации, со¬
держащейся в объекте SalesLineltem. Если атрибут является важным, но произво¬
дным от других атрибутов, на диаграммах UML перед его именем ставится символ /.Вполне возможна такая ситуация, когда покупатель приобретает несколько еди¬
ниц одного товара (например, шесть пакетиков с конфетами). Тогда кассиру доста¬
точно сначала один раз ввести идентификатор товара (itemID), а затем — его количе¬
ство (например, шесть). В результате отдельный объект SalesLineltem будет связан
с несколькими экземплярами объекта Item.Введенное кассиром количество может быть записано как атрибут объекта
SalesLineltem (Элемент продажи) (рис. 9.21). Однако количество может быть опре¬
делено из реального значения кратности, заданной для связи. Поэтому его тоже мож¬
но охарактеризовать как производный атрибут (derived attribute), который можно по¬
лучить из других данных.\SalesLineltem0..1 Записывает продажу 1..*Item/quantity QАтрибут,
унаследованный
от значения кратностиРис. 9.21. Запись количества приобретенных элементов товара в объект SalesLineltem
Глава 9. Модели предметной области 193Корректные типы атрибутовТипы атрибутов в модели предметной областиТипы большинства простых атрибутов зачастую рассматриваются как примитив¬
ные типы данных. Обычно тип атрибута не должен быть сложным понятием пред¬
метной области, таким как Sale (Продажа) или Airport (Аэропорт).Например, атрибут currentRegister класса Cashier (Кассир) лучше не исполь¬
зовать (рис. 9.22), поскольку он имеет тип Register, не являющийся простым типом
атрибута (таким, как Number (Число) или String (Строка)). Если объект Cashier
использует объект Register, то лучше всего выразить этот факт с помощью ассоци¬
ации, а не атрибута.СоветВ модели предметной области атрибуты должны быть шипами данных (data type).
К стандартным типам атрибутов относятся Boolean, Date, Number, String (Text),
Time.Другими часто используемыми типами являются следующие: Address (адрес),
Color (цвет), Geometries (Point, Rectangle) (геометрические фигуры: точка,
прямоугольник), Phone Number (номер телефона), Social Security Number (но¬
мер страхового полиса), Universal Product Code (UPC) (универсальный код то¬
вара), SKU, ZIP или postal code (почтовый индекс), перечислимые типы.ХужеCashierпаше ф.currentRegister“Непростой” атрибутCashier1 Использует 1RegisternamenumberРис. 9.22. Связь с помощью ассоциаций, а не атрибутовКак видно из приведенного примера, стандартной ошибкой является моделиро¬
вание сложного понятия предметной области в форме атрибута. Другими словами,
аэропорт назначения на самом деле является не строкой, а сложной сущностью с
территорией, протянувшейся на многие километры. Таким образом, объект Flight
(Полет) должен быть связан с объектом Airport (Аэропорт) с помощью ассоциации,
а не атрибута (рис. 9.23).СоветСвязывайте концептуальные классы с использованием ассоциаций, а не атри¬бутов.
194 Часть III. Первая итерация фазы развития — основыРис. 9.23. Избегайте представления сложных понятий пред¬
метной области в виде атрибутов; используйте ассоциацииТипы данныхАтрибутами должны быть данные простых типов. Неформально такие типы назы-
ваются примитивными, и к ним относятся числовые типы, логические, символьные,
строковые и перечисления (например, Size={small, large}). Более точно, в языке
UML этот термин означает типы, для которых совершенно незначимой является уни¬
кальная тождественность (в контексте модели или системы) [107]. Другими словами,
проверка на равенство для этих типов базируется не на идентичности, а на проверке
значений.Например, обычно не существует различия между:■ отдельными экземплярами числа 5 (тип Integer);■ отдельными экземплярами строк ‘cat’ (тип String);■ отдельными объектами Date, содержащими одну и ту же дату.Однако существенными являются различия между двумя отдельными объектами
Person (Человек), даже если в обоих объектах содержится имя “Jill Smith”, поскольку
два экземпляра могут представлять отдельных людей с одним и тем же именем.Значения типов данных зачастую являются неизменными, например экземпляр 5
типа Integer. С другой стороны, атрибут lastName отдельного экземпляра класса
Person может измениться по некоторым причинам.В терминах программных систем существует несколько случаев, когда нет необ¬
ходимости сравнивать адреса памяти экземпляров объектов Interger или Date, до¬
статочно лишь выполнить сравнение их значений. Однако для того чтобы различить
объекты Person, даже если они имеют одинаковые значения атрибутов, все же при¬
дется сравнить адреса памяти, поскольку в данном случае важна их уникальность.В некоторых книгах по объектно-ориентированному подходу и моделированию на
языке UML данные простых типов называют также объектами значений (value objects),
однако с небольшими смысловыми вариациями. Однако автор данной книги счита¬
ет эти различия несущественными и несколько размытыми, поэтому не акцентирует
внимание на них.Реализация атрибутов в программном кодеТребование того, что атрибуты модели предметной области должны описываться
преимущественно типами данных, не предполагает, что на языках программирования
C# или Java атрибутами должны быть простые, примитивные типы данных. Модель
предметной области концентрирует внимание лишь на аналитическом исследовании
Глава 9. Модели предметной области 195проблемы предметной области, а не на программных сущностях. В модели проекти¬
рования атрибуты могут относиться к любому типу.Когда определять новые классы данныхВ POS-системе NextGen используется универсальный идентификатор това¬
ра itemID. Обычно он рассматривается как число или строка, например: itemID:
Integer или itemID: String.Однако в модели предметной области зачастую полезно использовать класс
ItemID, связав с ним соответствующий атрибут, например: itemID: ItemID.Ниже приведены рекомендации, определяющие необходимость использования в
модели дополнительных типов данных.Применение этих рекомендаций к атрибутам модели предметной области POS-си¬
стемы приведет к формулировке следующих идей.■ Идентификатор товара — это абстракция, построенная на основе различных
стандартных схем кодирования, включая UPC-А, UPC-Е и семейство схем EAN.
Эти схемы кодирования могут использоваться при подсчете контрольной сум¬
мы или иметь другие атрибуты (например, код изготовителя, товара, страны).
Следовательно, это должен быть тип данных ItemID.■ Атрибуты price (цена) и amount (сумма) должны иметь тип Quantity
(Количество) или Money (Валюта), поскольку они представляют собой количе¬
ство, выраженное в денежных единицах.■ Атрибут address (адрес) должен относиться к классу Address, поскольку в нем
имеются отдельные разделы.СоветТип данных, изначально рассматриваемый как число или строка, может быть
представлен в виде нового типа данных в модели предметной области в следую¬
щих случаях.■ Если он составлен из отдельных частей.• Номер телефона, имя человека.■ Если с этим типом обычно ассоциируются операции, такие как синтаксиче¬
ский анализ и проверка.• Номер страхового полиса.■ Если он содержит другие атрибуты.• Для льготной цены могут устанавливаться сроки действия (начало и конец).■ Если этот тип используется для задания количества с единицами измерения.• Стоимость товара измеряется в некоторых единицах.■ Это абстракция одного или нескольких типов.• Идентификатор товара — это некое обобщение типов UPC (Universal Product
Code) и EAN (European Article Number).
196 Часть III. Первая итерация фазы развития — основыКак иллюстрировать классы типов данныхДолжен ли тип Item ID представляться в модели предметной области как отдель¬
ный концептуальный класс? Это зависит от того, хотите ли вы выделить его на диа¬
грамме. Если ItemID представляет тип данных (уникальная тождественность не ис¬
пользуется в проверке на равенство), то его можно поместить в раздел атрибутов
соответствующего класса, как показано на рис. 9.24. Если же ItemID является новым
типом и у него имеются собственные атрибуты и ассоциации, то больший интерес
он будет представлять в качестве отдельного концептуального класса. Однако это не
совсем корректный ответ. На самом деле все зависит от того, как модель предметной
области используется в качестве средства взаимодействия и от значимости понятия
в предметной области.ХорошоХорошоProductDescriptionitemld: itemIDStoreaddress: AddressPuc. 9.24. Два способа представления типа свойства объектаНе используйте атрибуты в качестве внешних ключейАтрибуты не должны использоваться для связи концептуальных классов в модели
предметной области. Наиболее распространенным нарушением этого принципа явля¬
ется добавление некоторой разновидности атрибута внешнего ключа (foreign key attri¬
bute), что обычно происходит при разработке реляционных баз данных. Например,
на рис. 9.25 атрибут currentRegisterNumber использовать нежелательно, поскольку
его назначением является связывание объекта Cashier с объектом Register.ПлохоCashierпашеcurrentRegisterNumber O'“Простой” атрибут,
используемый в качестве
внешнего ключа для связи
с другим объектомCashier1 Использует 1RegisternamenumberРис. 9.25. Не используйте атрибуты в качестве внешних ключей
Глава 9. Модели предметной области 197Объекты Cashier и Register лучше связать с помощью ассоциации, а не атрибу¬
та внешнего ключа. Не лишним будет повторить еще раз: связывайте типы с помо¬
щью ассоциаций, а не атрибутов.Связать объекты можно множеством различных способов, и внешние ключи яв¬
ляются далеко не единственной возможностью. Для успешного создания системы на
стадии проектирования необходимо решить, как реализовать требуемые связи.Моделирование атрибутов Quantity и UnitБольшинство количественных сущностей нельзя представить в виде числовых
типов данных. Возьмем, к примеру, цену или скорость. С этими количественными
сущностями связаны определенные единицы измерения, необходимые для поддерж¬
ки функций конвертирования. Программная система NextGen предназначена для
использования в различных странах, поэтому она должна поддерживать различные
типы валют. Решение заключается в создании отдельного концептуального класса
Quantity (Количество), с которым будет ассоциироваться класс Unit (Единица из¬
мерения) [50]. Поскольку количество рассматривается в качестве типа данных, соот¬
ветствующий атрибут можно поместить в раздел атрибутов, как показано на рис. 9.26.
Обычно количество измеряют в некоторых единицах. Деньги — это количество, еди¬
ницей измерения которого служит тип валюты. Вес — это количество, измеряемое в
килограммах или фунтах.Paymentо-amount : NumberНе имеет смыслаPaymentСодержит количествомQuantityИзмеряется в ►Unit* 1amount : Number1Paymentamount : MoneyPaymentСтоимость — это значение,которое стоит отобразитьamount: Quantityo в разделе атрибутовВариация: Money —это
специализированный тип,
измеряемый в денежных
единицахЛучшеРис. 9.26. Моделирование количества
198 Часть III. Первая итерация фазы развития — основы9.17. Атрибуты в моделях предметных областейPOS-система NextGenРассмотрим рис. 9.27. Показанные на нем атрибуты отображают информацион¬
ные требования для первой итерации сценария Оформление продажи.Записывает продажу0..1LedgerSalesLineltemquantityСодержится в1..*Оплачивается
1ProductCatalogЗаписывает
счета дляСодержит1..*ProductDescriptionitemIDdescriptionpriceStoreИспользуетсяХранитnameaddressРегистрируетзавершеннуюОписываетItem1..*Содержит1JSale*RegisterОбрабатываетсяdateTime/totalid0..1 1Инициируется
11 I < Записывает продажуCashPaymentamountTenderedCustomer1- CashieridРис. 9.27. Фрагмент модели предметной области для POS-системы NextGenРассмотрим следующие примеры.amountTendered (предложенная сумма). Если нужно опреде¬
лить, достаточную ли сумму заплатил покупатель, и вычис¬
лить разность между этой суммой и стоимостью покупок, не¬
обходимо иметь атрибут amount или amountTendereddescription (описание). Оказывается полезным, если опи¬
сание товара нужно отобразить на экране или распечатать
на товарном чекеitemID (идентификатор товара). Если необходимо просмо¬
треть данные объекта ProductDescription, соответствую¬
щего введенному значению кода itemID, то эту связь можно
обеспечить с помощью данного атрибутаprice (цена). Необходим для вычисления итоговой суммы и
отображения цены единицы товараCashPayment
(Платеж наличными)ProductDescription
(Описание товара)
Глава 9. Модели предметной области 199Sale (Продажа)SalesLineltem
(Элемент продажи)Store (Магазин)dateTime (дата/время). Товарный чек представляет собой
распечатанные на бумаге данные о продаже. Как правило, на
нем указываются также дата и время продажиquantity (количество). Требуется для записи введенного ко¬
личества товаров, если покупатель приобретает несколько еди¬
ниц одного и того же товара (например, пять коробок конфет)address (адрес), name (название). На товарном чеке требует¬
ся указывать название и адрес магазинаИгра “Монополия”Рассмотрим рис. 9.28. Изображенные на нем атрибуты отражают информацион¬
ные требования для данной итерации — упрощенного сценария игры. Вот несколько
примеров.Die (Игральная кость) faceValue (значение). Этот атрибут определяет количествоклеток для перемещения
Square (Клетка) name (имя). Используется для вывода названия клеткиРис. 9.28. Фрагмент модели предметной области для игры “Монополия”9.18. Насколько корректна модель
предметной областиНе существует такого понятия, как “единственно верная модель”. Все модели явля¬
ются аппроксимациями изучаемой предметной области. В хорошей модели представ¬
лены наиболее существенные абстракции и данные, которые требуются для понима¬
ния предметной области в контексте текущих требований. С помощью такой модели
можно досконально разобраться в предметной области, ее понятиях, терминологии
и взаимосвязях между различными элементами.
200 Часть III. Первая итерация фазы развития — основы9.19. Итеративное и эволюционное
моделирование предметной областиПарадоксально, но факт: моделированию предметной области в данной книге по¬
священо несколько десятков страниц. Тем не менее, опытный разработчик тратит на
создание такой модели на каждой итерации порядка 30 минут. Это время сокращает¬
ся еще более при использовании стандартных шаблонов анализа.При итеративной разработке модель предметной области постепенно эволюци¬
онирует в течение нескольких итераций. На каждой итерации строится модель, от¬
носящаяся лишь к рассматриваемому сценарию и не охватывающая все возможные
концептуальные классы и взаимосвязи между ними. Например, на первой итерации
разработки системы NextGen рассматривается лишь упрощенный сценарий преце¬
дента Оформление продажи, реализующий оплату наличными. Поэтому создаваемая
на этой итерации модель предметной области отражает лишь понятия, необходимые
для данного сценария. Следовательно, хотелось бы еще раз повторить совет, приве¬
денный в начале этой главы.СоветИзбегайте попыток построить полную модель предметной области на начальных
этапах разработки. Такой стиль был присущ каскадному процессу разработки, когда
модель предметной области строилась на этапе анализа без учета обратной связи.
Выделяйте на построение модели предметной области не более нескольких часов
на каждой итерации.Модели предметной области в рамках UPКак видно из табл. 9.3, начало и завершение модели предметной области в рамках
UP приходится на фазу развития.Таблица 9.3. Пример планирования сроков реализации артефактов UP
(н — начало, р — развитие)ДисциплинаАртефактИтерация-»Начало11РазвитиеЕ1..ЕпКонструи- п
рование тлтГ
С1..СП Т1"Тп“Бизнес-моделирование”Модель предметной об¬нласти“Требования”Модель прецедентовнРВидение системынРДополнительная специ¬нРфикацияСловарь терминовнР“Проектирование”Модель проектированиянРОписание архитектурынМодель данныхнР
Глава 9. Модели предметной области 201Начальная фазаМодели предметной области не рассматриваются на начальной стадии, поскольку
на этом этапе не выполняются серьезные исследования, а принимается решение о
целесообразности выполнения более глубоких исследований на стадии развития.Фаза развитияМодель предметной области в основном создается в процессе нескольких ите¬
раций фазы развития, когда появляется необходимость понять сущности реального
мира и отразить их в программных классах.Объектная бизнес-модель и модель
предметной области в рамках UPМодель предметной области — это официальный вариант менее распространенной
объектной бизнес-модели UP (UP Business Object Model — UP BOM). Модель UP BOM
не нужно путать с моделью BOM, определенной в рамках других методов другими ав¬
торами. Модель UP BOM — это вид модели предприятия, используемый для описания
всей его экономической деятельности. Ее можно использовать для проектирования
бизнес-процессов или их обратного проектирования независимо от каких-либо про¬
граммных приложений (таких, как POS-система NextGen). Приведем цитату.“[Модель UP BOM] служит абстракцией связи и взаимодействия бизнес-
сущностей и сотрудников в процессе экономической деятельности.” [112]Модель ВОМ состоит из нескольких различных диаграмм (классов, видов деятельно¬
сти и последовательностей), иллюстрирующих экономические процессы в рамках всего
предприятия. Она наиболее полезна для проектирования бизнес-процессов, однако та¬
кая деятельность менее типична, чем разработка отдельных программных приложений.Поэтому в UP модель предметной области определена как более типичный арте¬
факт или специализация модели ВОМ. Приведем цитату.“Вы можете разработать “неполную” объектную бизнес-модель, сконцентрировав
внимание на пояснении сущностей и понятий, важных для данной предметной
области. ...Такую модель часто называют моделью предметной области.” [112]9.20. Дополнительные ресурсыВ [94] рассмотрены вводные вопросы концептуального моделирования предмет¬
ной области. Для изучения этих же вопросов также полезна книга [29].В книге Фаулера [50] рассматриваются шаблоны для построения моделей пред¬
метной области. Еще одной хорошей книгой с точки зрения описания шаблонов для
моделей предметной области является [67]. В ней приводятся советы экспертов в
области моделирования данных, которые хорошо понимают различие между чисто
концептуальными моделями и схемами баз данных, что очень полезно при моделиро¬
вании объектов предметной области.Хорошей книгой по моделированию предметной области является [30]. Авторы
этой книги выделяют стандартные шаблоны типов и ассоциаций. При этом цвета,
как следует из названия этой книги, действительно используются для визуализации
стандартных категорий этих типов. Так, описания выделяются голубым цветом,
роли — желтым, а временные сущности — розовым. Выделение цветом используется
для большей наглядности шаблонов.
Системные диаграммы
последовательностейТеоретически, между теорией и практикой нет различий, но на практике они есть.Жан Л.А. ван де Снепшот (Jan L.A. van de Snepscheut)Основные задачи■ Идентифицировать системные события.■ Создать системные диаграммы последовательностей для прецедентов.ВведениеДиаграмма последовательностей (sequence diagram) — это быстро и легко создавае¬
мый артефакт, иллюстрирующий входные и выходные события, связанные с разра¬
батываемой системой.Для иллюстрации событий, связывающих внешних исполнителей с системой, в
языке UML существуют специальные обозначения, позволяющие создавать диаграм¬
мы последовательностей.Что дальше?После ознакомления с принципами моделирования предметной области в данной
главе идентифицируются системные операции на системных диаграммах
последовательностей. В следующей главе проводится анализ влияния этих
операций на объекты из модели предметной области. В процессе этого анализа
используются условные обозначения для пред- и постусловий/\Требования
итерации 1МоделированиепредметнойобластиСистемные
диаграммы
последова¬
тельностей
—•—ОписанияоперацийПереход
к проекти¬
рованию
204 Часть IIS. Первая итерация фазы развития - основыВзаимосвязь системных диаграмм последовательностей (СДП) с артефактами UP
показана на рис. 10.1. Входными данными для создания системных диаграмм последо¬
вательности служат описания прецедентов и системные события. Операции, отобра¬
жаемые на СДП (например, enterltem), могут также анализироваться в описаниях
операций и словаре терминов. Они служат отправной точкой для проектирования
взаимодействия объектов.Пример взаимосвязи артефактов UPБизнес-
модели -
рованиеМодель предметной областиSale1 1..*SalesLineltemquantitydateМодель прецедентовОпреде¬лениетребо¬ванийДиаграмма прецедентовОформлениепродаж1. Покупатель
подходит...2.Кассир вводит
идентификатор
товара.3...Текст прецедентаI Системные
событияВидениеИнформация
о параметрах
ивозвращаемых Словарь
значенияхОперация:enterltem(...)Постусловия:: КассирСистемныеоперации^Описания операцийОтправная точка для проектирования
взаимодействующих объектовДополнительнаяспецификацияСистемные диаграммы
последовательностейМодель проектированияПроекти¬рование:Register:ProductCatalog: Saleenterltem
(itemID, quantity)
• *specgetProductSpec( itemID )addLineItem( spec, quantity )Puc. 10.1. Пример взаимосвязи артефактов UP
Глава 10. Системные диаграммы последовательностей 20510.1. Пример СДП для приложения NextGenНа системной диаграмме последовательностей для определенного хода событий,
описанного в прецеденте, отображаются внешние исполнители, которые взаимо¬
действуют непосредственно с системой, сама система (как “черный ящик”), а также
системные события, инициируемые исполнителями (рис. 10.2). При этом порядок
событий должен соответствовать их последовательности в описании прецедента.
Время на диаграмме последовательности изменяется сверху вниз.Пример, приведенный на рис. 10.2, соответствует основному успешному сценарию
прецедента Оформление продажи. Он иллюстрирует, что для POS-системы кассир
генерирует системные события makeNewSale, enterltem, endSale и makePayment.
Описания этих событий содержится в описании прецедента.Система как “черный ящик”.В качестве имени можно использовать “NextGenPos”,
однако имя "System” проще.Символ и подчеркивание означают экземпляр.
Более подробно диаграммы последовательностей
и обозначения UML будут обсуждаться в последующих
главахВнешний по отношению
к системе исполнительЦиклический ■
фреймвзаимодействия
UML с булевым
условным
выражением: КассирIСценарий прецедента
Оформление продажиmakeNewSale():System.-"Оloopj[для других товаров]I enterltem(itemID, quantity)
iОписание, общая стоимость jВозвращаемые Iзначения, связанные
с предыдущим
сообщением.Абстракция, не связанная
с конкретным
представлением
и носителем данных.Обратная линия является
необязательной, если
никакое значение
не возвращаетсяIIIIIк-endSaleОбщая стоимость с налогамиmakePayment(amount)Сдача, чекО"'Сообщение Ь
с параметрами.Это абстракция,
представляющая
системное событие
ввода данных
о платеже
с использованием
некоторого
механизмаРис. 10.2. СДП для сценария прецедента Оформление продажи
206 Часть III. Первая итерация фазы развития — основы10.2. Системные диаграммы последовательностейПрецеденты определяют, как внешние исполнители взаимодействуют с программ¬
ной системой. В процессе этого взаимодействия исполнителем генерируются систем¬
ные события (system event), которые представляют собой запросы на выполнение
некоторой системной операции (system operation). Например, кассир, введя идентифи¬
катор товара, тем самым предписывает, чтобы система POS записала данные о при¬
обретении товара (событие enter Item). Это событие инициирует в системе выпол¬
нение некоторой операции. Событие enter Item вводится в описании прецедента, а
на СДП конкретизируется и формализуется.В состав языка UML входят обозначения для диаграммы последовательностей (se¬
quence diagram), с помощью которых можно проиллюстрировать взаимодействие ис¬
полнителя с системой и операции, выполнение которых при этом инициируется.Системная диаграмма последовательностей (system sequence diagram — SSD) — это
схема, которая для определенного сценария прецедента показывает генерируемые
внешними исполнителями события, их порядок, а также события, генерируемые
внутри самой системы. При этом все системы рассматриваются как “черный ящик”.
Назначение данной диаграммы — отображение событий, передаваемых исполнителя¬
ми системе через ее границы.СоветДиаграмму последовательностей нужно создать для основного успешного сценария
прецедента, а при необходимости и для наиболее существенных и сложных альтер¬
нативных сценариев.10.3. Зачем строить СДППри разработке системы возникает важный вопрос: какие события поступают
в систему? Дело в том, что проектируемая система должна обрабатывать эти собы¬
тия (поступающие от мыши, клавиатуры, других систем и т.д.) и реагировать на них.
Программная система реагирует на три типа событий: внешние события, иницииру¬
емые исполнителями (людьми или компьютерами), таймерные события и сбои или
исключения (тоже зачастую генерируемые внешними источниками).Поэтому очень важно знать, что следует понимать под внешними, или системны¬
ми, событиями (system event). Они являются важной частью анализа поведения сис¬
темы.Возможно, читатель знаком с идеей идентификации сообщений, поступающих в
программные объекты. Но это понятие используется на более высоком уровне компо¬
нентов. В качестве одного из компонентов или объектов может выступать вся система.Прежде чем приступать к проектированию логики работы программного при¬
ложения, необходимо исследовать и определить ее поведение как “черного ящика”.
Поведение системы (system behavior) представляет собой описание того, какие действия
выполняет система, без определения механизма их реализации. Одной из частей та¬
кого описания является диаграмма последовательностей. К остальным частям отно¬
сятся прецеденты и описания системных операций (которые будут рассмотрены в по¬
следующих главах).
Глава 10. Системные диаграммы последовательностей 20710.4. Применение UML для построения
диаграммы последовательностиВ контексте языка UML нет понятия “системная диаграмма последовательностей”,
есть просто “диаграмма последовательностей”. Это уточнение автор использовал для
того, чтобы сделать акцент на рассмотрении системы в виде “черного ящика”. В даль¬
нейшем диаграммы последовательностей будут рассмотрены в другом контексте — для
иллюстрации взаимодействия разрабатываемых программных объектов.Циклы на диаграммах последовательностейОбратите внимание, что на рис. 10.2 для обозначения цикла используются фреймы
взаимодействия (interaction frame).10.5. Системные диаграммы
последовательностей и прецедентыНа диаграмме последовательностей отображаются системные события для одного
сценария некоторого прецедента. Поэтому сама диаграмма строится на основе описания
прецедента (рис. 10.3).I IРис. 10.3. Системные диаграммы последовательностей строятся на основе описания прецеден¬
тов и отражают один сценарий
208 Часть III. Первая итерация фазы развития — основыНужно ли отображать описание прецедентов на СДПЭто делать необязательно. Если для СДП удачно выбрано имя, то по нему можно
идентифицировать название соответствующего прецедента.Какое имя лучше, scan (itemID) или enterltem (itemID) ? Системные события
нужно именовать на абстрактном уровне, а не в терминах входных физических носи¬
телей данных или управляющих элементов пользовательского интерфейса.Таким образом, имя enterltem гораздо лучше, чем имя scan (в смысле считыва¬
ния лазерным сканером), поскольку в нем отражается смысл операции. К тому же
такое имя является абстрактным, не зависящим от выбора управляющих элементов
интерфейса, которые будут участвовать в непосредственной обработке системного
события. В качестве таких управляющих элементов могут выступать лазерный ска¬
нер, клавиатура, устройство голосового ввода или что-нибудь еще.Имя системного события лучше всего начинать с глагола: add... (добавить),
enter... (ввести), end... (завершить), make... (выполнить) (рис. 10.4). Это повы¬
шает читабельность имен и, кроме того, дополнительно подчеркивает направление
передачи событий.СДП можно также использовать для иллюстрации взаимодействия между систе¬
мами, например между POS-системой NextGen и внешней службой авторизации пла¬
тежей по кредитной карточке. Однако этот вопрос мы отложим до следующих ите¬
раций, поскольку на данном этапе нас не интересует взаимодействие с удаленными
системами.10.6. Имена системных событий и операций:System: КассирБолее удачное имяenterltem(itemID, quantity)Неудачное имяscan(ItemID, quantity)Рис. 10.4. Выбирайте имена событий и операций на абстрактном уровне10.7. Как моделировать взаимодействие
с внешними системами
Глава 10. Системные диаграммы последовательностей 20910.8. Диаграммы последовательностей
и словарь терминовНа системной диаграмме последовательностей термины (операции, параметры,
возвращаемые значения) отображаются в краткой форме. Поэтому на этапе проек¬
тирования могут понадобиться некоторые пояснения этих термшшш. Если значение
терминов не разъясняется в описании прецедентов, то их нужно внести в словарь
терминов.Например, на рис. 10.2 показана возвратная линия с надписью “сдача, чек”. При
этом чек представляет собой комплексный отчет, требующий отдельного описания.
Поэтому в словарь терминов необходимо ввести понятие “чек”, добавить его деталь¬
ное описание и формат, а также привести примеры цифровых фотографий чеков.СоветДля большинства артефактов детальную информацию следует приводить в словаре
терминов.Для прецедента Игра Монополия главный сценарий очень прост. Наблюдатель
задает количество игроков и инициирует начало игры, наблюдая за ее ходом10.9. Пример диаграммы последовательности
для игры “Монополия”(рис. 10.5).Рис. 10.5. СДП для сценария прецедента Игра Монополия
210 Часть III. Первая итерация фазы развития — основы10.10. Итеративное и эволюционное
построение СДПНе создавайте СДП для всех сценариев, поскольку для этого потребуется иденти¬
фицировать все системные операции. Лучше построить СДП только для тех сценари¬
ев, которые будут реализовываться на следующей итерации. Это не потребует много
времени, а займет не более получаса.Диаграммы последовательностей облегчают понимание интерфейса и принципов
взаимодействия с существующими системами, а также позволяют документировать
архитектуру.СДП в контексте UPДиаграммы последовательностей — это часть модели прецедентов. Они обеспе¬
чивают визуализацию взаимодействия объектов при реализации прецедента. В ис¬
ходном описании унифицированного процесса диаграммы последовательностей не
упоминаются явно, хотя разработчики UP хорошо понимают значимость и полез¬
ность подобных диаграмм. Диаграммы последовательностей — это пример артефак¬
тов анализа и проектирования или видов деятельности, не упомянутых в документах
по описанию UP или RUP. Однако при всей гибкости UP специалисты рекомендуют
включать все артефакты, обеспечивающие дополнительную информацию о разраба¬
тываемой системе.ФазыНачало — на этой стадии диаграммы последовательностей обычно не строятся.
Единственным исключением является необходимость оценки трудоемкости разработ¬
ки системы на основе идентификации системных операций, в частности функциональ¬
ных точек (function point) или СОСОМО II (www.ifpug.org). Однако такую оценку
нельзя считать надежной.Развитие — большая часть СДП разрабатывается на стадии развития, когда не¬
обходимо определить детали системных событий и прояснить основные системные
операции, составить описания системных операций и выполнить некоторые оценки
(например, макрооценивание на основе ненастраиваемых функциональных точек и
принципов СОСОМО II).10.11. История и дополнительные ресурсыРазличные типы диаграмм, иллюстрирующих входные и выходные события систе¬
мы, рассматриваемой в качестве “черного ящика”, давно известны и широко исполь¬
зовались в течение десятилетий. Например, в области телекоммуникаций широко из¬
вестны диаграммы потоков звонков. Они особенно популярны в различных методах
объектно-ориентированного подхода, в частности используются в методе Fusion [38].
В этой книге детально рассматриваются вопросы взаимосвязи диаграмм последо¬
вательностей и системных операций с другими артефактами анализа и проектиро¬
вания.
Описание операцийКогда закапчиваются идеи, па помощь приходят слова.
Иогапп Вольфганг Гете (Johann Wolfgang von Goethe)Основные задачи■ Определить системные операции.■ Создать описания системных операций.ВведениеОсновным механизмом описания поведения в UP являются прецеденты. Зачастую
приводимой в них информации достаточно для описания поведения системы.
Однако иногда требуется более детальное описание поведения. Описания системных
операций (system operation contract) определяют детальное поведение системы в тер¬
минах изменения состояния объектов модели предметной области после выполнения
системных операций. При описании системных операций используются пред- и по¬
стусловия. Основной моделью объектно-ориентированного анализа является модель
предметной области. Однако описание операций и модели состояний тоже являются
полезными артефактами.Описание операций можно рассматривать как часть модели прецедентов UP, по¬
скольку они обеспечивают детализацию выполняемого анализа системных операций.Что дальше? После анализа системных диаграмм последовательностей и системных операций
в данной главе оценивается их влияние на объекты предметной области.В следующей главе после завершения анализа на данной итерации осуществляется
переход к проектированию - виду деятельности, повторяющемуся на каждой
итерации/ \.. Системные поделирование диаграммы Описания ереход Логическаяпредметной „к проекти-области последова- операции ^ архитектурательностеи-о # о
212 Часть III. Первая итерация фазы развития — основыВзаимосвязи между описаниями операций и другими артефактами показаны на
рис. 11.1. Основными входными данными для описаний являются системные опера¬
ции, определяемые с помощью СДП (например, enter Item), а также модели пред¬
метной области. В свою очередь, эти описания служат входными данными в процессе
проектирования, поскольку они описывают изменения программных объектов или
базы данных.Пример взаимосвязей артефактов UPМодель предметной областиБизнес-модели¬рованиеОбъекты
предметной
области,
атрибуты и
ассоциации,/
которые
подвергаются
изменениямSale1 1..*SalesLineltemdatequantityМодель прецедентов/Оформление^Vjipoflax^ s «vКассир ЛИменапрецедентовОформление
продажи
1. Покупатель
подходит...£x О2VV. _''3.Кассир вводит'
идентификатор
^товара.ВидениеН7ЦОпре-
/деление
требо¬
ванийДиаграмма прецедентовТекст прецедентаСистемные
событияСловарь:SystemОтправная точка
для проектиро¬
вания; детали¬
зированные
требования,
которые
должны быть
удовлетворены
в программном
обеспеченииОперациям ('enterltem (...))Постусловия:: КассирIСистемные \
операции -^ -IЧ| (id, quantity)/make
NewSale()enterltemДополнительнаяспецификация\Описания операцийСистемные диаграммы
последовательностейУ/Требования, которые
должны быть реализо¬
ваны в программном
обеспеченииМодель проектирования■лПроекти¬рование:Register :ProductCatalog :Saleenterltem
^(itemID, quantity^'I I
I I
I I
I Ispec = getProductSpec( itemID ) ( |VIaddLineItem( spec, quantity )( \I ►! ^Рис. 11.1. Взаимосвязь описаний операций с другими артефактами
Глава 11. Описание операций 21311.1. ПримерРассмотрим пример описания системной операции enterltem. Важным элемен¬
том этого описания являются постусловия. Другие части описания тоже полезны, но
менее важны.Описание операции ОП2: enterltemОперация enterltem(itemID: ItemID, quantity: integer)Ссылки Прецеденты: Оформление продажиПредусловия Инициирована продажаПостусловия - Создан экземпляр sli класса SaiesLineitem (создание экземпляра)- Экземпляр sli связан с текущим экземпляром класса Sale (формиро¬
вание ассоциации)-Атрибуту sli.quantity присвоено значение quantity (модификация
атрибута)- Экземпляр sli связан с классом ProductDescription на основе соот¬
ветствия идентификатора товара itemID (формирование ассоциации)Классификация постусловий (например, создание экземпляра) приводится для
лучшего понимания материала и не является частью описания операций.11.2. Разделы описанияНиже рассмотрен каждый из разделов описания.ОперацияСсылкиПредусловияПостусловияИмя операции и ее параметрыПрецеденты, в рамках которых может выполняться эта операция
Предположения о состоянии системы или объектов модели предметной
области до выполнения операции. Выполнение этих условий не проверя¬
ется в рамках логики выполнения данной операции, а предполагается, что
они истинны. Это нетривиальные условия, на которые читатель должен
обратить вниманиеЭто самый важный раздел. Состояние объектов модели предметной об¬
ласти после завершения операции (подробнее обсуждается в следующем
разделе)11.3. Что такое системная операцияОписания определяются для системных операций (system operations). Системными
называются операции, входящие в открытый интерфейс системы для обработки вход¬
ных системных событий, которые система выполняет как черный ящик. Системные
операции можно идентифицировать на основе системных событий (рис. 11.2). Более
точно СДП отражают системные события или входные и выходные сообщения,
связанные с системой. Входные системные события требуют обработки с помощью
системных операций. Они обрабатываются с помощью объектно-ориентированных
методов.
214 Часть III. Первая итерация фазы развития - основыРис. 11.2. СДП: системные операции обрабатывают входные системные событияВесь набор системных операций, выполняемых в процессе всех прецедентов,
определяет открытый системный интерфейс (system interface), в ракурсе которого
система рассматривается как единый компонент или класс. В UML систему в целом
можно представить в виде одного класса.11.4. ПостусловияОбратите внимание, что для каждого из постусловий в примере описания систем¬
ной операции enterltem для улучшения понимания указана категория, например
“Создание экземпляра” или “Формирование ассоциации”.ОпределениеВ разделе “Постусловия” декларируются изменения состояния объектов модели
предметной области. К таким изменениям относятся создание экземпляра, фор¬
мирование или разрыв ассоциации, или изменение атрибута.Постусловия - это не действия, выполняемые в процессе операции, а лишь декларация об
изменении состоянии объектов модели предметной области после выполнения операции
(когда рассеется туман).
Глава 11. Описание операций 215Существуют следующие категории постусловий описаний.■ Создание и удаление экземпляра.■ Модификация атрибута.■ Формирование и разрыв ассоциаций.Разрыв ассоциации встречается очень редко. В качестве примера разрыва ассоци¬
ации рассмотрим операцию удаления наименования товара. Постусловие этой опера¬
ции может иметь вид: “Ассоциация выбранного класса SalesLineltem с экземпляром
класса Sale разорвана”. Если рассматривать другие предметные области, то разрыв
ассоциации происходит при выплате кредита или выходе человека из некоторого со¬
общества.Реже всего встречаются постусловия удаления экземпляра, поскольку явное раз¬
рушение объекта реального мира обычно не имеет значения для разработчиков про¬
граммной системы. Однако рассмотрим следующий пример. Во многих странах, со¬
гласно законодательству, через семь-десять лет после объявления о банкротстве все
записи об этом банкротстве должны быть удалены. Заметим, что это относится к
концептуальному аспекту, а не к аспекту реализации. Это не означает необходимость
очистки памяти компьютера, занимаемой программными объектами.Связь постусловий с моделью предметной областиПостусловия формулируются в контексте модели предметной области. Экземпляры
каких объектов могут создаваться? Из модели предметной области. Какие ассоциа¬
ции могут формироваться? Опять же, ассоциации, предусмотренные в модели пред¬
метной области, и т.д.Зачем нужны постусловияВо-первых, они нужны не всегда. Зачастую результаты выполнения системных
операций понятны разработчикам из описания прецедентов, общения с экспертами
и собственного опыта. Однако иногда требуются дополнительные детали, которые и
обеспечиваются с помощью описания операций.Заметим, что в постусловиях детально описываются результаты операции. Этого
уровня описания можно придерживаться и в прецедентах, но это нежелательно, по¬
скольку перегружается описание прецедентов низкоуровневой информацией.Описание операции — прекрасное средство анализа требований или ООА, позво¬
ляющее детально описать изменения, выполняемые системными операциями в тер¬
минах модели предметной области, не вдаваясь в способ их реализации.Другими словами, при описании операций можно абстрагироваться от проектных
решений, а сконцентрироваться на анализе происходящих событий.Рассмотрим постусловия описанной ранее операции.
216 Часть III. Первая итерация фазы развития — основыПостусловия - Создан экземпляр sli класса SalesLineltem (создание экземпляра)-Экземпляр sli связан с текущим экземпляром класса Sale (формиро¬
вание ассоциации)-Атрибуту sli.quantity присвоено значение quantity (модификация
атрибута)- Экземпляр sli связан с классом ProductDescription на основе соот¬
ветствия идентификатора товара itemID (формирование ассоциации)Здесь ничего не говорится о способе создания экземпляра SalesLineltem или
установке ассоциации с экземпляром класса Sale. Речь может идти об описании клас¬
сов на бумаге и скреплении двух таких описаний, использовании Java-технологии для
создания программных объектов и их связывании или о вставке записей в реляцион¬
ную базу данных.Как описывать постусловияПостусловия должны описывать состояние системы, а не выполняемые действия.
Их желательно формулировать в прошедшем времени, чтобы подчеркнуть уже про¬
изошедшие изменения, например:■ (хороший вариант) создан экземпляр SalesLineltem,а не■ (плохой вариант) создание экземпляра SalesLineltem.“Дух” постусловий: сцена и занавесПочему постусловия желательно формулировать в прошедшем времени? Рассуждаяо постусловиях, уместно использовать следующую метафору.Система и ее объекты находятся на сцене театра.1. Сфотографируйте сцену перед выполнением операций.2. Опустите занавес и выполните системную операцию (за кулисами раздается ,
шум, возникающий из-за передвижения декораций, голоса и прочие звуки...).3. Откройте занавес и сделайте еще один снимок.4. Сравните оба снимка и выразите произошедшие изменения в форме постусло¬
вий (создан экземпляр объекта SalesLineltem...).Насколько детальными должны быть постусловияВо-первых, описания операций могут вообще не понадобиться. Об этом говори¬
лось в предыдущих разделах. Однако если нужно составить описания системных опе¬
раций, то генерировать полный и детальный список постусловий на этапе анализа
требований нежелательно. В духе гибкого процесса моделирования их надо рассма¬
тривать как некие начальные сведения и понимать, что описания операций являются
далеко не полными.Однако при этом нисколько не умаляется роль анализа и исследований до начала
программной реализации системы — это другая крайность.
Глава 11. Описание операций 21711.5. Постусловия описания операции enterltemВ этом разделе подробно рассматриваются постусловия системной операцииenterltem.Создание и удаление экземпляраКакие новые объекты создаются в системе, когда кассир вводит код товара
itemID и количество его единиц quantity? Должен быть создан экземпляр объекта
SalesLineltem. Таким образом:■ создан экземпляр sli класса SalesLineltem (создание экземпляра).Обратите внимание на имя экземпляра. Это имя упростит ссылки на вновь создан¬
ный экземпляр в последующих постусловиях.Модификация атрибутаКакие атрибуты новых или уже существующих объектов должны быть модифици¬
рованы, когда кассир вводит код товара itemID и количество его единиц quantity?
Должно быть установлено количество покупаемых единиц для товара SalesLineltem.
Таким образом:■ атрибуту sli.quantity присвоено значение quantity (модификация атрибута).Формирование и разрыв ассоциацииКакие ассоциации между новыми или существующими объектами должны быть
сформированы или разорваны, когда кассир вводит код товара itemID и количество
его единиц quantity? Новый покупаемый товар SalesLineltem должен быть связан
с текущей продажей Sale, а также со своей спецификацией ProductDescription.
Таким образом:■ экземпляр sli связан с текущим экземпляром класса Sale (формирование ассоци¬
ации);■ экземпляр sli связан с классом ProductDescription на основе соответствия
идентификатора товара itemID (формирование ассоциации).Обратите внимание на неформальную констатацию формирования взаимосвязи с
конкретным экземпляром класса ProductDescription на основе соответствия иден¬
тификатора товара itemID. Для выражения этого факта можно использовать более
формальный подход, в частности, основанный на применении объектного языка
ограничений OCL (Object Constraint Language). Однако автор советует придержи¬
ваться принципа простоты и не усложнять себе жизнь.11.6. Описание операций приводит
к изменению предметной областиВ процессе составления описаний операций в модель предметной области зача¬
стую приходится вводить новые концептуальные классы, атрибуты или ассоциации.
218 Часть III. Первая итерация фазы развития — основыНе привязывайтесь к существующей модели предметной области, усовершенствуйте
ее в процессе исследования и описания системных операций.При итеративной и эволюционной разработке все артефакты анализа и проекти¬
рования рассматриваются как неполные и незавершенные. Они эволюционируют
в процессе разработки системы.11.7. Когда нужны описания операций?В рамках UP прецеденты — основной источник информации о требованиях к про¬
екту. В них могут отражаться основные или все детали, необходимые для проекти¬
рования. В этом случае описания системных операций не нужны. Однако бывают
случаи, когда изменение состояния не слишком детально описывается в прецедентах
из-за своей сложности.Например, рассмотрим систему резервирования авиабилетов и системную опера¬
цию addNewReservation. Она обладает высокой сложностью, поскольку затрагивает
множество объектов предметной области, состояние которых изменяется. Детали
таких изменений можно описать в прецеденте, связанном с этой операцией, однако
при этом описание прецедента станет излишне многословным (поскольку придется
упомянуть каждый атрибут всех изменяемых объектов).Обратите внимание, что формат описания постусловий предполагает использова¬
ние очень точного языка с необходимой степенью детализации.Если на основании описаний прецедентов и обсуждения проблемы со специали¬
стами по предметной области разработчикам понятно, что нужно делать, то состав¬
лять описание системных операций не обязательно.Однако если операции достаточно сложны и их детальное описание вносит яс¬
ность в проблему, то такое описание системной операции можно рассматривать как
еще один механизм формулировки требований.В данном примере описание операции является слишком детальным. Это сделано
в учебных целях. На практике большинство деталей очевидны из описания прецеден¬
тов. Однако очевидность — очень субъективное понятие.11.8. Составление описанияПриведем некоторые советы по составлению описаний.1. Определите системные операции из диаграмм последовательностей.2. Составьте описание для сложных системных операций, результаты которых сочевидностью не следуют из описания прецедента.3. При описании постусловий используйте следующие категории.• Создание и удаление экземпляра• Модификация атрибута• Формирование и разрыв ассоциаций
Глава 11. Описание операций 219Создание описаний■ Постусловия целесообразно описывать в декларативной форме, желательно с
использованием глаголов пассивного залога в прошедшем времени, чтобы под¬
черкнуть факт изменения состояний, а не способ реализации, как, например,
показано ниже.• Создан экземпляр SalesLineltem (лучше).• Создание экземпляра SalesLineltem (хуже).■ Не забудьте установить отношения между существующими и вновь создаваемы¬
ми объектами путем формирования ассоциаций. Например, при выполнении
операции enterltem недостаточно просто создать новый экземпляр записи о
покупке товара SalesLineltem. После выполнения операции этот экземпляр
должен быть связан с текущей продажей Sale. Поэтому одним из постусловий
этой операции является следующее.• Вновь созданный экземпляр SalesLineltem связан с объектом Sale (формиро¬
вание ассоциации).Наиболее типичная ошибка при
описании системных операцийНаиболее типичной ошибкой при составлении описаний является невключение
формирования ассоциаций в число постусловий операции. Установка ассоциаций игра¬
ет особо важную роль при создании новых экземпляров. Не забывайте об этом!11.9. Пример описания операции для
POS-системы NextGenСистемные операции для прецедента
Оформление продажиОписание операции 0П1: makeNewSaleОперация makeNewSale()ССЫЛКИ Прецеденты: Оформление продажиПредусловия ОтсутствуютПостусловия - Создан экземпляр s объекта Sale (создание экземпляра)- Экземпляр объекта Sale связан с объектом Register (формирование
ассоциации)- Инициализированы атрибуты экземпляра sОбратите внимание на нечеткое описание последнего постусловия. Если оно вам
понятно, то все хорошо.В реальном проекте все эти постусловия настолько очевидны и следуют из описа¬
ния прецедентов, что создавать описание системной операции makeNewSale не име¬
ет смысла.
220 Часть III. Первая итерация фазы развития — основыНапомним один из основных принципов UP: стремитесь к максимальной просто¬
те и избегайте использования артефактов, которые не добавляют новых знаний.Описание операции ОП2: enterltemОперация enterltem(itemID: ItemID, quantity: integer)Ссылки Прецеденты: Оформление продажиПредусловия Инициирована продажаПостусловия - Создан экземпляр sli класса SalesLineitem (создание экземпляра)-Экземпляр sli связан с текущим экземпляром класса Sale (формиро¬
вание ассоциации)-Атрибуту sli.quantity присвоено значение quantity (модификация
атрибута)- Экземпляр sli связан с классом ProductDescription на основе соот¬
ветствия идентификатора товара itemID (формирование ассоциации)Описание операции ОПЗ: endSaleОперация endSale()Ссылки Прецеденты: Оформление продажиПредусловия Инициирована продажаПостусловия - Атрибут Sale. iscomplete принял значение true (модификация атрибута)Описание операции ОП4: makePaymentОперация makePayment(amount: Money)Ссылки Прецеденты: Оформление продажиПредусловия Инициирована продажаПостусловия - Создан экземпляр р класса Payment (создание экземпляра)-Атрибут p.amountTendered принял значение amount (модификация
атрибута)- Экземпляр р связан с текущим экземпляром класса Sale (формирование
ассоциации)- Текущий экземпляр Sale связан с экземпляром класса store для его до¬
бавления в журнал регистрации продаж (формирование ассоциации)Изменение модели предметной областиПри составлении этих описаний предполагалось наличие одного объекта данных,
который еще не был представлен в модели предметной области, а именно — заверше¬
ние ввода информации о покупаемых товарах. Значение этого объекта изменяется
при выполнении операции endSale, а в операции makePayment оно проверяется в
предусловии.Одним из способов представления этой информации является введение атрибута
isComplete логического типа для объекта Sale.
Глава 11. Описание операций 221SaleisComplete: BooleandateTimeСуществуют и альтернативные решения, позволяющие представить изменение
состояния системы. Одним из них является шаблон State. Еще одно решение состоит
в использовании объектов session, отвечающих за состояние сеанса. Это решение
тоже будет рассмотрено в последующих главах.11.10. Описание операций для игры “Монополия”Этот пример приводится для того, чтобы показать, что многие артефакты анали¬
за не являются обязательными, включая описание операций. Согласно идеологии UP
следует избегать создания лишних артефактов. Люди, знакомые с правилами игры
“Монополия” с детства, смогут реализовать ее без дополнительных описаний.11.11. Описания операций на UML и 0CLКакова взаимосвязь между описаниями операций и языком UML? В UML суще¬
ствует формальное определение операции (operation). Приведем цитату.“Операция — это спецификация преобразования или запроса к объекту” [107].Например, в терминах UML элементы интерфейса являются операциями. Опера¬
ция — это абстракция, а не реализация. В отличие от нее, в UML метод (method) —
это реализация операции. Приведем еще одну цитату.“ [метод — это] реализация операции. Он описывает алгоритм или процедуру,
связанную с данной операцией” [99].В UML каждой операции соответствует сигнатура (signature), т.е. имя и параме¬
тры, а также спецификация (operation specification), описывающая результаты выпол¬
нения операции или постусловия. Для спецификаций в UML определен свободный
формат. Не существует также формата описания операций. Однако в документации
по UML приводятся примеры описания операций со стилями оформления пред- и
постусловий. Такой подход к описанию операций наиболее распространен.Итак, в UML определены спецификации операций, имеющие вид описаний с
пред- и постусловиями. Как уже отмечалось в этой главе, в спецификации операции
не отражаются алгоритм или проектное решение, а только констатируются измене¬
ния состояния или результаты выполнения операции.Помимо описаний открытых операций для всей системы (системных операций)
можно создавать описания операций любого уровня детализации, в частности опи¬
сания открытых операций (или интерфейсов) подсистем, абстрактных классов и т.д.
Рассмотренные в этой главе операции относятся к классу системных. В UML опера¬
ции делятся на классы. Более того, в UML подсистемы моделируются в виде классов
(а также в виде пакетов). В контексте UML вся система — это подсистема самого вы¬
сокого уровня. Она моделируется с помощью класса System (на самом деле можно
использовать любое имя) с открытыми операциями и спецификациями.
222 Часть III. Первая итерация фазы развития — основыОписание операций на языке OCLПринятый в этой главе формат описания операций на основе пред- и постусловий
представляет собой неформальное описание на естественном языке. Такое описание
облегчает понимание и вполне приемлемо для языка UML.Однако с языком UML связан формальный объектный язык ограничений OCL
(Object Constraint Language) [122], который можно использовать для описания ограни¬
чений в модели. Язык OCL можно использовать вместо неформального естественного
языка, поскольку UML допускает произвольный формат спецификации операций.СоветЕсли нет насущной необходимости в изучении и использовании языка OCL, при¬
держивайтесь принципа простоты и составляйте описания на естественном язы¬
ке. Автору никогда не приходилось встречаться с проектами, где используется
язык OCL, хотя он имеет богатый практический опыт.В языке OCL определен официальный формат задания пред- и постусловий в опи¬
саниях операций. Это демонстрирует следующий пример.System: :makeNewSale ()pre : <операторы языка OCL>
post : ...Более подробное описание языка OCL не входит в задачи этой книги.11.12. Описания операций в рамках UPОписания с указанием пред- и постусловий — это стандартный стиль специфика¬
ции операций в языке UML. В UML операции существуют на различных уровнях,
начиная от системных операций и заканчивая операциями отдельных классов, та¬
ких как Sale. Спецификации операций системного уровня составляют часть модели
прецедентов, хотя они формально не выделяются в документации по UP или RUP.
Однако их соответствие модели подтверждено авторами RUP.1ФазыНачало — на этом этапе описания не составляются, поскольку они должны нести
слишком детальную информацию.Развитие — если описания операций вообще создаются, то это происходит на эта¬
пе развития в процессе реализации большинства прецедентов. Описание следует со¬
ставлять только для наиболее сложных и неоднозначных операций.1 В частной беседе.
Глава 11. Описание операций 22311.13. Немного историиОписания операций изначально возникли в компьютерных науках как формаль¬
ные спецификации, предложенные Тони Хоаре (Топу Ноаге). В середине 1960-х годов
он работал над созданием компилятора Алгол 60 и познакомился с книгой Бертрана
Рассела (Bertrand Russell) Introduction to mathematical philosophy (Введение в математическую
философию), в которой высказана идея аксиоматической теории. Он понял, что ком¬
пьютерная программа может быть описана с помощью пред- и постусловий. В 1968
году его идея, наряду с теориями других исследователей в области формальных спе¬
цификаций, получила широкое распространение.В 1974 году в лаборатории IBM в Вене был разработан компилятор PL/1, и ис¬
следователи потребовали формальной спецификации этого языка. Эти потребности
привели к появлению языка VDL (Vienna Development Language), автором которо¬
го стал Питер Лукас (Peter Lucas). В этом языке заимствованы идеи использования
пред- и постусловий. Язык VDL постепенно эволюционировал, и на его основе был
создан метод VDM (Vienna Definition Method), который применяется для формаль¬
ной спецификации описания операций [15].В 1980-х годах форму описания операций с указанием пред- и постусловий пред¬
ложил Бертран Мейер (Bertrand Meyer) (как ни странно, еще один автор компиля¬
тора для объектно-ориентированного языка Eiffel). Он внес значительный вклад в
развитие формальных спецификаций и описание операций. Его идеи нашли отра¬
жение в подходе к проектированию, получившем название проектирование на основе
описаний (Design by contract). В рамках этого подхода составляются описания опера¬
ций программных классов, причем не только для открытых операций системы или
подсистем. Кроме того, в рамках этого подхода в спецификацию включается раздел
инвариантов. В нем определяются элементы, состояние которых не изменяется в
процессе выполнения операции. В этой главе инварианты не рассматривались из со¬
ображений простоты.В начале 1990-х годов применение описаний к операциям объектов кратко описал
Гради Буч (Grady Booch) в предложенном им методе. Эту же идею позаимствовали
Дерек Колеман (Derek Coleman) и его коллеги из лаборатории HP и применили ее к
моделированию предметной области в рамках метода Fusion [38].Языки программирования и описания операцийНекоторые языки программирования, такие как Eiffel, обеспечивают поддержку
инвариантов, а также пред- и постусловий. Аналогичные препроцессоры существуют
и для Java и С#.11.14. Дополнительные ресурсыМногие примеры описания операций можно найти в книге [38]. Примеры описа¬
ний на программном уровне на языке Eiffel приводятся в книге [93]. Более строгое
описание операций в рамках UML обеспечивает язык OCL, которому посвящена кни¬
га Вормера и Клеппа [122].
Итеративный переход
от анализа требований
к проектированиюАппаратное обеспечение — часть компьютерной системы, которую можно разбить.Автор неизвестенОсновные задачи■ Быстро обосновать переход к проектированию.■ Продемонстрировать более важную роль навыков проектирования по
сравнению со знанием системы обозначений UML.ВведениеИтак, к настоящему моменту в рамках данной итерации, в основном, исследованы
требования, понятия и операции, связанные с системой. Согласно принципам UP, на
протяжении начальной фазы нужно проанализировать примерно 10% требований, а
на первой итерации стадии развития начинаются более глубокие исследования. В сле¬
дующих главах основное внимание будет смещено в область разработки проектного
решения для данной итерации в терминах взаимодействия программных объектов.Что дальше? После исследования описания операций в данной главе подытоживаются результаты
анализа и осуществляется переход к проектированию, которое выполняется
на каждой итерации. В следующей главе рассматривается логическая архитектура
рассматриваемых примеров приложений, в основу которой положен шаблон LayersИтеративный
переходСистемные Пеоеход от анализадиаграммы Описания объектному Логическая тРебованийпоследова- операции ппоектиоованию логическая кпроекти-тельностей проектированию архитектура рованиюо о • о о8 Зак. 3357
226 Часть III. Первая итерация фазы развития — основы12.1. Занимаясь итеративной
разработкой, делайте это правильноВ процессе анализа требований и объектно-ориентированного анализа основное
внимание уделялось правильной организации деятельности, т.е. изучению основных
целей примеров, а также связанных с ними правил и ограничений. На следующем
этапе проектирования акцент смещается в сторону правильной реализации постав¬
ленных целей, т.е. разработки грамотного проектного решения, удовлетворяющего
требованиям данной итерации.При итеративной разработке переход от анализа требований к проектированию
и реализации выполняется на каждой итерации. Более того, в процессе проектиро¬
вания и реализации на начальных итерациях некоторые требования естественным
образом изменяются. На ранних итерациях основное внимание уделяется анализу.
После формирования общего ведения системы представление о ней стабилизирует¬
ся на основе раннего программирования, тестирования и обратной связи. На после¬
дующих итерациях выполняется анализ предшествующей деятельности, но основное
внимание уделяется построению программных решений.12.2. Раннее начало всех видов деятельностиЕстественно, на этапах проектирования и реализации изменяются и модифициру¬
ются некоторые требования к системе, особенно на ранних итерациях. Итеративные
и эволюционные методы разработки предполагают внесение существенных измене¬
ний на ранних итерациях, чтобы к более поздним итерациям развития проекта цель
создания системы, а значит, и график ее реализации, были достаточно стабильными.
Раннее программирование, тестирование и демонстрация работы системы пользова¬
телям призваны обеспечить эти ранние изменения. Эта простая идея лежит в основе
итеративной разработки.Благодаря изменению спецификации проясняются задачи проектирования на дан¬
ной итерации и уточняются требования, реализуемые на последующих итерациях. В
результате, к моменту завершения фазы развития, требования к системе в основном ста¬
билизируются, и примерно 80% из них уже определены детально. Это является резуль¬
татом раннего программирования, тестирования и обратной связи, а не голословных
рассуждений, как это было при использовании каскадного метода проектирования.12.3. Возможно, на это потребуются недели?После подробного обсуждения этапа анализа на страницах нескольких глав может
создаться впечатление, что для моделирования требуется несколько недель. Вовсе нет.Если разработчик умеет описывать прецеденты, строить модель предметной обла¬
сти и т.д., то на выполнение всех видов деятельности по моделированию потребуется
от силы несколько дней.Это не означает, что проектирование системы начинается через несколько дней
после начала проекта. Несколько недель занимает подготовка: создание программ¬
ных прототипов для проверки правильности концепции (proof-of-concept program¬
ming), поиск ресурсов (человеческих, программных и т.д.), планирование, создание
окружения и т.п.
ГлаваЛогическая архитектура
и диаграммы пакетов UML0x2В | ~0х2В
Гамлет (Hamlet)Основные задачи■ Составить представление о логической архитектуре системы в терми¬
нах уровней.■ Проиллюстрировать логическую архитектуру на языке UML с исполь¬
зованием диаграмм пакетов.ВведениеДля ясности сразу же оговоримся, что в этой главе речь пойдет о введении в логи¬
ческую архитектуру, поскольку эта область очень широка. Более подробно этот во¬
прос рассматривается в главе 34.При переходе от анализа к проектированию системы необходимо посмотреть на
систему в целом с высоты “птичьего полета”. На этом уровне абстракции проекти¬
рование типичной объектно-ориентированной системы основывается на нескольких
архитектурных уровнях, как то уровень интерфейса пользователя, логики приложе¬
ния (или предметной области) и т.д. В этой главе кратко рассматривается архитекту¬
ра системы, а также затрагиваются вопросы взаимодействия пакетов.
228 Часть III. Первая итерация фазы развития - основыЧто дальше?После перехода к проектированию на данной итерации в этой главе
рассматривается понятие логической архитектуры. В следующей главе подводятся
итоги проектирования объектов и рассматриваются вопросы статического
и динамического моделирования. При этом особый акцент делается на том, что
важнее иметь навыки проектирования, а не просто владеть системой обозначений
UML/\ОписанияоперацийПереход
к объектному
проектированиюЛогическаяархитектураИтеративный пк Диаграммыпереход от анализа к -* w взаимодеи-требовании .....к ствия UML
к проектированию о оПримеры артефактов UP с точки зрения логической архитектуры (ЛА) показаны
на рис. 13.1. Из диаграммы пакетов UML видно, что логическая архитектура состав¬
ляет часть модели проектирования и отображается в документе, описывающем про¬
граммную архитектуру. Входными данными для его построения служит дополнитель¬
ная спецификация. Логическая архитектура определяет пакеты, в рамках которых
создаются программные классы.13.1. ПримерНа рис. 13.2 показан фрагмент трехуровневой логической архитектуры, представ¬
ленной в терминах диаграммы пакетов UML (package diagram).13.2. Что такое логическая архитектураЛогическая архитектура (logical architecture) описывает систему в терминах ее
принципиальной организации в виде уровней, пакетов (или пространств имен), про¬
граммных классов и подсистем. Она называется логической, поскольку не определяет
способы развертывания этих элементов в различных операционных системах или на
физических компьютерах в сети (это относится к архитектуре развертывания (deploy¬
ment architecture)).Уровень (layer) — это крупномасштабная группа классов, пакетов или подсистем,
имеющих сходные обязанности для большинства аспектов системы. Уровни организу¬
ются в группы (например, уровень интерфейса пользователя). К типичным уровням
объектно-ориентированной системы относятся следующие.■ Интерфейс пользователя (user interface).■ Уровень приложения или объектов предметной области (application logic and
domain objects). К этому уровню относятся программные объекты, представля¬
ющие понятия предметной области (например, программный класс Sale) и
обеспечивающие выполнение требований к системе (например, вычисление
общей стоимости покупки),■ Уровень технических служб (technical services). Объекты и подсистемы обще¬
го назначения, обеспечивающие поддержку взаимодействия с базой данных
или журналов регистрации ошибок. Эти службы обычно независимы от при¬
ложения, и их можно повторно использовать в нескольких системах.
Глава 13. Логическая архитектура и диаграммы пакетов UML 229Пример взаимосвязи артефактов UPМодель предметной областиБизнес-
модели -
рованиеОпреде-Модель прецедентовВидениетребо¬ванийДополнительнаяспецификацияСловарь1:ТЛогическая архитектура определяется
ограничениями и нефункциональными
требованиями, сформулированными
в дополнительной спецификацииДиаграммы пакетовлогическойархитектуры(статическоепредставление)Проекти¬рование\ОбъектыпредметнойобластиТехническиеслужбыДиаграммывзаимодействия(динамическоепредставление):Registerenterltem
(itemID, quantity)• ►:ProductCatalogspec = getProductSpec( itemID )Диаграммыклассов(статическоепредставление)ЧRegister1 1
 >■ProductCatalogmakeNewSale()
enterltem(...)getProductSpec(...)Рис. 13.1. Пример взаимосвязи артефактов UP
230 Часть III. Первая итерация фазы развития — основыРис. 13.2. Представление уровней на диаграмме пакетов UMLВ жестко структурированной многоуровневой архитектуре объекты каждого уровня мо¬
гут вызывать службы только уровня, расположенного непосредственно под ним.Такой принцип лежит в основе стека сетевых протоколов, но в информационных
системах обычно используется гибкая многоуровневая архитектура, при которой объек¬
ты могут обращаться к нескольким уровням, расположенным ниже. Например, объекты
уровня интерфейса пользователя могут обращаться напрямую к уровню логики при¬
ложения, а также к элементам нижнего уровня технических служб.Логическая архитектура не связана с многоуровневой организацией. Но автору
показалось, что сейчас самое время ввести это понятие.13.3. На каких уровнях сосредоточено
описание примеров?Повторим идею, которая уже приводилась в начале описания примеров.Хотя объектную технологию можно применять ко всем уровням, материал дан¬
ной книги сосредоточен на базовом уровне логики приложения, в то время как
остальные уровни затрагиваются лишь поверхностно.При изучении остальных уровней, например интерфейса пользователя, основное
внимание будет уделяться его взаимодействию с уровнем логики приложения.
Глава 13. Логическая архитектура и диаграммы пакетов UML 231Ранее кратко упоминалось, что остальные уровни являются технологически зави¬
симыми, а любые проектные решения для уровня приложения применимы также к
остальным уровням и компонентам.13.4. Программная архитектура системыПриведем одно из определений программной архитектуры системы (software archi¬
tecture).“Архитектура — это набор важных решений, касающихся организации про¬
граммной системы, выбора структурных элементов и их интерфейсов, затраги¬
вающих поведение и взаимодействие этих элементов, их группировку в более
крупные подсистемы и архитектурный стиль приложения. К архитектуре отно¬
сятся элементы, их интерфейсы и принципы их взаимодействия.” [24]Независимо от определения (а их существует множество), архитектура системы
включает крупномасштабные элементы — основные идеи организации, шаблоны, спо¬
соб распределения обязанностей, взаимодействие и мотивацию поведения системы и
ее основных подсистем.13.5. Диаграммы пакетов UMLДиаграммы пакетов UML используются для иллюстрации логической архитекту¬
ры приложения — уровней, подсистем, пакетов (в смысле Java). Каждый уровень мож¬
но представить в виде пакета, например, уровень интерфейса пользователя можно
моделировать с помощью пакета UI.Диаграмма пакетов обеспечивает один из способов группировки элементов.
В одном пакете UML могут объединяться различные элементы: классы, другие паке¬
ты, прецеденты и т.д. Зачастую используются вложенные пакеты. Пакет UML — это
более общее понятие, чем пакет Java или пространство имен .NET, которые могут
включаться в состав пакета UML.Имя пакета располагается на корешке, если на диаграмме отображается внутрен¬
нее содержимое пакета, либо на самом обозначении пакета.Зачастую изображают зависимости между пакетами, чтобы разработчикам была
понятна взаимосвязь элементов системы. Для этого используется линия зависимости
UML (dependency line), представляющая собой пунктирную линию со стрелкой, на¬
правленную в сторону независимого пакета. Пакет UML представляет собой простран¬
ство имен (namespace), поэтому класс Date может быть определен в двух различных
пакетах. Если нужно обеспечить полную квалификацию имен, используется обозначе¬
ние вида java: :util: :Date, описывающее вложенность пакетов java и util.В языке UML существуют и другие обозначения вложенных пакетов. Иногда вло¬
женные пакеты графически размещаются внутри более общего пакета. Различные
обозначения вложенных пакетов показаны на рис. 13.3.
232 Часть III. Первая итерация фазы развития — основыРис. 13.3. Альтернативные подходы к изображению вложенных пакетов в UMLОбратное проектирование диаграммы
пакетов на основе кодаНа ранних стадиях разработки можно быстро построить диаграмму пакетов UML
и затем организовать свой код в соответствии с этой диаграммой. Со временем код
разрастается, и разработчики все больше внимания уделяют программированию, а не
моделированию. На этих стадиях полезно использовать специальные CASE-средства
для обратного проектирования и автоматического построения диаграммы пакетов на
основе исходного кода.При этом желательно использовать предложенные в следующем разделе соглаше¬
ния по именованию пакетов.13.6. Проектирование на основе шаблона LayersОсновные принципы шаблона Layers [17] сводятся к следующему.■ Организовать крупномасштабные структурные элементы системы в отдельные
уровни со взаимосвязанными обязанностями таким образом, чтобы на нижнем
уровне располагались низкоуровневые службы и службы общего назначения, а
на более высоких уровнях — объекты уровня логики приложения.■ Взаимодействие и связывание уровней происходит сверху вниз. Нужно избе¬
гать связывания объектов снизу вверх.Более подробная информация об использовании этого шаблона содержится в гла¬
ве 34. Шаблон Layers определяет общую Л^уровневую модель логической архитекту¬
ры. На его основе строится многоуровневая архитектура (layered architecture) [17]. Его
принципы настолько часто формулировались в виде шаблонов, что в книге [106] на¬
считывается порядка сотни его вариаций.
Глава 13. Логическая архитектура и диаграммы пакетов UML 233Использование шаблона Layers позволяет решить следующие возможные проблемы.■ Изменение исходного кода влечет за собой корректировку всех элементов си¬
стемы, поскольку все части системы тесно связаны друг с другом.■ Логика приложения переплетается с интерфейсом пользователя, поэтому в
приложении нельзя изменить интерфейс или принципы реализации логики
приложения.■ Общие технические службы тесно связаны с бизнес-логикой приложения, поэ¬
тому их нельзя использовать повторно, распространить на другие системы или
изменить их реализацию.■ Из-за высокой степени связывания сложно модифицировать функции приложе¬
ния, масштабировать систему или переходить на новые технологии.Количество и функции уровней зависят от типа приложения и его предметной* области (информационная система, операционная система и т.д.). Типичные уровни
информационной системы показаны на рис. 13.4.Уровень приложения, представленный на рис. 13.4, будет описан в главе 34.Преимущества использования шаблона Layers■ В целом, этот шаблон обеспечивает разделение разных аспектов, высокоуров¬
невых служб от низкоуровневых, специализированных функций от общих. Это
снижает уровень связывания и зависимости в приложении, повышает степень
зацепления, увеличивает потенциал повторного использования и вносит допол¬
нительную ясность.■ Сложные элементы подвергаются декомпозиции и подлежат инкапсуляции.■ Некоторые уровни заменяются новыми реализациями. В общем случае это не
возможно для низкоуровневых технических служб и базового уровня (в частно¬
сти, java.util), однако вполне реально для уровней интерфейса, приложения
и предметной области.■ Нижние уровни содержат повторно используемые функции.■ Некоторые уровни (особенно уровни предметной области и технических служб)
могут быть распределенными.■ Логическая сегментация обеспечивает возможность работы над приложением
группы разработчиков.Связывание обязанностейОбязанности объектов одного уровня должны быть тесно связаны между собой
и отличаться от обязанностей объектов других уровней. Например, объекты уровня
интерфейса пользователя должны отвечать за создание диалоговых окон, элементов
управления, обработку событий мыши и клавиатуры и т.д. Объекты уровня логики
приложения должны сконцентрироваться на реализации функций предметной об¬
ласти, например, вычисления общей стоимости покупки, налога или перемещения
фишки по игральной доске.
234 Часть III. Первая итерация фазы развития — основы* Окна графического интерфейса► Отчеты► Голосовой интерфейс► HTML, XML, XSLT, JSP, Javascript,...Уровень представления(пользовательского интерфейса)Обработка запросов уровня
представления
Потоки управленияПоследовательность событий состояние
сеансаПереходы между окнами/страницами
Объединение/преобразование
разнородных данных для объектовОбработка запросов уровня приложения"^
Реализация бизнес-правил предметной
областиСлужбы из предметной области (POS,
бухгалтерия)Такие службы могут использоваться
лишь одним приложением, однако можно
создать службы и для нескольких
приложений уУ>Уровень приложения(управления потоками
выполнения, процессами,
промежуточный уровень
или контроллер приложения)Уровень объектов
предметной области(или бизнес-логики приложения,
модели)СтепеньспецификидляприложенияА1!I!0Q ,
СО 1со I
YОбобщенные низкоуровневые
производственные службы,
используемые во многих предметных
областяхСлужба конвертирования валютВысокоуровневые (относительно)
службы и контуры, например, хранения
данных и обеспечения безопасностиНизкоуровневые технические службы,
утилиты и контурыСтруктуры данных, потоки, математи¬
ческие операции,средства взаимодей¬
ствия с файлами, базой данных и сетьюШирина определяет степень применимости w
 . ^Рис. 13.4. Типичные уровни логической архитектуры информационной системы’}1 Ширина условного обозначения пакета пропорциональна степени его применения, одна
ко это не является стандартным обозначением UML. В круглых скобках приводятся другие на
звания уровня.
Глава 13. Логическая архитектура и диаграммы пакетов UML 235Объекты уровня интерфейса пользователя не должны реализовывать логику при¬
ложения. Например, объект JFrame пакета java. swing, отвечающий за создание
окна, не должен заниматься вычислением налога и перемещением фишки. С другой
стороны, классы логики приложения не должны обрабатывать события мыши и кла¬
виатуры. В этом состоит поддержка базового архитектурного принципа высокого за-
цепления (high cohesion).Эти важные принципы, наряду с принципом Model-View-Separation (MVS), более
подробно будут описаны ниже.Представление реализации: распределение
исходного кода по уровням и пакетамБольшинство популярных объектно-ориентированных языков, таких как Java,
С#, C++, Python, обеспечивает простую поддержку пакетов (в языках C++ и C# — про¬
странств имен).Приведем пример преобразования пакетов UML в код Java. Эти уровни и пакеты
показаны на рис. 13.2. Обратите внимание, что имена уровней используются как раз¬
делы имен пакетов Java.//— УРОВЕНЬ ИНТЕРФЕЙСАcom.mycompany.nextgen. ui.swingсот.mycompany.nextgen.ui.web// — УРОВЕНЬ ПРЕДМЕТНОЙ ОБЛАСТИ11 пакеты, специфические для проекта NextGen
com. mycompany.nextgen.domain.sales
com. mycompany.nextgen.domain.payments//— УРОВЕНЬ ТЕХНИЧЕСКИХ СЛУЖБ
// разработки нашей группы разработчиков
com.mycompany.service.persistence// сторонних производителей
org.apache.log4j
org.apache.soap.rpc// БАЗОВЫЕ СЛУЖБЫ// созданные нашей группой разработчиков
com.mycompany.utilОбратите внимание, что в именах пакетов без необходимости не упоминается
квалификатор конкретного приложения (nextgen). Он участвует только в именах
пакетов, связанных с интерфейсом пользователя приложения NextGen, например
com. mycompany. next gen. ui.*. Для облегчения повторного использования имена
элементов должны, по возможности, не зависеть от имени приложения. Например,
созданная группой разработчиков библиотека утилит общего назначения размещена
в пакете com.mycompany.util, а не в сот.mycompany.nextgen.util.
236 Часть III. Первая итерация фазы развития - основыПостроение диаграммы пакетов на основе исходного кодаУже отмечалось, что существуют специальные CASE-средства для автоматическо¬
го построения диаграммы пакетов UML на основе исходного кода. Для повышения
эффективности этой процедуры следует придерживаться определенных соглашений
по именованию. Например, если во все имена Java-пакетов уровня интерфейса поль¬
зователя включить фрагмент .ui., то CASE-средство автоматически сгруппирует эти
пакеты в пакет ui, и многоуровневая архитектура будет отражена как в коде, так и на
диаграмме пакетов.Уровень предметной области или логики приложенияВ этом разделе описываются простые, тем не менее базовые, понятия объектно-
ориентированного проектирования.В типичном программном приложении имеются уровни интерфейса пользователя
и логики приложения, отвечающие за создание элементов пользовательского интер¬
фейса и вычисление налога. Возникает вопрос, как спроектировать логику приложе¬
ния на основе объектного подхода.Можно создать один класс XYZ и поместить в него все методы, реализующие
логику предметной области. Он будет работать (хотя его изучение и окажется на¬
стоящим кошмаром), однако автор не рекомендует придерживаться такого способа
мышления.Как же решить эту проблему? Необходимо создать программные объекты, имена
которых соответствуют сущностям предметной области, и присвоить им обязанно¬
сти по реализации логики приложения. Например, в реальном мире существует POS-
система, обрабатывающая продажи и платежи. Поэтому имеет смысл создать классы
Sale и Payment, назначив им соответствующие обязанности. Такие программные
объекты называются объектами предметной области (domain object). Они обеспечива¬
ют реализацию бизнес-логики, например, объект Sale отвечает за вычисление стои¬
мости покупки.В этом контексте уровень логики приложения следует называть уровнем предметной
области (domain layer).Взаимосвязь уровня и модели предметной областиЕще один важный вопрос: какова взаимосвязь между уровнем и моделью предмет¬
ной области? Модель предметной области (представляющая собой визуализацию по¬
нятий предметной области) служит для выделения имен классов уровня предметной
области (рис. 13.5).Уровень предметной области является частью программной реализации, а модель
предметной области — частью концептуального аспекта анализа. И это разные вещи.
Однако, создавая объекты уровня предметной области на основе соответствующей
модели, мы сокращаем разрыв представления (representational gap) между реальным ми¬
ром и его программной реализацией. Например, концептуальный класс Sale из мо¬
дели предметной области становится прототипом программного класса Sale уровня
логики приложения в модели проектирования.
Глава 13. Логическая архитектура и диаграммы пакетов UML 237Модель предметной области в рамках UP
Понятия предметной области с точки зрения заинтересованных лицВ модели предметной ^области Payment — это понятие,
а в модели проектирования
Payment представляет собой
программный класс. Эти
сущности отличны друг от друга,
однако первая из них оказывает
влияние на имя и определение
второй.Такой подход позволяет
сократить разрыв между
ментальными и программными
моделями.Это одна из наиболее важных
идей объектной технологииPaymentч1 Оплачивает 1Saleг amountdatetimeВлияют- на имена
объектовPaymentС)amount: MoneygetBalance(): Money1 Оплачивает 1К — ИSaledate: DatestartTime:TimegetTotal():MoneyУровень объектов предметной области архитектуры
в рамках модели проектирования UPПри создании программных классов разработчик объектно-
ориентированной системы учитывает понятия из предметной области.Таким образом, удается сократить разрыв между представлением
заинтересованных лиц о понятиях предметной области
и представлением этих понятий в программном обеспеченииРис. 13.5. Взаимосвязь уровня и модели предметной областиУровни и разделыИзначально термин “уровень” относился только к логическому представлению
архитектуры, а не к физическому узлу. Однако он стал широко использоваться и в
значении физического обрабатывающего элемента (узла или кластера узлов), напри-
меР “уровень клиента” (в смысле клиентского компьютера). В этой книге для ясности
автор старался не смешивать эти два понятия, однако в другой литературе по архи¬
тектуре приложений можно встретить оба значения этого термина.Архитектурные уровни (layer) представляют деление системы по вертикали, а разде¬
лы (partition) — по горизонтали на параллельные подсистемы в рамках одного уровня.
Например, уровень служб можно разделить на разделы, отвечающие за выполнение
требований безопасности и формирование отчетов (рис. 13.6).Внешние ресурсы или уровень внешней базы данныхБольшинство систем опирается на внешние ресурсы или службы, такие как базы
данных Oracle или службу имен и каталогов Novell LDAP. В логическом представле¬
нии архитектуры можно использовать не только уровни, но и физические реализа¬
ции компонентов.
238 Часть III. Первая итерация фазы развития — основыОбъекты
предметной областиУровни по
вертикалиТехнические службыХранилищеБезопасностьРегистрациясобытий<4 Разделы по горизонтали ►Рис. 13.6. Уровни и разделыЕсли ниже базового уровня изобразить внешние ресурсы или конкретную базу
данных, то такая диаграмма будет совмещать логическое представление системы с
представлением реализации или развертывания.В терминах логического представления архитектуры доступ к конкретной базе
данных отображается как пакет уровня предметной области. При этом для доступа к
базе данных можно использовать пакет Persistence (Хранилище) раздела техниче¬
ских служб (рис. 13.7).13.7. Принцип Model-View SeparationКак можно обеспечить взаимодействие других пакетов с уровнем представления?
Как классы, не имеющие отношения к интерфейсу пользователя, должны взаимодей¬
ствовать с окнами?СоветЭтот принцип можно сформулировать так.1. Не связывайте объекты интерфейса пользователя с объектами других уровней
напрямую. Например, программный объект Sale уровня предметной области
не должен иметь ссылку на оконный объект JFrame пакета java. swing. Дело
в том, что окна связаны с конкретным приложением, а остальные компоненты
(в идеале) могут повторно использоваться в новых приложениях или допол¬
няться другим интерфейсом.2. Не используйте имена объектов логики приложения в методах объектов ин¬
терфейса пользователя. Объекты интерфейса пользователя должны лишь
инициализировать соответствующие элементы интерфейса, получать сообще¬
ния о событиях (например, о перемещении мыши или щелчке на кнопке) и
делегировать запросы объектам уровня логики приложения.
Глава 13. Логическая архитектура и диаграммы пакетов UML 239Плохо. ^Логическое представление
смешано с представлением
реализацииЛучше.Логическое представлениеОбъекты
предметной областиТехническиеслужбыБазовыеслужбыКаталогMySQL«component»
NOVELL LDAPО-;;:.,Объекты предметной области , ,POSКаталог сТехнические сдеясбыЛогическое ■представлениетребуемых данныхили служббез отображенияреальныхкомпонентов, таких
как база данныхХранилищеСлужбы имен
и каталоговКаркас
взаимодействия
с WebБазовыеслужбыОбозначение UML: компонент UML или модуль, заменяемая часть физической системыОбозначение UML: физическая база данных в UMLРис. 13.7. Комбинация разных представлений архитектурыВ этом контексте “модель” — это синоним объектов уровня предметной области,
а “внешнее представление” — это объекты уровня представления, такие как окна,
аплеты и отчеты.Согласно принципу Model-View Separation2, объекты модели (уровня предметной
области) не должны напрямую взаимодействовать с объектами уровня представления.
Например, объект Register или Sale не должен напрямую отправлять сообщения
об изменении цвета или о закрытии объекту окна ProcessSaleFrame.Некоторое “смягчение” этого принципа обеспечивает шаблон Observer, соглас¬
но которому объекты уровня предметной области отправляют сообщения объектам
интерфейса пользователя, рассматриваемым только в качестве связующих объектов
между уровнями (PropertyListener).Этот шаблон содержит еще одну рекомендацию: классы уровня предметной об¬
ласти должны инкапсулировать информацию и поведение, связанные с логикой при¬2 Этот принцип является ключевым в шаблоне Model-View Controller (MVC). Шаблон MVC
изначально появился как мелкомасштабный шаблон для языка Smalltalk-80. Согласно этому ша¬
блону, объекты данных (модели) взаимодействовали с объектами GUI (внешним представлени¬
ем) через обработчики событий мыши и клавиатуры (контроллеры). В настоящее время тер¬
мин MVC в сообществе разработчиков распределенных систем применяется при обсуждении
крупномасштабных архитектурных решений. В качестве модели здесь выступает уровень пред¬
метной области, а в качестве внешнего представления — уровень интерфейса. Контроллерами
при этом являются объекты уровня приложения.
240 Часть III. Первая итерация фазы развития — основыложения, а классы окон являются относительно “тонкими”. Они отвечают лишь за
ввод и вывод информации, но не поддерживают обработку данных или функции при¬
ложения. Например, оконный объект JFrame не должен вычислять налоги, объекты
интерфейса пользователя должны делегировать выполнение этих обязанностей объ¬
ектам других уровней.Применение принципа Model-View Separation предоставляет следующие возмож¬
ности.■ Поддерживает высокий уровень зацепления специальных объектов и позволяет
сконцентрировать внимание на процессах предметной области, а не на вопро¬
сах интерфейса.■ Позволяет разделить процесс разработки уровней модели и интерфейса поль¬
зователя.■ Минимизирует влияние изменений интерфейса на специальные объекты.■ Позволяет легко подключить новый интерфейс, не затрагивая уровень реали¬
зации.■ Позволяет одновременно использовать несколько различных представлений
для одного и того же специального объекта, например, вывести информацию о
продажах в виде таблицы и диаграммы.■ Обеспечивает выполнение задач уровня реализации независимо от интерфейса
пользователя, например обработку сообщений в пакетном режиме.■ Упрощает переход к другому каркасу интерфейса пользователя.13.8. Взаимосвязь между СДП, системными
операциями и уровнямиНа этапе анализа строятся системные диаграммы последовательностей для сце¬
нариев прецедентов. При этом идентифицируются входные события, иницииру¬
емые внешними исполнителями, а также вызовы системных операций, например
makeNewSale или enterltem.На диаграммах последовательностей изображают системные операции, а не пред¬
ставления объектов. Однако обычно эти системные операции перехватываются объ¬
ектами интерфейса пользователя.В хорошо спроектированной архитектуре, поддерживающей принцип высокого
зацепления и разделения обязанностей, объекты уровня интерфейса пользователя
направляют или делегируют эти запросы объектам уровня предметной области.Отметим очень важный момент.Сообщения, отправляемые с уровня интерфейса пользователя объектам предмет¬
ной области, обычно отображаются на СДП, например enterltem.Например, в Java Swing класс окна ProcessSaleFrame уровня пользовательского
интерфейса перехватывает событие мыши и клавиатуры, а затем отправляет сообще¬
ние enterltem программному объекту Register уровня предметной области для его
обработки (рис. 13.8).
Глава 13. Логическая архитектура и диаграммы пакетов UML 241Рис. 13.8. Системные операции на системной диаграмме последовательностей в терминахуровней системы13.9. Логическая архитектура и диаграмма
пакетов для приложения NextGenЛогическая архитектура этого приложения для данной итерации показана на
рис. 13.2. Она станет более интересной на последующих стадиях разработки. Многие
примеры диаграмм пакетов приложения NextGen будут приведены в главе 34.13.10. Пример логической архитектуры
игры “Монополия”Архитектура для игры “Монополия” имеет простую структуру, состоящую из трех
уровней — интерфейса пользователя, предметной области и служб. В ней нет ничего
нового, поэтому в качестве примеров в этой главе рассматриваются диаграммы для
приложения NextGen.
242 Часть III. Первая итерация фазы развития — основы13.11. Дополнительные ресурсыМногоуровневой архитектуре приложений посвящено множество публикаций,
как печатных, так и электронных. Шаблоны для проектирования такой архитектуры
впервые предложены в первом томе книги [44], однако сама архитектура описана во
многих работах начиная с 60-х годов. Во втором томе указанной книги приводятся
новые шаблоны, относящиеся к многоуровневой архитектуре. Шаблон Layers хорошо
описан в книге [17] (том 1).
Переход к объектному
проектированиюЯ не люблю слово “бомба ”. На самом деле это не бомба, а взрывное устройство.
Амбассадор Джакус ле Бланк (Ambassador Jacques le Blank) о ядерных вооруженияхОсновные задачи■ Ознакомиться с динамическими и статическими аспектами объект¬
ных моделей проектирования»■ Применить гибкий подход к моделированию и специальные CASE-
средства для построения диаграмм UML.ВведениеКак разработчики проектируют объекты? Существует три способа.1. Написание программного кода. Проектирование в процессе кодирования (на
Java, C# и т.д.) лучше всего выполнять с помощью такого мощного средства, как
рефакторинг (refactoring). При этом происходит переход от ментальной модели
к ее воплощению в программном коде.2. Рисование с последующим кодированием. Этот метод подразумевает построе¬
ние диаграмм UML на доске или с помощью специальных CASE-средств, а затем
переход к п. 1 с использованием специальных интегрированных сред разработ¬
ки IDE (например, Eclipse или Visual Studio).3. Рисование. Некоторые CASE-средства позволяют сгенерировать код на основе
диаграмм. Такое название процесса может ввести в заблуждение, поскольку в
нем все равно участвует язык программирования, связанный с графическими
элементами UML.
244 Часть III. Первая итерация фазы развития — основыЧто дальше?Переход
к объектному
проектированиюПосле построения многоуровневой логической архитектуры в данной главе
выполняется переход к проектированию объектов. В следующей главе содержится
справочный материал по системе обозначений диаграмм взаимодействия UML,
которые чрезвычайно полезно применять для детального проектирования объектовЛогическаяархитектураИтеративный
переход от анализа
требований
к проектированию
—•—\ДиаграммывзаимодействияUMLДиаграммыклассовUMLСуществуют и другие способы проектирования на других языках.1 При использо¬
вании второго подхода, предполагающего построение диаграмм с последующим ко¬
дированием (при этом для моделирования чаще всего используется UML), затраты
на построение диаграмм должны быть не слишком высокими. В этой главе представ¬
лены основы объектного проектирования и “облегченного” моделирования, позволя¬
ющего снизить трудозатраты на построение объектной модели.14.1. Гибкое моделирование и облегченный
процесс построения диаграмм UMLЦелью гибкого моделирования [6] является снижение затрат на построение диа¬
грамм и использование моделей для улучшения понимания и взаимодействия между
разработчиками. При этом модель не рассматривается в качестве документа, хотя его
легко получить с помощью цифровой фотокамеры. Испытайте на себе простой под¬
ход к гибкому моделированию. При этом вам понадобится доска, а лучше несколько в
одной комнате, или специальные пластиковые листы, покрывающие всю свободную
площадь стен, маркеры, цифровые камеры, а также принтер для фиксации получен¬
ных моделей [55].Гибкое моделирование подразумевает:■ групповую работу;Ш параллельное создание нескольких моделей. Например, 5 минут можно потратить на
построение диаграмм взаимодействия, а затем еще 5 минут — на создание соот-
ветствующих диаграмм классов.Какой должна быть площадь для рисования диаграмм? Большинство людей пред¬
почитают большое пространство. Однако на сегодняшний день не существует деше¬
вых средств для построения виртуальной реальности UML. Простая альтернатива
огромной доске — множество белых пластиковых листов (или досок). Это соответ¬
ствует основному принципу экстремального программирования: решения должны
быть максимально простыми.1 Каким будет язык следующего, пятого поколения? Существует мнение, что он будет позво¬
лять генерировать символы программного кода на основе текстовых или графических описа¬
ний. Согласно другой точке зрения язык пятого поколения должен быть более декларативным,
чем процедурным, хотя подобные свойства демонстрируют уже и языки четвертого поколения.
Глава 14. Переход к объектному проектированию 245Можно дать еще один совет: цифровые фотографии построенных на доске моде¬
лей легко загрузить в специальную систему wiki (www.twiki.org), в которой хранится
вся информация по проекту.14.2. CASE-средства UMLНа основе вышеизложенного материала можно сделать неправильный вывод о
том, что CASE-средства UML в свете гибкого моделирования вообще не нужны. На
самом деле важны оба подхода. CASE-средства варьируются от бесплатных с откры¬
тым кодом до очень дорогих, и каждый год их функции улучшаются. Учитывая измен¬
чивость рынка CASE-средств, мы не станем приводить конкретные рекомендации, а
ограничимся несколькими общими советами.СоветШ Выбирайте CASE-средство, интегрированное с популярными средами разработ¬
ки, например Eclipse или Visual Studio.■ При выборе CASE-средства UML отслеживайте наличие функции обратного
проектирования (генерирования диаграмм на основе кода). Хорошие CASE-
средства обеспечивают не только построение диаграмм классов, но и диаграмм
взаимодействия.Многие разработчики предпочитают сначала создать код в любимой ими среде
разработки, а затем щелкнуть на кнопке обратного проектирования и получить пол¬
ное графическое представление проектного решения на языке UML.В рамках гибкого моделирования построение диаграмм на доске и с помощью
CASE-средств являются взаимодополняющими методами. Обычно эти способы
проектирования используются на различных стадиях выполнения проекта.14.3. Сколько времени занимает рисование
до начала кодированияСоветЕсли на выполнение одной итерации отводится три недели, то в начале итера¬
ции нужно выделить несколько часов (максимум один день) для построения диаграмм
UML, отражающих наиболее сложные и нестандартные фрагменты проектного
решения. Затем можно сфотографировать полученные модели, распечатать их и
перейти к написанию программного кода на данной итерации. При этом необ¬
ходимо понимать, что окончательное проектное решение будут улучшено и мо¬
дифицировано в процессе кодирования. В течение каждой итерации можно вы¬
делить еще несколько моментов времени для построения диаграмм.
246 Часть III. Первая итерация фазы развития — основыВ рамках гибкого моделирования перед началом каждой итерации необходимо
выполнить обратное проектирование программного кода, распечатать полученные
диаграммы UML (возможно, на большом плоттере), а затем обращаться к ним при
построении моделей на следующей итерации.14.4. Статические и динамические
модели объектовСуществует два типа моделей объектов: статические и динамические. Динамические
модели (dynamic model), в том числе диаграммы взаимодействия UML (диаграммы по¬
следовательностей (sequence diagram) и коммуникации (communication diagram)), позво¬
ляют спроектировать логику приложения, поведение или методы объектов. Они яв¬
ляются более интересными, сложными и важными. Статические модели (static model),
в том числе диаграммы классов UML, позволяют спроектировать пакеты, имена клас¬
сов, атрибуты и сигнатуры методов (но не их реализацию). Динамическая и статиче¬
ская модели показаны на рис. 14.1.Статические и динамические модели в рамках гибкой разработки создаются па¬
раллельно: сначала строятся диаграммы взаимодействия (динамические), а затем со¬
ответствующие диаграммы классов (статические).Динамические модели объектовНовички в проектировании и изучении UML зачастую считают более важными
статические диаграммы классов. На самом деле более интересными, нетривиальны¬
ми и полезными с точки зрения проектирования являются динамические диаграммы
взаимодействия. Именно в процессе динамического моделирования (построение диа¬
грамм последовательностей) продумываются реальные детали поведения и взаимо¬
действия объектов путем передачи сообщений и реализации методов.
Глава 14. Переход к объектному проектированию 247Поэтому в данной книге описание динамических моделей начинается с изучения
диаграмм взаимодействия.СоветУделяйте достаточно внимания диаграммам взаимодействия (последовательно¬
стей или коммуникации), а не только диаграммам классов.Игнорирование этой рекомендации является типичной ошибкой проектирова¬
ния.Именно в процессе динамического моделирования применяются шаблоны GRASP
и реализуется проектирование на основе распределения обязанностей (responsibility-driven
design). Этим вопросам посвящены следующие главы данной книги. Эти моменты яв¬
ляются ключевыми в объектно-ориентированном проектировании.В активе UML существуют и другие средства динамического моделирования. К
ним относятся диаграммы состояний и видов деятельности.Статическое моделированиеНаиболее типичными статическими моделями являются диаграммы классов UML.
Заметим, что при гибком подходе к моделированию различные модели создаются па¬
раллельно.К другим типам статических моделей UML относятся диаграммы пакетов (package
diagram) и диаграммы развертывания (deployment diagram).14.5. Важнее иметь навыки объекткого
проектирования, чем знать
систему обозначений UMLВ последующих главах рассматривается процесс создания этих артефактов, или,
точнее, навыки объектного проектирования, лежащие в основе их создания. Очень
важно уметь мыслить объектами и проектировать в рамках объектного подхода. Это
гораздо важнее, чем просто знать систему обозначений языка UML. В то же время
стандартный язык визуального моделирования обеспечивает дополнительные воз¬
можности для выполнения этих видов деятельности, поэтому будет представлена си¬
стема обозначений UML для поддержки проектирования.При построении объектных диаграмм необходимо ответить на следующие клю¬
чевые вопросы. Каковы обязанности объектов? С кем они взаимодействуют? Какие
шаблоны проектирования необходимо применить? Это гораздо важнее, чем знать от¬
личия в обозначениях UML версии 1.4 и 2.0. Поэтому в следующих главах основное
внимание уделяется принципам распределения обязанностей и применению шабло¬
нов в процессе объектного проектирования.
248 Часть III. Первая итерация фазы развития — основыНавыки объектного проектирования и система обозначений UMLДиаграммы взаимодействия на языке UML отражают принимаемые проектные
решения, поэтому навыки объектного проектирования лежат в основе построе¬
ния диаграмм UML.При создании диаграмм взаимодействий необходимо знать следующее.■ Принципы распределения обязанностей.■ Шаблоны проектирования.Поскольку люди мыслят по-разному и имеют разный опыт разработки систем, они
могут предпочитать и различные методы проектирования. Не надо думать, что все
люди предпочитают картинки, а не текстовые описания или наоборот.Популярным текстовым средством моделирования являются карты CRC (CRC
cards — Class-Responsibility-Collaborator cards). Они были введены Кентом Беком (Kent
Beck) и Уордом Каннингхемом (Ward Cunningham), которые внесли значительный
вклад в повышение абстрактности мышления разработчиков объектно-ориентиро¬
ванных систем и уделили большое внимание распределению обязанностей и взаимо¬
действию объектов.Карты CRC — это индексные карты (по одной на каждый класс), на которых крат¬
ко описаны обязанности классов и перечислены объекты, взаимодействующие с дан¬
ным классом при выполнении этих обязанностей. Обычно они разрабатываются в
процессе небольших групповых семинаров, на которых проигрываются сценарии
“что — если”. Примеры карт CRC показаны на рис. 14.2 и 14.3.14.6. Другие методы проектирования
объектов: карты CRC11м<£мса.Рис. 14.2. Шаблон карты CRC
Глава 14. Переход к объектному проектированиюa** iW »w4OA иумМь |M*W.^r<u*;»vv^Тц|>д.iЙЛк fry»**.1^АЦS^CuJruKV*“f?>*Ctto р^ммЦ\|м^)3*ky/*1u+Ц*Д1*WiiH-b 14 \)hwSРис. 14.3. Примеры карт CRC, призванные отобразить типичный
уровень детализации, а не конкретное содержание
Диаграммы взаимодействия
на UMLКошки умнее собак. Вы не сможете заставить восемь кошек тянуть сани по снегу.Джефф Валдез (Jeff Valdez)Основная задача■ Ознакомиться с системой обозначений языка UML для построения
диаграмм взаимодействия — последовательностей и кооперации.ВведениеВ состав языка UML входят обозначения для диаграмм взаимодействий (interaction
diagrams), используемых для динамического моделирования объектов (dynamic model¬
ing). Они иллюстрируют способ взаимодействия объектов с помощью сообщений. В
этой главе вводится система обозначений, а в последующих главах внимание читате¬
ля будет сфокусировано на более важных вопросах — ключевых принципах объектно-
ориентированного проектирования.В следующих главах диаграммы взаимодействия применяются для иллюстрации
принципов объектного проектирования. Но сначала рассмотрим несколько приме¬
ров динамических диаграмм.Что дальше? После перехода к объектно-ориентированному проектированию в данной главе
приведен справочный материал по обозначениям диаграмм взаимодействия,
которые предназначены для динамического объектно-ориентированного
проектирования. В следующей главе приведены аналогичные сведения о диаграммах
классов, применяемых в процессе статического объектно-ориентированного
проектирования/ \ПроектированиеИтеративный
Логическая переход от анализа
архитектура требованийДиаграммы Диаграммы объектоввзаимодействия классов с помощьюUML UML шаблоновк проектированию GRASP о • о о
252 Часть III. Первая итерация фазы развития — основы15.1. Диаграммы последовательностей
и коммуникацииТермин диаграмма взаимодействия (interaction diagram) используется в качестве об¬
щего названия для двух следующих конкретных типов диаграмм.■ Диаграммы последовательностей (sequence diagram)■ Диаграммы коммуникации (communication diagram)Оба типа диаграмм могут использоваться для иллюстрации схожих взаимодей¬
ствий.Существует еще один вид динамических диаграмм — обзорная диаграмма взаимодей¬
ствия (interaction overview diagram), обеспечивающая общую картину взаимодействия
объектов в терминах логики приложения и последовательности процессов. Этот вид
диаграмм появился только в UML 2.0, поэтому еще не ясно, будет ли он действитель¬
но полезным.Для построения диаграмм последовательностей существует более богатый набор
обозначений, однако диаграммы коммуникации тоже находят свое применение, осо¬
бенно в рамках гибкого моделирования. Чтобы подчеркнуть свободу разработчиков
при выборе артефактов проектирования, в книге будут использованы оба типа диа¬
грамм.Диаграммы последовательностей (sequence diagram) иллюстрируют взаимодействие
в форме, показанной на рис. 15.1. Здесь объекты располагаются слева направо.: АшуВ : ВТdoOne• todoTwo11Ь 1doThreei• ^ iп-Рис. 15.1. Диаграмма последовательностиКак эта информация отображается в коде?1 Скорее всего, класс А содержит ме¬
тод doOne () и атрибут типа В. класс В, в свою очередь, содержит методы doTwo () и
doThree (). Описание класса А может иметь примерно следующий вид.public class А
{private В шуВ =new В() ;1 Правила генерации кода на основе диаграмм зависят от объектно-ориентированного язы¬
ка программирования
Глава 15. Диаграммы взаимодействия на UML 253public void doOne (){myB.doTwo ();
myB.doThree ();}// ...}Диаграммы коммуникации (communication diagram) иллюстрируют взаимодействие
объектов в формате графа или сети. При этом объекты могут размещаться в любом
месте диаграммы, как показано на рис. 15.2.Рис. 15.2. Диаграмма коммуникацииПреимущества и недостатки диаграмм
последовательностей и коммуникацииОба типа диаграмм имеют свои преимущества и недостатки, поэтому нельзя одно¬
значно отдать предпочтение одному из видов диаграмм. При использовании CASE-
средств разработки многие предпочитают строить диаграммы последовательностей
из-за более богатого набора обозначений, применяемых для этих диаграмм.Диаграммы последовательностей имеют некоторые преимущества по сравнению
с диаграммами коммуникации. В первую очередь следует отметить, что система обо¬
значений для диаграмм последовательностей более разнообразна. Поэтому средства
автоматического построения диаграмм последовательностей обеспечивают большую
выразительность этого вида диаграмм. На подобных диаграммах проще отслеживать
последовательность вызовов — нужно просто читать диаграмму сверху вниз. На диа¬
граммах коммуникации необходимо обращать внимание на цифровые обозначения, на¬
пример 1: или 2:. Таким образом, диаграммы последовательностей прекрасно подхо¬
дят для документирования или обратного проектирования на основе исходного кода.С другой стороны, диаграммы коммуникации имеют свои преимущества при ис¬
пользовании доски больших размеров (в контексте гибкого подхода к моделирова¬
нию), поскольку новые объекты к этим диаграммам можно добавлять как по гори¬
зонтали, так и по вертикали. Такие диаграммы легче модифицировать — для этого
нужно только стереть ненужный элемент и добавить новый. При использовании диа¬
грамм последовательностей новые объекты добавляются справа, что не всегда мож¬
но сделать в условиях ограниченной ширины страницы. При изображении диаграмм
последовательностей на большой доске гораздо быстрее заполняется свободное про¬
странство.
254 Часть III. Первая итерация фазы развития — основыДиаграммы коммуникации обладают преимуществами при изображении на листах
ограниченной ширины, поскольку допускают добавление новых объектов по вертика¬
ли. Поэтому на небольшом пространстве можно поместить гораздо больше объектов.Тип диаграммыПреимуществаНедостаткиПоследовательностейЯсно отображает последовательностьРасширяется вправо при добавле¬и временной порядок сообщений.нии новых объектов; занимает мно¬Богатый набор обозначенийго места по горизонталиКоммуникацииЭкономия пространства — возмож¬Сложнее отследить последователь¬ность добавления объектов в двухность сообщений. Более беднаянаправлениях.система обозначенийПример диаграммы последовательностей: makePaymentПоказанную на рис. 15.3 диаграмму последовательностей нужно интерпретировать
следующим образом.1. Сообщение makePayment передается экземпляру объекта Register. Отправи¬
тель сообщения не определен.2. Объект Register передает сообщение makePayment экземпляру объекта Sale.3. Объект Sale создает экземпляр объекта Payment.Рис. 15.3. Диаграмма посмдователъностейКак в свете диаграммы на рис. 15.3 должен выглядеть код класса Sale и его метода
makePayment?public class Sale
{private Payment payment;public void makePayment(Money cashTendered){payment = new Payment(cashTendered);//}//}
Глава 15. Диаграммы взаимодействия на UML 255Пример диаграммы коммуникации: makePaymentНа рис. 15.4 в виде диаграммы коммуникации изображена информация, представ¬
ленная на приведенной выше диаграмме последовательностей.Рис. 15.4. Диаграмма коммуникации15.2. Проблема для новичковСтандартной проблемой новичков в UML является недопонимание важности соз¬
дания диаграмм взаимодействий. Они считают наиболее важным видом моделей диа¬
граммы классов. Но это совсем не так.Хотя статические диаграммы тоже играют свою роль, динамические диаграммы
взаимодействия являются чрезвычайно важными.СоветЗначительную часть усилий необходимо затратить на построение динамических
диаграмм взаимодействия, а не только на создание статической модели в рамках
диаграммы классов.Дело в том, что на таких диаграммах отображается процесс передачи сообщений
между объектами, требующий более детальной проработки. В терминах объектно-
ориентированного проектирования, в данном случае “путь прокладывает резинка”.15.3. Основные обозначения UML для
диаграмм взаимодействияОтображение участников взаимодействияПрямоугольники, показанные в предыдущих примерах диаграмм, на языке UML
называются изображениями участников (participant) взаимодействия — взаимосвязан¬
ных элементов, отображаемых на структурных моделях, например диаграммах клас¬
сов. Строго говоря, такие прямоугольники используются для иллюстрации экземпля¬
ров класса. Поэтому в данной книге будут встречаться фразы вида “прямоугольник,
256 Часть III. Первая итерация фазы развития — основыпредставляющий экземпляр класса Sale”. Типичные примеры участников взаимодей¬
ствия показаны на рис. 15.5.Неименованный
экземпляр класса saleЪИменованныйэкземплярКласс Font или, более Ъ,
точно, экземпляр класса
class, экземпляр метакласса © —0 в :Salesi : Sale<<metaclass>>FontЭкземпляр шпараметризованного класса
ArrayList, предназначенного
для хранения объектов SaleОдин экземпляр класса Ь
Sale, выбранный из набора
объектов sales коллекции
ArrayList<Sale>List — это интерфейс.В UML1 .х использовать интерфейс
подобным образом было нельзя,
однако в UML 2 такая конструкция
вполне допустима. Точно так же
можно использовать и абстрактные
классы в sales :
ArrayList<Sale> ^ Psales[i] : Salex : ListСвязанныепримерыЬРис. 15.5. Обозначения участников взаимодействияСинтаксис для отображения сообщенийДиаграммы взаимодействия отражают сообщения, передаваемые от одних объек¬
тов другим. В языке UML существует стандартный синтаксис для обозначения пере¬
дачи сообщений.2получатель = сообщение (параметр : типПараметра) : типПолучателяЕсли параметры отсутствуют, скобки опускаются.Информация о типах, например, может исключаться в силу своей очевидности
или незначительности.initialize(code)initialized = getProductDescription(id)d = getProductDescription(id:ItemID)d = getProductDescription(id:ItemID) : ProductDescription2 Допускается и альтернативный синтаксис, например на C# или Java. Его поддерживают
средства автоматизированного проектирования.
Глава 15. Диаграммы взаимодействия на UML 257Объекты-синглетоныСреди шаблонов объектно-ориентированного проектирования особенно попу¬
лярным является шаблон Singleton (Единственный экземпляр). Детальнее он будет
описан позже, а пока ограничимся единственным замечанием о том, что в рамках
этого шаблона создается класс, для которого инстанцируется единственный экзем¬
пляр — объект-синглетон. На диаграммах взаимодействия (последовательностей или
коммуникации) такой объект помечается цифрой 1 в правом верхнем углу прямоу¬
гольника (рис. 15.6). Это означает, что для обеспечения видимости объекта исполь¬
зуется шаблон Singleton. Пока смысл этого утверждения не совсем ясен, но он станет
понятен позже, при изучении главы 26.Рис. 15.6. Обозначение синглетонов на диаграммах взаимодействия15.4. Основные обозначения диаграммы
последовательностейУчастники взаимодействия и линии жизниВ отличие от диаграмм коммуникации, на диаграммах последовательностей каж¬
дый прямоугольник участника взаимодействия связан с расположенной под ним вер¬
тикальной линией — линией жизни (lifeline). Практически во всех примерах диаграмм
UML эта линия изображается пунктиром (в силу влияния UML 1). Однако согласно
спецификации UML 2 эта линия может быть либо сплошной, либо пунктирной.СообщенияСообщения между объектами изображаются в виде соединяющих вертикальные
линии жизни линий с заштрихованными стрелками на конце*, над которыми указыва¬
ется имя сообщения (рис. 15.7). Порядок передачи сообщений определяется их рас¬
положением сверху вниз.Первое сообщение на рис. 15.7 называется начальным (found message). Оно начи¬
нается с заштрихованного кружочка, символизирующего неизвестного, неопределен¬
ного или случайного отправителя. Однако по согласованию в рамках команды раз¬
работчиков это обозначение можно игнорировать и использовать обычную линию
сообщения без кружочка.43 Линии с открытыми стрелками на диаграммах взаимодействия означают асинхронные со¬
общения.4 На многих примерах диаграмм в данной книге обозначение начального сообщения опу¬
скается.9 Зак. 3357
258 Часть III. Первая итерация фазы развития — основы:Register„ОdoX I
• ►Г'Начальное сообщение,
отправитель которого
не заданБлок выполнения I
отображает фокус
управленияdoA:Sale
 1 doBоdoCTJIIFdoDТипичное синхронное Шсообщение, представленное
линией с заштрихованной стрелкойРис. 15.7. Сообщения и фокус управления с блоком выполненияФокус управления и блоки выполненияКак видно из рис. 15.7, на диаграммах последовательностей можно отображать
фокус управления с использованием блока выполнения (execution specification bar), ко¬
торый в UML 1 назывался блоком активации (activation bar). Блоки выполнения указы¬
вать необязательно. Обычно их используют (зачастую автоматически) при построе¬
нии диаграмм с помощью специальных CASE-средств. При моделировании вручную
их, как правило, опускают.Возвращаемые значенияСуществует два способа отобразить возврат значения при передаче сообщения.1. С использованием специальной надписи над линией сообщения видавозвращаемаяПеременная = сообщение (параметр).2. С использованием возвратной линии сообщения, исходящей из блока активации.На практике применяются оба обозначения. При построении диаграмм вручную
автор предпочитает первый подход. Возвратные линии тоже иногда сопровождают
произвольными обозначениями возвращаемых значений (рис. 15.8).:RegisterТ:SaleТdoXgetDate* »aDatewiРис. 15.8. Два способа отображения возврата значения
Глава 15. Диаграммы взаимодействия на UML 259Сообщения, передаваемые самому объектуПередача сообщения объектом самому себе отображается с использованием вло¬
женных активационных блоков (рис. 15.9).:Register ГIIРис. 15.9. Сообщения, передаваемые самому объектуСоздание экземпляров объектовОбозначения, иллюстрирующие создание экземпляра, показаны на рис. 15.10.
Обратите внимание на пунктирную линию сообщения.5 На конце линии использует¬
ся заштрихованная стрелка, если линия символизирует обычное синхронное сообще¬
ние (например, вызов конструктора в Java). Открытая стрелка указывает на несин¬
хронное сообщение. Сообщение о создании объекта не обязательно должно иметь
имя create, но это уже сложившаяся традиция.Сообщение create, обычно изображаемое пунктирной линией с заштрихованной
стрелкой на конце, в Java или C# интерпретируется как оператор new с вызовом кон¬
структора.:Register~Т: SalemakePayment(cashTendered)Обратите внимание, Ьц
что вновь созданные
объекты располагаются
на соответствующем уровнеcreate(cashTendered)authorize:PaymentTI IPuc. 15.10. Создание экземпляра объекта и линии жизни5 Автор не видит необходимости в использовании именно пунктирной линии, однако тако¬
вы требования спецификации UML. Тем не менее, многие специалисты по-прежнему использу¬
ют в этих случаях сплошную линию.
260 Часть III. Первая итерация фазы развития — основыЛинии жизни объектов и уничтожение объектовИногда желательно отобразить на диаграмме факт уничтожения объекта (напри¬
мер, в языке C++ отсутствует механизм сборки мусора). Кроме того, зачастую необхо¬
димо явно указать, что объект больше не будет использоваться (например, отразить
факт закрытия соединения с базой данных). Этот факт можно отобразить в терминах
UML с помощью специального символа на линии жизни объекта (рис. 15.11).: Salecreate(cashTendered)«destroy»:Payment"Г-►XО"'Сообщение со стереотипом bk,
«destroy» вместе
с большим символом X
и укороченной линией жизни
указывает на явное уничтожение
объектаРис. 15.11. Уничтожение объектаФреймы на диаграммах последовательностей UMLДля поддержки условных операторов или циклов (а также многих других кон¬
струкций) в UML используются фреймы (frame).6 Фреймы — это области или фрагмен¬
ты диаграмм, содержащие оператор или метку (например, loop) и условное выраже¬
ние.6 Пример обозначения фреймов показан на рис. 15.12.: А: ВmakeNewSaleФрейм UML В
loop с условным
булевым
выражениемloopj [для других товаров]! enterltem(itemID, quantity)I Описание, общая суммаК iendSaleРис. 15.12. Пример фрейма UML6 Их иногда называют фреймами диаграмм, или фреймами взаимодействия.
Глава 15. Диаграммы взаимодействия на UML 261В следующей таблице приведены основные операторы, изображаемые с помощью
фреймов.отalt Альтернативный фрагмент для представления взаимоисключающих условийloop фрагмент цикла, выполняемый в случае истинности условного выражения. Многократное
выполнение оператора цикла (п раз) записывается в виде loop (п). В настоящее время
обсуждается спецификация для определения цикла for, например: ioop(i,i,lO)opt Необязательный фрагмент, который выполняется в случае истинности условного выраженияpar фрагменты, выполняемые параллельноregion Критическая область, в рамках которой может выполняться только один потокЦиклыФреймовое представление циклов показано на рис. 15.12.Условные сообщенияДля одного или нескольких сообщений создается фрейм opt. Обратите внима¬
ние, что условное выражение размещается поверх соответствующей линии жизни.
Условное сообщение показано на рис. 15.13.Рис. 15.13. Условное сообщениеУсловные сообщения в стиле UML1 .хОбозначение единственного условного сообщения в UML 2.x является достаточно
“тяжеловесным”, поскольку требует создания отдельного фрейма opt для одного сооб¬
щения (см. рис. 15.13). Устаревшее обозначение единственного условного сообщения
в UML 1.x уже не действует, но является настолько удобным и простым, что, веро¬
ятно, будет популярным еще не один год (особенно при построении диаграмм вруч¬
ную). Пример устаревшего обозначения условного сообщения показан на рис. 15.14.Обозначения в стиле UML 1.x следует использовать только для простых оди¬
ночных сообщений при построении диаграмм вручную.
262 Часть III. Первая итерация фазы развития — основыРис. 15.14. Условное сообщение в стиле UML 1.xПредставление взаимоисключающих условных сообщенийДля этого случая фрейм alt помещается вокруг взаимоисключающих альтернатив,
как показано на рис. 15.15.: А: В: СdoX->177 1 х < 10 ]Ialt[ else ]calculatecalculateРис. 15.15. Взаимоисключающие условные сообщенияИтерационный процесс для коллекций объектовЗачастую сообщение передается каждому элементу коллекции (например, списку
или карте). Для этого можно использовать некий вид объекта-итератора, например, в
Java реализацию java.util.Iterator или итератор из стандартной библиотеки C++.
Однако на диаграмме последовательности этот низкоуровневый механизм не отобра¬
жается в целях обеспечения нужного уровня абстракции.На момент написания этой книги в спецификации UML не содержится официаль¬
ного обозначения для этого случая. На рис. 15.16 и 15.17 показаны два возможных
обозначения.Обратите внимание на выражение селектора (selector) lineltems [i] на рис. 15.16.
Оно используется для выделения одного объекта из группы. Участники взаимодей¬
ствия должны представлять отдельные объекты, а не коллекцию.
Глава 15. Диаграммы взаимодействия на UML 263lineltems[i] :SalesLineltem■а-В блоке операции могут содержаться
операторы на любом языке (в данном
случае инкрементирование значения i).Блок операции размещается над линией
жизни, к которой он относитсяОдин экземпляр ^из коллекции объектовSalesLineltem.Выражение line items [i]
иллюстрирует выбор одного
элемента из коллекции
объектов SalesLineltem.
Значение i в этом выражении
совпадает с аналогичным
значением в условном
выражении фрейма loopРис. 15.16. Явное обозначение итерационного процесса над коллекциейРис. 15.17. Неявное обозначение итерационного процесса над коллекциейНапример, следующий код Java представляет собой возможную реализацию яв¬
ного использования инкрементальной переменной i на рис. 15.16 с использованием
оператора for (в C# существует такая же возможность).public class Sale
{private List<SalesLineItem> lineltems =new ArrayList<SalesLineItem>();public Money getTotal();{Money total = new Money();Money subtotal = null;for(SalesLineltem lineltem : Lineltems){subtotal = lineltem.getSubtotal();
264 Насть III. Первая итерация фазы развития — основыtotal.add(subtotal);}return total;}// ...}Еще один вариант обозначений показан на рис. 15.17. Здесь содержится та же ин¬
формация за исключением некоторых деталей. Можно договориться использовать
этот простой стиль для представления итерационного процесса над всеми элемента¬
ми коллекции.7Вложенные фреймыФреймы могут быть вложенными (рис. 15.18).: Foo:Вагopt J[цвет = красный]loop(n)JcalculateРис. 15.18. Вложенные фреймыКак связать диаграммы взаимодействия?Рис. 15.19 отвечает на этот вопрос лучше, чем любые слова. Вхождение взаимодей¬
ствия (interaction occurrence) — это ссылка на взаимодействие в рамках другого вза¬
имодействия. Его также называют использованием взаимодействия (interaction use). Это
обозначение применяют для упрощения диаграммы и вынесения ее фрагмента на
другую диаграмму либо для повторного использования вхождений. Оно особенно
полезно при использовании автоматизированных средств построения диаграмм, по¬
скольку позволяет связывать различные диаграммы.Для обозначения вхождений используется два фрейма.■ В первый помещается общая диаграмма последовательности8. Этот фрейм по¬
мечается дескриптором sd с указанием имени, например: AuthenticateUser.■ Второй фрейм ref, называемый ссылкой (reference), указывает на другую име¬
нованную диаграмму последовательностей. Она и является вхождением взаимо¬
действия.7 Именно этот стиль будет использоваться далее в данной книге.8 Вхождение взаимодействий и фреймы ref можно использовать и на диаграммах комму¬
никации.
Глава 15. Диаграммы взаимодействия на UML 265Обзорная диаграмма взаимодействия (interaction overview diagram) также содержит
набор ссылочных фреймов (вхождений взаимодействия). Такие диаграммы связыва¬
ют ссылки в более крупную логическую структуру.Любую диаграмму взаимодействия можно поместить во фрейм sd и присво¬
ить ей имя. Это делается для обеспечения возможности ссылки на эту диаграмму
с помощью фрейма ref.sd AuthenticateUser7: Сauthenticate(id)
 ►!doAdoBdoMlauthenticate(id)AuthenticateUserdoM2■>!Сообщения для классов с использованием
статических методовОбращение к классу или вызов статического метода отображается на диаграмме
последовательности путем представления объекта-получателя в виде класса, а точнее
экземпляра метакласса (metaclass) (рис. 15.20).Что имеется в виду? Например, в Java и Smalltalk все классы концептуально и
литерально являются экземплярами класса Class, а в .NET — экземплярами класса
Туре. Эти родовые классы являются метаклассами, экземпляры которых сами явля¬
ются классами. Каждый конкретный класс, например класс Calendar, является эк¬
земпляром класса Class, т.е. экземпляром метакласса.
266 Часть III. Первая итерация фазы развития — основыСообщение классу или
вызов статического метода: Foo«metacla88>>CalendardoXlocales = getAvailableLocalesОРис. 15.20. Обращение к классу с помощью вызова статического
метода. Объект класса выступает в роли экземпляра метаклассаКод, реализующий эту диаграмму, может выглядеть следующим образом.public class Foo
{public void doX(){/ / вызов статического метода класса Calendar
Locale[] locales = Calendar.getAvailableLocales();//}//}Полиморфные сообщения и переключателиПолиморфизм — основное свойство объектно-ориентированного подхода. Как
оно отображается на диаграмме последовательности? Это типичный вопрос. Один
из способов состоит в использовании нескольких диаграмм последовательностей.
На одной изображаются полиморфные сообщения абстрактному суперклассу или
объекту интерфейса, а затем каждый конкретный случай полиморфизма отобража¬
ется на отдельной диаграмме, начинающейся с начального полиморфного сообщения
(рис. 15.21).Асинхронные и синхронные вызовыАсинхронные сообщения (asynchronous message) не требуют отклика и не блокируют
выполнения программы. Они используются в многопоточных средах, например, Java
или .NET, где можно создавать или инициировать новые потоки (thread) выполне¬
ния. Например, в Java сообщение Thread, start или Runnable.run (вызываемое из
Thread, start) можно рассматривать как асинхронное и использовать для инициали¬
зации выполнения нового потока.В UML асинхронные вызовы обозначаются линиями сообщений с открыты¬
ми стрелками, а обычные синхронные — линиями с заштрихованными стрелками
(рис. 15.22).
Глава 15. Диаграммы взаимодействия на UML 267СоветРазличия в стрелках являются несущественными. При построении диаграмм
UML вручную для простоты на диаграммах последовательностей синхронные
сообщения помечают обычными открытыми стрелками. Поэтому при изучении
диаграмм взаимодействия UML не следует обращать внимания на стрелки.Объект Clock на рис. 15.22 называется активным объектом (active object). Каждый
его экземпляр используется в отдельном потоке выполнения. В UML это можно изо¬
бразить с помощью двойной вертикальной черты в левой и правой частях прямо¬
угольника объекта. Такое же обозначение используется для активного класса (active
class), экземпляры которого являются активными объектами.Payment — это абстрактный
суперкласс с конкретными
подклассами, в которых
реализована полиморфная
операция authorizeCreditPaymentauthorize()Payment {abstract}
authorize() {abstract}DebitPaymentauthorize()TII:DebitPayment:Foo1authorize ,! doAlwI doBb.1iWОтдельные диаграммы для каждой
конкретной реализации полиморфной операцииРис. 15.21. Полиморфное сообщение на диаграмме последовательности
268 Часть III. Первая итерация фазы развития — основыВ языке UML для обозначения Ьасинхронных вызовов используется
открытая стрелка, а для синхронных —
заштрихованная.Например, в Java асинхронный вызов
можно осуществить следующим образом://Класс Clock реализует
//интерфейс Runnable
Thread t = new Thread new ClockO);
t.start();Асинхронный вызов метода start всегда
приводит к вызову метода run объекта,
реализующего интерфейс Runnable
(Clock).Для упрощения диаграммы UML
объект Thread и метод start на ней
не показываются (они являются
стандартными). Вместо этого иллюстри¬
руются важные детали создания объекта
clock и асинхронное сообщение runРис. 15.22. Асинхронные вызовы и активные объектыНиже приводится возможная реализация диаграммы из рис. 15.22 на языке Java.
Обратите внимание на объект класса Thread, обеспечивающий механизм асинхрон¬
ных вызовов в Java.public class ClockStarter
{public void startClock(){Thread t = new Thread(new Clock());t.start (); // асинхронный вызов метода run () класса Clock
System.runFinalization(); // последующее сообщение}// ...}// если объекты Java будут использоваться в новых потоках,// они должны реализовывать интерфейс Runnablepublic class Clock implements Runnable
{public void run(){while(true) // бесконечный цикл для отдельного потока
{// ...}}// ...}
Глава 15. Диаграммы взаимодействия на UML 26915.5. Основные обозначения
диаграммы коммуникацииОтображение связейСвязь (link) является соединением между двумя экземплярами классов, определя¬
ющим некоторую форму перемещения и видимости между ними (рис. 15.23). Более
строго можно сказать, что связь является экземпляром ассоциации. Например, име¬
ется связь, или маршрут перемещения, от объекта Register к объекту Sale, в соот¬
ветствии с которым могут передаваться сообщения, такие как makePayment.1 :makePayment (cashTendered) ►Рис. 15.23. Линии связейЗамечаниеОбратите внимание, что по одной и той же линии связи могут передаваться не¬
сколько сообщений в обоих направлениях. Для каждого сообщения не нужно
строить отдельную линию связи. Все сообщения передаются по одной той же ли¬
нии, которую можно рассматривать как трассу с двухсторонним движением.СообщенияПередаваемые между объектами сообщения представляются в виде имен этих
сообщений над линиями связей, помеченных стрелками. Над одной линией связи
может быть указано любое количество сообщений (рис. 15.24). Для отображения по¬
рядка следования сообщений в текущем потоке управления рядом с сообщением при¬
водится порядковый номер.РВсе сообщения передаются по одной и той же связиРис. 15.24. СообщенияСоветНачальные сообщения нумеровать не следует. Формально это можно сделать, но
отсутствие номера упрощает общую нумерацию сообщений.
270 Часть III. Первая итерация фазы развития — основыСообщения, передаваемые самому объектуСообщение может передаваться объектом самому себе (рис. 15.25).
Такой случай отображается с помощью связи объекта с самим со¬
бой, когда сообщения передаются в направлении этой связи.Создание экземпляров объектовmsgl:Register1: clear JРис. 15.25.
Сообщения, пере¬
даваемые само¬
му объектуДля создания экземпляра объекта можно использовать любые со¬
общения. Однако в языке UML принято использовать для этой цели
сообщение create (создать) или new (рис. 15.26). При использова¬
нии другого имени (возможно, менее очевидного) сообщение следу¬
ет снабдить специальным свойством, получившим название стерео¬
типа UML (stereotype), в частности «create». Сообщение create
может иметь параметры, задающие начальные значения свойств
создаваемого экземпляра. Такая форма записи может означать, например, вызов кон¬
структора с параметрами на языке Java. Более того, чтобы подчеркнуть факт созда¬
ния экземпляра, новому экземпляру объекта можно дополнительно присвоить тегиро¬
ванное значение (tagged value) {новый}. Тегированное значение — это гибкий механизм
расширения UML, позволяющий добавлять семантически значимую информацию к
элементам диаграмм.Три способа представления I
операции создания объекта
на диаграмме коммуникацииСообщение о создании объекта с дополнительными параметрами
инициализации. Обычно оно интерпретируется как вызовРис. 15.26. Создание экземпляра объектаПорядок передачи сообщенийПорядок передачи сообщений иллюстрируется с помощью порядковых номеров (se¬
quence number) (рис. 15.27). При этом используется следующая схема нумерации.
Глава 15. Диаграммы взаимодействия на UML 2711. Первое сообщение не нумеруется. Таким образом, сообщение msgl () является
ненумерованным.92. Порядок и вложенность последующих сообщений отображается в соответствии
с принятой схемой нумерации. При ее использовании к вложенным сообщени¬
ям добавляется номер. Вложенность означает, что к номеру исходящего сооб¬
щения добавляется номер входящего сообщения.Рис. 15.27. Нумерация последовательности сообщений
На рис. 15.28 показан более сложный случай.ПервоеВтороесообщение 1сообщение 1Третье
сообщениеЪРис. 15.28. Сложная нумерация последовательности сообщений9 На самом деле можно использовать номер начального сообщения, однако это усложняет
последующую нумерацию сообщений и требует создания лишнего уровня вложенности номеров.
272 Часть III. Первая итерация фазы развития — основыУсловные сообщенияУсловное сообщение (рис. 15.29) изображается с помощью его номера, за кото¬
рым в квадратных скобках указывается условное выражение, аналогичное условию
цикла. Сообщение передается только в том случае, когда оператором возвращается
значение true.Условное сообщение
с проверкой условияРис. 15.29. Условное сообщениеВзаимоисключающие условные маршрутыПриведенный на рис. 15.30 пример иллюстрирует порядковые номера сообщений
при использовании взаимоисключающих условных маршрутов.В этом случае требуется модифицировать схему нумерации, воспользовавшись
символом условного маршрута. В соответствии с принятым соглашением первым
таким символом является буква а. Фрагмент диаграммы, приведенной на рис. 15.30,
означает, что после передачи сообщения msgl() будет передано либо сообщение 1а,
либо сообщение lb. Наличие номера 1 означает, что оба сообщения относятся к пер¬
вому внутреннему сообщению.Обратите внимание, что последующие вложенные сообщения по-прежнему нуме¬
руются согласно соответствующим внешним сообщениям. Таким образом, lb.l явля¬
ется вложенным сообщением сообщения lb.Рис. 15.30. Взаимоисключающие сообщения
Глава 15. Диаграммы взаимодействия на UML 273Итерационный процесс или циклОбозначения для итерационного процесса показаны на рис. 15.31. Итерационный
процесс можно отобразить, указав за порядковым номером сообщения символ *.Цикл изображается с помощью символа
звездочки (*) и необязательного оператора
повторения, следующих за порядковым номеромРис. 15.31. Итерационный процессИтерационный процесс для коллекции объектовЦикл представляет собой единый итерационный процесс для всех элементов кол¬
лекции, например списка или карты. На диаграммах коммуникации итерационные
процессы над элементами коллекции обычно изображаются с помощью обозначе¬
ний, показанных на рис. 15.32. Официального соглашения UML для данного случая
не существует.t = getTotal: Sale1 * [i=l..n]: st = getSubtotallineitems[i]:jOSalesLineltemоЭтот составной оператор В
иллюстрирует выполнение
цикла над каждым элементом
коллекции line ItemsОдин экземпляр из коллекции объектов яSalesLineltem.Выражение lineitems[i] иллюстрирует
выбор одного элемента из коллекции
объектов SalesLineltem. Значение i в
этом выражении совпадает с аналогичным
значением в передаваемом сообщенииt = getTotal: Sale1 *: st = getSubtotallineitems[i]:jOSalesLineltemМенее точно, однако приемлемо для •
представления итеративной обработки
коллекции объектовРис. 15.32. Итерационный процесс над элементами коллекции
274 Часть III. Первая итерация фазы развития — основыСообщения, передаваемые классу,
и вызовы статических методовЧтобы понять рис. 15.33, обратитесь к описанию метаклассов при обсуждении
диаграмм последовательностей выше в данной главе.Рис. 15.33. Сообщения, передаваемые объекту класса (вызов статических методов)Полиморфные сообщенияПредставление полиморфных сообщений на диаграммах последовательностей по¬
казано выше на рис. 15.21. Как и для диаграмм последовательностей, полиморфизм
отображается на диаграммах коммуникации с помощью объединения нескольких диа¬
грамм (рис. 15.34).ПолиморфноеСтоп: для данногосообщения больше ничегосообщениепоказывать не нужноdoX:RegisterО Оauthorize:Payment {abstract} ОАбстрактный I
суперкласс
в роли объектаГОтдельные диаграммы для каждой ^конкретной реализации полиморфной операцииРис. 15.34. Моделирование полиморфизма на диаграммах коммуникации
Глава 15. Диаграммы взаимодействия на UML 275Синхронные и асинхронные вызовыКак и на диаграммах последовательностей, асинхронные вызовы помечаются от¬
крытыми стрелками, а синхронные — заштрихованными (рис. 15.35).Рис. 15.35. Асинхронный вызов на диаграмме коммуникации
Диаграммы классов UMLИтеративность присуща деятельности человека,
а рекурсивность — деятельности высших существ.Автор неизвестенОсновная задача■ Предоставить справочный материал о часто используемых обозначе¬
ниях диаграмм классов UML.ВведениеВ состав языка UML входят условные обозначения диаграмм классов (class diagram),
которые можно использовать для отображения классов, интерфейсов, а также ассо¬
циаций между ними. Диаграммы классов предназначены для статического моделирова¬
ния объектов (static object modeling). Ранее эта система обозначений уже применялась
в концептуальном ракурсе (conceptual perspective) при моделировании предметной об¬
ласти. В данной главе подводится итог по применению большей части системы обо¬
значений, независимо от конкретного ракурса ее использования (концептуального
или прикладного). Как и в предыдущей главе, посвященной диаграммам взаимодей¬
ствия, в данной главе содержится справочный материал.В последующих главах основное внимание будет уделено рассмотрению более важ¬
ного вопроса: каковы основные принципы объектно-ориентированного проектиро¬
вания? В этих главах с использованием диаграмм взаимодействия и диаграмм классов
UML подробно рассматривается процесс проектирования объектов. Поэтому, перед
тем как перейти к изучению последующих глав, имеет смысл сначала хотя бы бегло
просмотреть данную главу.
278 Часть III. Первая итерация фазы развития — основыЧто дальше?После ознакомления с диаграммами взаимодействия для динамического объектно-
ориентированного проектирования в данной главе рассматриваются диаграммы
классов и вопросы статического объектно-ориентированного проектирования.В следующей главе вводятся ключевые принципы ООП, применение которых
иллюстрируется на конкретных примерах с использованием UML\Итеративныйпереход Диаграммыот анализа взаимодействия
требований UMLк проектированиюо о ДиаграммыклассовUMLПроектированиеобъектов Примерыс помощью проектирования
шаблонов объектовGRASP о о16.1. Применение UML: система обозначений
для диаграммы классовНаиболее часто используемые обозначения диаграмм классов UML представлены
на рис. 16.1.На рис. 16.1 большинство элементов является необязательными (например, об¬
ласть видимости (visibility) +/-, параметры методов и часть разделов в обозначении
классов). Решение об использовании или сокрытии конкретных элементов на диа¬
грамме классов принимается специалистом по моделированию в зависимости от кон¬
текста и реальных нужд.СоветСоветы и рекомендации по объектно-ориентированному анализу, моделированию
и проектированию, связанные с применением различных элементов диаграмм
классов UML, распределены по нескольким главам, в которых рассматриваются
учебные примеры. Ссылки на основные принципы ООА/П можно найти в пред¬
метном указателе.16.2. Определение: диаграмма
классов проектированияКак уже упоминалось, одну и ту же диаграмму UML можно использовать в несколь¬
ких ракурсах (рис. 16.2). В концептуальном ракурсе диаграммы классов можно приме¬
нять для визуализации модели предметной области. В дальнейшем окажется полез¬
ным также термин для однозначного описания ситуации, когда диаграммы классов
используются в ракурсе проектирования (design perspective) или программирования
(software perspective). В качестве такого термина удобно воспользоваться общеприня¬
тым термином диаграммы классов проектирования (design class diagram — DCD). Именно
он и будет использоваться в последующих главах. В рамках унифицированного про¬
цесса набор всех диаграмм классов является частью модели проектирования (design
model). Другими составными частями этой модели являются диаграммы взаимодей¬
ствия (interaction diagram) и диаграммы пакетов (package diagram).
Глава 16. Диаграммы классов UML 279Три стандартных •
раздела в обозначении
класса1. Имя классификатора2. Атрибуты3. ОперацииИнтерфейс и
с ключевым
словом«interface»RunnableSuperclassFooилиSuperClassFoo {abstract}- атрибутКлассаИлиСтатическийАтрибут: Int
+ открытыйАтрибут: String- закрытыйАтрибут
закрытыйПоПредположениюАтрибут
инициализированныйАтрибут: Bool=true
коллекцияОбъектов: VeggieBurger [*]
атрибутСВозможнымНулевымЗначением:String [0..1]
конечныйАтрибут: Int=5 {readonly}/произ водныйАтрибут+ методКлассаИлиСтатическийМетод()+ открытыйМетод()
открытыйПоПредположениюМетод()- закрытыйМетод()# защищенныйМетод()~ видимыйМетодПакета()«constructor» SuperclassFoo (Long)
методСПараметрами(parml: String, parm2:Float)
методСВозвращаемымЗначением(): VeggieBurger
методГенерирущийИсключение(){exception IOException}
абстрактныйМетод ()абстрактныйМетод2(){abstract}//альтернативное обозначение
конечныйМетод(){leaf}//не перекрывается в подклассах
синхронизованныйМетод() {guarded}Определенный Шв спецификации UML
официальный формат,
используемый для отделения
имени пакета от имени класса.
Неофициально зачастую
используется и второй
альтернативный формат/d java.awt::FontИЛИj ava.awt,.Fontplain : Int=0 {readonly}
bold : Int=l {readonly}
name : String
style: Int = 0getFont(name:String):Font
getNameO : StringРеализация
интерфейса
и создание
подклассовЗависимость— 1 SubclassFoo— >PurchaseOrderrun() \Q order- Троеточие означает, что в данном разделе могут В
содержаться элементы, которые в данный момент не показаны- Пустой раздел официально означает, что количество элементов
неизвестно. Однако может использоваться для обозначения
отсутствия элементовАссоциация Ьк,
со значением
кратностиРис. 16.1. Основные обозначения для диаграмм классов UML
280 Часть III. Первая итерация фазы развития — основыРис. 16.2. Использование диаграммы классов UML в двух ракурсах16.3. Определение: классификаторВ языке UML под классификатором (classifier) понимается “элемент модели, кото¬
рый описывает поведенческие и структурные свойства” [100]. К классификаторам
могут относиться специальные элементы диаграмм классов, например обычные клас¬
сы и интерфейсы. Классификаторы являются обобщением многих элементов языка
UML, в том числе классов, интерфейсов, прецедентов и исполнителей.16.4. Способы представления атрибутов UML:
имя атрибута и линии ассоциацийАтрибуты классификатора (которые в языке UML1 также называются структурны¬
ми свойствами (structural property)) можно представить несколькими способами.■ С использованием имени атрибута (attribute text), например currentSale : Sale.■ С помощью линии ассоциации (association line).■ С применением обоих подходов.Ни рис. 16.3 изображен тот факт, что объект Register в качестве атрибута вклю¬
чает (содержит ссылку на) один объект Sale.Полный формат описания атрибута имеет следующий вид.область-видимости имя: тип кратность = значение-по-умолчанию {строка-свойств)Для объявления атрибутов язык UML позволяет использовать синтаксис любого
языка программирования. Естественно, что об этом нужно уведомить пользователя
диаграммы или специальным образом настроить используемое CASE-средство.1 Зачастую в этом же контексте используется сокращенный термин свойство (property), кото¬
рый привносит определенную неоднозначность при его сравнении с более общим определени¬
ем свойства в языке UML (см. ниже в этой главе).
Глава 16. Диаграммы классов UML 281С помощью имени ■
атрибута показано,
что объект Register
содержит ссылку
на один экземпляр
SaleRegistercurrentSale : SaleSaleТот факт, что объект Register содержит ссылку на один Ь
экземпляр Sale, отражен с использованием линии ассоциацииРис. 16.3. Использование имени атрибута и линии ассоциации для обозначения атрибута UMLКак видно из рис. 16.1, область видимости (visibility) может быть открытой + (public),
закрытой - (private) и т.д.Рекомендация. Если область видимости не указана явно, то предполагается, что
атрибут относится к закрытой области видимости (private).Обратите внимание, что на рис. 16.3 атрибут представлен с помощью линии ассо¬
циации со следующими элементами.■ Стрелка навигации (navigability arrow) указывает направление связи от объекта-
источника (Register) к целевому объекту (Sale). Это означает, что объект
Register в качестве своего атрибута содержит один объект Sale.■ Кратность связи указывается со стороны целевого объекта, а не объекта-источ¬
ника. (Обозначение кратности более подробно рассматривается в главе 9.)■ Имя роли (rolename) (currentSale) располагается только со стороны целевого
объекта и определяет имя атрибута.■ Имя ассоциации отсутствует.Рекомендация. Если при построении диаграмм классов проектирования для пред¬
ставления атрибутов используются ассоциации, следуйте описанному выше стилю.
Именно такой подход рекомендуется использовать в спецификации UML. На самом
деле метамодель языка UML позволяет использовать кратность, имя роли, а также
имя ассоциации, и со стороны объекта-источника (т.е. со стороны объекта Register
на рис. 16.3). Однако при построении диаграмм классов проектирования такой под¬
ход оказывается не очень полезным.
282 Часть III. Первая итерация фазы развития — основыРекомендация. С другой стороны, при построении диаграмм классов для модели
предметной области лучше показывать имена ассоциаций и избегать стрелок навига¬
ции, поскольку модель предметной области нельзя рассматривать в ракурсе реализа¬
ции (рис. 16.4).Модель предметной
области UP
концептуальный ракурсМодель
проектирования UP
Диаграммы классов
проектирования
ракурс реализацииРис. 16.4. Условные обозначения для ассоциаций, используемых в разных ракурсахСледует заметить, что приведенные обозначения ассоциаций не являются новы¬
ми. Аналогичная система обозначений UML уже использовалась при построении
диаграмм классов для модели предметной области в главе 9. Эти обозначенияубыли
просто уточнены для их использования в контексте построения диаграмм классов
проектирования.Когда нужно использовать имя атрибута и линии ассоциацийЭтот вопрос уже упоминался в контексте построения модели предметной области
в главе 9. Вспомните, что термин тип данных (data type) применим к объектам, для
которых уникальная тождественность не является важной. Стандартными типами
данных являются следующие простые типы.■ Boolean, Date (или DateTime), Number, Character, String (Text), Time,
Address (адрес), Color (цвет), Geometries (Point, Rectangle) (геометричес¬
кие фигуры: точка, прямоугольник), Phone Number (номер телефона), Social
Security Number (номер страхового полиса), Universal Product Code (UPC)
(универсальный код товара), SKU, ZIP или почтовые индексы, перечислимые
типы.Рекомендация. Используйте имя атрибута для обозначения объектов, относящихся
к типам данных, и линии ассоциаций для всех других объектов. Семантически оба
подхода являются эквивалентными, однако линия ассоциации, проведенная к друго¬
му прямоугольнику класса на диаграмме, позволяет добавить визуальный акцент, т.е.
привлечь внимание и дополнительно подчеркнуть взаимосвязь между классами объек¬
тов. На рис. 16.5 приведено несколько примеров обозначения атрибутов.
Глава 16. Диаграммы классов UML 283Рис. 16.5. Представление атрибутов двумя способамиНе забывайте о том, что различные способы представления атрибутов имеют от¬
ношение лишь к системе обозначений UML. В программном коде атрибуты всегда
представляются одинаково: класс Register (см. рис. 16.5) содержит три атрибута.
Например, на языке Java это имеет следующий вид.public class Register{private int id;private Sale currentSale;private Store location;// ...}Обозначения UML для концов линии ассоциацииКак уже упоминалось, на конце линии ассоциации может располагаться стрелка
навигации, а также необязательное имя роли (rolename) (в терминах UML, имя конца
линии ассоциации (association end name)), определяющее имя атрибута. Конечно же,
с концом линии ассоциации может быть также связано и значение кратности (multi¬
plicity), например * или 0..1. Понятие кратности уже рассматривалось выше в гла¬
ве 10. Обратите внимание, что на рис. 16.3 имя роли currentSale определяет имя
атрибута.Как показано на рис. 16.6, при необходимости можно использовать строку свойств
(property string), например {ordered} (упорядоченный) или {ordered, List} (упо¬
рядоченный, список). Первая строка свойств определена в языке UML и означает,
что элементы коллекции являются упорядоченными. Другим предопределенным клю¬
чевым словом является {unique}, которое определяет множество уникальных эле¬
ментов.Как видно из строки свойств {ordered, List}, язык UML поддерживает также
ключевые слова, определяемые пользователем. Данная строка свойств указывает на
то, что коллекция атрибутов line Items будет реализована с помощью интерфейсаList.
284 Часть III. Первая итерация фазы развития — основыПредставление атрибутов-коллекций с помощью
имен атрибутов и линий ассоциацийПредположим, что программный объект Sale содержит список List (интерфейс
с некоторой коллекцией) из нескольких объектов SalesLineltem. Например, на Java
это будет иметь следующий вид.public class Sale
{private List<SalesLineItem> lineltems = new ArrayListo(SalesLine Item);}На рис. 16.6 показаны два способа изображения атрибутов-коллекций на диаграм¬
ме классов.Два способа Ь.отображенияатрибута-коллекцииSaletime : DateTimelineltems : SalesLineltem [1..*]
илиlineltems : SalesLineltem [1..*] {ordered}SalesLineltemSaletime : DateTime1. >lineltems
{ordered, List}
-OSalesLineltemС концом линии ассоциации м.б. связана
строка свойств, например {ordered, List}Рис. 16.6. Два способа изображения атрибутов-коллекций в UML
Заметим, что строки свойств, например, {ordered}, отображать не обязательно.16.5. Блоки примечаний: примечания,
комментарии, ограничения и тела методовБлоки примечаний (note symbol) обычно используются на диаграммах классов.
В UML они отображаются в виде прямоугольников с завернутым уголком, которые
связываются с соответствующим элементом пунктирной линией. Подобные обозначе¬
ния уже встречались в книге, например, на рис. 16.6. Блок примечаний может пред¬
ставлять различные понятия, в том числе следующие.■ Примечание (note) или комментарий (comment), не имеющие семантического
значения.
Глава 16. Диаграммы классов UML 285■ Ограничение (constraint), заключаемое в фигурные скобки.■ Тело метода (method) — реализация операции UML (рис. 16.7).«method» Ь//допустимо использовать синтаксис псевдокода или любого языка
public void enterltem(id, qty){ProductDescription desc = catalog.getProductDescription(id);
sale.makeLineItem(desc, qty);}RegisterendSale()OenterItem(id, qty)
makeNewSale()
makePayment(cashTendered)Рис. 16.7. Изображение тела метода на диаграмме классов16.6. Операции и методыОперацииНа диаграммах классов UML зачастую представляют операции (например,
рис. 16.1). На момент написания этой книги полный официальный формат представ¬
ления операции имеет следующий вид.Область-видимости имя (список-параметров) {строка-свойств}Обратите внимание на отсутствие типа возвращаемого значения, которое в спе¬
цификации UML 2.0 по каким-то причинам не определено. Остается надеяться, что
со временем авторы стандарта вернутся к обозначениям в стиле UML 1, которым до
сих пор пользуются многие разработчики.Область-видимости им я {список-параметров) : тип-возвращаемого-значения{строка-свойств}Рекомендация. Указывайте тип возвращаемого значения.Рекомендация. Если область видимости не указана явно, по умолчанию предполага¬
ется, что операция является открытой.В строке свойств содержится произвольная дополнительная информация, напри¬
мер генерируемое исключение и т.д. Помимо официального синтаксиса описания
операций UML допускает представление сигнатуры операции на любом языке про¬
граммирования, например Java. Таким образом, допустимы оба способа представле¬
ния операций.+ getPlayer( name : String ) : Player {exception IOException}public Player getPlayer ( String name ) throws IOException
286 Часть III. Первая итерация фазы развития — основыОперация — это не метод. Операцией (operation) UML называют объявление с ука¬
занием имени, параметров, типа возвращаемого значения, списка исключений и,
возможно, набора ограничений для пред- и постусловий. Однако это не реализация,
описываемая в теле метода.При рассмотрении описаний операций в главе 11 было введено понятие ограни¬
чения операции UML.Как отображать методы на диаграмме классовМетод (method) представляет собой реализацию операции, удовлетворяющую
всем заданным для нее ограничениям. Методы можно представлять на диаграммах
взаимодействия либо на диаграммах классов. В последующих главах используется оба
способа иллюстрации методов.Обозначение тела метода на языке UML показано на рис. 16.7.Обратите внимание, что при использовании для отображения метода блока при¬
мечания на одной и той же диаграмме смешиваются статическое и динамическое
представления. Тело метода, определяющее динамику поведения, добавляет эту ди¬
намику на диаграмму классов. Такой способ представления информации годится
для книги или документов, но не очень удобен при построении диаграмм вручную.
Автоматизированные средства проектирования зачастую предоставляют для описа¬
ния тела методов отдельное всплывающее окно.Представление операций на диаграммах UMLОперация createСообщение create на диаграмме взаимодействия обычно интерпретируется как
вызов оператора new или конструктора на языках Java или С#. На диаграмме классов
сообщение create обычно представляется в виде определения конструктора с уче¬
том правил конкретного языка (например, Java, С#, C++ и т.д.). На рис. 16.1 показан
пример конструктора SuperClassFoo со стереотипом «constructor», уточняю¬
щим категорию данного метода.Операции доступаОперациями доступа (accessing operation) называются методы извлечения или за¬
писи атрибутов, например getPrice или setPrice. Такие операции зачастую не
изображают на диаграммах классов, чтобы не перегружать их избыточной инфор¬
мацией, поскольку при наличии N атрибутов пришлось бы указывать 2N операций
доступа. Операции доступа не изображаются при построении диаграмм вручную, а
также зачастую не выводятся на экран при использовании средств автоматизации
проектирования.16.7. Ключевые словаВ UML ключевым словом (keyword) называется текстовое представление категории
элемента модели. Например, для обозначения интерфейса используется ключевое
слово «interface» (см. рис. 16.1). Для обозначения исполнителя используется
ключевое слово «actor».
Глава 16. Диаграммы классов UML 287Рекомендация. При построении диаграмм вручную обозначения ключевых слов мак¬
симально упрощаются, например, в одинарных угловых скобках <interface> или <1>.Большинство ключевых слов заключают в угловые скобки «»2, однако иногда
их помещают в фигурные скобки, соответствующие обозначению ограничений, на¬
пример {abstract}. В целом каждому элементу UML может соответствовать строка
свойств, представляющая собой ключевые слова, заключенные в фигурные скобки.На рис. 16.1 приводятся оба способа обозначения ключевых слов.Рассмотрим некоторые примеры ключевых слов UML.3Ключевое словоЗначениеПример использования«actor»Представляет исполнителяНа диаграмме классов выше имени
классификатора«interface»Представляет интерфейсНа диаграмме классов выше имени
классификатора{abstract}Абстрактный элемент, который
не может быть инстанцированНа диаграмме классов, после имени
классификатора или операции{ordered}Множество упорядоченных объектовНа диаграмме классов, в конце ассо¬
циации16.8. Стереотипы, профили и меткиСтереотипы, так же как и ключевые слова, выделяются с помощью угловых ско¬
бок, например «стереотип». Однако, несмотря на одинаковые обозначения, эти
два элемента значительно отличаются. Стереотип (stereotype) отображает уточне¬
ние существующего понятия моделирования и определяется в рамках UML-профиля
(profile) — набора взаимосвязанных стереотипов, меток и ограничений, которые ис¬
пользуются для некоторой предметной области. Примерами таких профилей могут
являться профили для управления проектами и моделирования данных.В языке UML определено множество стереотипов4, таких как «destroy» (ис¬
пользуется на диаграммах последовательностей), а также допускается использование
задаваемых пользователем стереотипов. Таким образом, стереотипы предоставляют
механизм расширения (extension mechanism) UML.На рис. 16.8 показан пример объявления стереотипов и их использования.
Стереотип определяет множество дескрипторов или меток (tag) с использованием син¬
таксиса атрибутов. Если элемент (например класс Square) отмечен некоторым стере¬
отипом, все метки этого стереотипа применяются к элементу и могут иметь опреде¬
ленное значение.2 Заметим, что в UML 1 угловые скобки «» использовались только для представления сте¬
реотипов. В UML 2 они применяются для обозначения не только стереотипов, но и ключевых
слов.3 В UML определено много ключевых слов, полный список которых приводится в соответ¬
ствующей спецификации.4 См. спецификацию UML.
288 Часть III. Первая итерация фазы развития — основыОбъявление стереотипа 1Расширение UML. ЬОпределение связи с базовым
элементом метамодели UML —
метаклассом Element\«metaclass»Element\«stereotype»\1 ё Authorshipauthor: Stringstatus: StringИспользование стереотипа.Если элемент отмечен стереотипом
«authorship», к нему применяются
все метки этого стереотипа, которые
могут содержать значения7\/с/\>«authorship»
SquareС«authorship»
author = "крэг"
status = "проверено"Рис. 16.8. Объявление и использование стереотипов16.9. Свойства и строки свойствСвойством (property) в UML называется “именованное значение, описывающее
характеристику элемента и имеющее семантическое значение” [100]. Часть свойств
является предопределенными в UML, например, такие как область видимости (visibi¬
lity), представляющая собой свойство операции. Остальные могут быть определены
пользователем.Свойства элементов могут быть представлены множеством способов, однако для
текстового представления следует использовать определенную в UML форму стро¬
ки свойств: {имя1=значение!, имя2=значение2). Некоторые свойства могут быть
представлены без определенного значения, например свойство {abstract} в стро¬
ке {abstract, visibility=public}. Обычно такая форма описания подразумевает
двоичное свойство и является сокращением для {abstract=true}. Следует отметить,
что запись {abstract} одновременно является примером как ограничения (constraint),
так и строки свойств (property string).16.10. Обобщение, абстрактные классы,
абстрактные операцииОтношение обобщения (generalization) в UML изображается при помощи сплош¬
ной линии и жирной треугольной стрелки, ведущей от подкласса к суперклассу (см.
рис. 16.1). Что обозначает это отношение? В спецификации UML по этому поводу
сказано следующее.Обобщение — таксономическое отношение между более общим элементом и
более конкретным. Каждый экземпляр конкретного элемента также является
непрямым экземпляром обобщенного элемента. Таким образом, конкретизиро¬
ванный элемент косвенно обладает свойствами обобщенного элемента. [100]Является ли отношение обобщения синонимом наследования (inheritance) в
объектно-ориентированном проектировании? Ответ зависит от области применения
Глава 16. Диаграммы классов UML 289отношения. Для диаграммы концептуальных классов из модели предметной области
ответом будет “нет”. В этом случае отношение обобщения подразумевает то, что су¬
перкласс является множеством, а подкласс — подмножеством. С другой стороны, на
диаграмме классов проектирования это отношение подразумевает объектно-ориенти¬
рованное наследование свойств подкласса от суперкласса.Как показано на рис. 16.1, абстрактные классы (abstract class) и операции могут
быть показаны либо при помощи метки {abstract} (полезно при построении диа¬
грамм UML вручную), либо при помощи выделения имени элемента курсивом (такой
способ поддерживается средствами автоматизации проектирования).Финальные классы (final class) и операции, которые не могут быть переопределены
в подклассах, изображаются при помощи дескриптора {leaf}.16.11. ЗависимостьЛинии зависимости можно использовать на любой диаграмме, однако чаще все¬
го их применяют на диаграммах классов и пакетов. UML включает общее обозначе¬
ние для отношения зависимости (dependency relationship), которое показывает, что
элемент-клиент (любого рода, включая классы, пакеты, прецеденты и т.д.) обладает
знанием об элементе-поставщцке и что изменение в поставщике может повлиять на
клиента. Естественно, такое определение является очень широким.Зависимость представляется пунктирной линией со стрелкой, указывающей от
клиента к поставщику.Зависимость можно рассматривать как разновидность связывания (coupling), поня¬
тия, которое является традиционным в области разработки программных систем и
обозначает, что некоторый элемент связан с другим или зависит от него.Существует много возможных вариантов зависимости; наиболее распространен¬
ными из которых являются следующие (в терминах диаграмм объектов и классов).■ Обладание атрибутом с типом элемента-поставщика.■ Отправка сообщения поставщику. В этом случае видимость поставщика может
быть реализована следующим образом.• Посредством атрибутов, переменных-параметров, локальной переменной, гло¬
бальной переменной, на уровне класса (вызов статических методов класса).■ Получение параметра с типом элемента-поставщика.■ Поставщик является суперклассом или интерфейсом.Все эти связи могут быть показаны при помощи линии зависимости в UML.
Однако для некоторых из этих связей имеются особые обозначения, которые пред¬
полагают зависимость. Например, существуют специальные обозначения для супер¬
классов, реализации интерфейсов и атрибутов (линия, обозначающая атрибут как
ассоциацию).Таким образом, для этих случаев использование обозначения зависимости являет¬
ся бесполезным. Например, на рис. 16.6 элемент Sale имеет некоторую зависимость
от SalesLineltems, показанную при помощи линии ассоциации. Поскольку связь
между этими двумя элементами уже обозначена, добавление второй пунктирной ли¬
нии является избыточным.И все-таки, когда стоит использовать данное обозначение?ЮЗак. 3357
290 Часть III. Первая итерация фазы развития — основыРекомендация. На диаграммах классов следует использовать обозначение зависим(
сти для отображения глобальных переменных, переменных-параметров, локальны
переменных и статических методов (в тех случаях, когда вызывается статический м<
тод другого класса).Например, следующий код Java иллюстрирует метод updatePriceFor в классе Sale
public class Sale
{public void updatePriceFor(ProductDescription description){Money basePrice = description.getPrice();//. . .}//. . .}Метод updatePriceFor получает в качестве параметра объект класса Product¬
Description и после этого отправляет ему сообщение getPrice. Таким образом
объект класса Sale посредством параметров обеспечивает видимость объекта
ProductDescription и, следовательно, зависимость от него. Если последний класс
будет изменен, то это изменение может затронуть класс Sale. Такая зависимость мо¬
жет быть показана на диаграмме классов (рис. 16.9).Рис. 16.9. Обозначение зависимостиПриведем другой пример. В следующем фрагменте кода на Java описан метод doX
класса Foo.public class Foo
{public void doX(){System.runFinalization() ;//...}//...}
Глава 16. Диаграммы классов UML 291Метод doX вызывает статический метод класса System, что приводит к появле¬
нию зависимости через статический член. Эта зависимость может быть показана на
диаграмме классов ( рис. 16.10).Метод dox вызывает статический метод
runFinalization. Поэтому существует
отношение зависимости с классом SystemFoodoX ()SystemrunFinalizationOРис. 16.10. Еще одно обозначение зависимостиМетки зависимостейДля указания типа зависимости ее можно пометить некоторыми ключевыми сло¬
вами или стереотипами ( рис. 16.11).WindowClockgetTime()«create»ОЗависимость, определяемая Ь,
вызовом операций класса clockЗависимость, определяющая
создание объектами а объектов вРис. 16.11. Метки зависимостей в UML16.12. ИнтерфейсыUML предоставляет несколько возможностей для отображения реализации интер¬
фейса (interface), предоставления интерфейса клиентам и зависимости через интерфейс
(требуемый интерфейс, required interface). В UML существует понятие реализации ин¬
терфейса (interface realization). На рис. 16.12 показаны возможности UML по отобра¬
жению интерфейсов.Обозначение при помощи сокетов (socket notation) является нововведением в
UML 2. Это обозначение полезно для отображения зависимости “Класс X требует
(использует) интерфейс Y” без изображения линии, указывающей на интерфейс Y.
292 Часть III. Первая итерация фазы развития - основыРис. 16.12. Различные обозначения для отображения интерфейсов в UML16.13. Композиция или агрегацияАгрегация (aggregation) является слабоопределенным типом ассоциации в UML и
отображает самую общую зависимость типа “целое-часть” (как и многие другие ассо¬
циации). Этот тип связи не имеет четко определенной семантики в UML, в отличие
от обычной ассоциации. Несмотря на это данный термин введен в спецификации
UML. Зачем? Ответ заключен в цитате Румбаха (одного из основоположников и клю¬
чевых разработчиков UML).Несмотря на слабовыраженную семантику агрегации, все считают, что она не¬
обходима (по различным причинам). Думайте о ней как о плацебо в моделиро¬
вании. [108]Рекомендация. Таким образом, следуя совету создателей UML, не следует исполь¬
зовать агрегацию при моделировании. Вместо этого по возможности стоит использо¬
вать композицию (composition).Композиция, так же известная как композитная агрегация (composite aggregation),
является строго определенным типом связи “целое-часть” и полезна в некоторых
моделях. Отношение композиции предполагает, что 1) экземпляр части (например,
Square) в каждый момент времени принадлежит только одному целому (напри¬
мер, Board); 2) часть всегда принадлежит целому (пальцы не существуют отдельно
Глава 16. Диаграммы классов UML 293от руки); 3) целое ответственно за создание и удаление своих частей — либо через
самостоятельное создание/удаление, либо через взаимодействие с другими объекта¬
ми. Следствием этих ограничений является то, что при уничтожении композитно¬
го объекта его части должны быть либо уничтожены, либо присоединены к другому
композитному объекту. Например, если реальная настольная игра “Монополия” уни¬
чтожается, то также уничтожаются и все ее клетки (с концептуальной точки зрения).
Аналогично, если программный объект Board уничтожается, то уничтожаются и про¬
граммные объекты Square.Для обозначения композиции в UML используется закрашенный ромб на линии
ассоциации со стороны целого (см. рис. 16.13).Рекомендация, Имя ассоциации в композиции всегда подразумевает некоторую раз¬
новидность отношения “имеет-часть”, так что не следует специально заботиться об
их именовании.Рис. 16.13. Композиция в UML16.14. ОграниченияОграничения можно использовать для большинства диаграмм UML, но наиболее
часто их применяют для диаграмм классов. Ограничение (constraint) UML — это не¬
которое условие, накладываемое на элемент UML. Оно изображается как текстовое
сообщение, заключенное в фигурные скобки; например {size >= 0}. Текст может
быть на естественном языке либо на формальном языке спецификации UML, Object
Constraint Language (OCL) [122] (рис. 16.14).Три способа отображения ограничений UML 'Stacksize : Integer {size >= 0}push (element) O- pop () :ObjectOk^{постусловие: новый размер = старый размер + 1}постусловие: новый размер = старый размер -1
}Рис. 16.14. Ограничения
294 Часть III. Первая итерация фазы развития — основы16.15. Уточненная ассоциацияУточненная ассоциация (qualified association) обладает неким квалификато¬
ром (qualifier), который используется для выбора элемента (или элементов) из мно¬
жества объектов на основании ключа. Неформально, с точки зрения программного
обеспечения, это предполагает выборку объектов по некоторому ключу, подобно вы¬
борке объектов из HashMap. Например, если объект ProductCatalog содержит не¬
сколько элементов ProductDescription и каждый из них можно выбрать при помо¬
щи itemID, то для отображения этого факта можно использовать обозначение UML,
показанное на рис. 16.15.Существует особенность, которую необходимо учитывать при использовании уточ¬
ненных ассоциаций: изменение кратности. На рис. 16.15, а и б видно, что уточнение
уменьшает кратность ассоциации, поскольку предполагается выбор одного экземпля¬
ра из множества объектов.ProductСодержитProductCatalog11..*Descriptionб)11ProductitemIDСодержитProductCatalogDescriptionОоЗначение кратности
уменьшено до 1Рис. 16.15. Уточненная ассоциация в UML16.16. Класс ассоциацииКласс ассоциации (association class) позволяет рассматривать ассоциацию саму по
себе как класс и моделировать ее при помощи атрибутов, операций и других свойств.
Например, если некая компания Company нанимает множество сотрудников Persons
и это отношение можно промоделировать ассоциацией Employs, то данную ассоциа¬
цию можно представить как класс Employment с атрибутами startDate.В UML такая ситуация отображается с помощью пунктирной линии, ведущей от
ассоциации к классу ассоциации (рис. 16.16).Человек может Ь
работать в нескольких
компанияхEmploymentsalarystartDateРис. 16.16. Класс ассоциации в UML
Глава 16. Диаграммы классов UML 29516.17. Классы-синглетоныВ мире шаблонов объектно-ориентированного проектирования существует один
часто используемый шаблон Singleton. Подробно этот шаблон будет описан ниже, од¬
нако его основная идея состоит в том, что существует только единственный инстанци¬
рованный экземпляр класса, и не более. На диаграмме UML такой класс может быть
помечен символом 1 в верхнем правом углу поля имени (рис. 16.17).Рис. 16.17. Отображение объекта-синглетона16.18. Параметризованные классы и интерфейсыМногие языки (Java, C++, ...) поддерживают шаблонные типы (templatized type),
также известные (с различиями в нюансах), как шаблоны (template), параметризован¬
ные типы (parameterized type) и родовые типы (generic).5 Наиболее часто параметризо¬
ванные классы используются для создания коллекций объектов определенного типа.
В качестве примера можно привести программный объект Board, содержащий ин¬
терфейс к коллекции List, представляющий множество объектов Squares. В каче¬
стве конкретной реализации интерфейса List используется ArrayList.public calss Board{private List<Square> squares'= new ArrayList<Square>();П ...}Заметим, что интерфейс List и класс ArrayList параметризуются типом элемен¬
та Square. На рис. 16.18 показано обозначение UML для параметризованного класса.5 Введение шаблонных классов было обосновано увеличением производительности и без¬
опасности типов.
296 Часть III. Первая итерация фазы развития — основыПараметризованные ■
интерфейсы или классы,
интерфейсы-шаблоны
или классы-шаблоны.К - параметр шаблона.Л)«interfaced
Listclear()Анонимный класс с В
завершенным связыванием
с шаблономArrayList<T->Square>
 CL.clear()ArrayListelementsclear()Вполне возможно, что символ -сбудет заменен Ь.
каким-нибудь другим символом, например =В спецификации иМ1_тип Вц
атрибута можно определить
путем связывания с шаблоном.
Этот механизм предполагает
использование стрелки.Илис использованием конструкций
другого языка, например JavaхBoardsquares : List<K»Square>
илиsquares : List<Square>Например, атрибут elements ■
является параметризованным
массивом типа т, который перед
реальным использованием
нужно конкретизировать
(связать с реальным типом)Рис. 16.18. Параметризованные классы в UML16.19. Поля, определяемые пользователемПомимо предопределенных полей,, таких как имя класса, его атрибуты и операции,
пользователь может вводить собственные поля в элемент представления класса. Эта
возможность показана на рис. 16.19.DataAccessObj ect
id : IntdoX ()Генерируемые исключенияDatabaseExceptionIOExceptionОбязанностиВыполнение сериализации
и десериализации объектов,
а также их запись и чтениеРис. 16.19. Поля, определенные пользователем
Глава 16. Диаграммы классов UML 29716.20. Активный классАктивный объект (active object) — это объект, методы которого выполняются в от¬
дельном программном потоке. Нет ничего удивительного в том, что класс активных
объектов получил название активного класса (active class). В UML такие классы от¬
мечаются при помощи двойных вертикальных линий по бокам обозначения класса
(рис. 16.20).Рис. 16.20. Активные классы в UML16.21. Связь между диаграммами
классов и взаимодействияПри построение диаграммы взаимодействия выделяется набор классов и их ме¬
тодов. Например, из тривиальной диаграммы последовательностей make Payment,
показанной на рис. 16.21, очевидным образом можно получить определения классовRegister и Sale.: Register
 , : Saleв makePayment(cashTendered) jСообщения на диаграммах Ъ
взаимодействия определяют
операции на диаграммах
классовmakePayment(cashTendered)/Registersale *1 >(currentSalemakePayment(...)makePayment(...)Классы, Ь
идентифициро¬
ванныепри построениидиаграммвзаимодействия,используютсяна диаграммахклассовРис. 16.21. Влияние диаграммы последовательностей на диаграмму классов
298 Часть III. Первая итерация фазы развития — основыТаким образом, диаграмма классов может быть получена из диаграммы взаимодей¬
ствия. Это предполагает определенный порядок построения диаграмм: сначала созда¬
ются диаграммы взаимодействия, а затем — диаграммы классов. Однако на практике,
особенно при использовании гибкого подхода к моделированию, эти взаимодополня¬
ющие динамические и статические диаграммы строятся параллельно (например, 10
минут отводится для создания одной диаграммы и 10 минут для другой).Рекомендация. Хорошее средство построения диаграмм UML должно автоматиче¬
ски переносить изменения от одной диаграммы к другой. При создании этих диа¬
грамм вручную следует использовать расположенные рядом доски или листы бумаги.
GRASP: проектирование
объектов на основе
распределения обязанностейПонимание обязанностей — это ключ к хорошему объектно-ориентированномупроектированию.Мартин Фаулер (Martin Fowler)Основная задача■ Научиться применять пять принципов или шаблонов GRASP для
объектно-ориентированного проектирования.Эта и следующая главы посвящены ключевым вопросам объектно-ориентирован¬
ного проектирования. Процесс объектного проектирования иногда описывают сле¬
дующим образом.Сначала определяются требования и создается модель предметной области,
затем добавляются методы программных классов, описывающие передачу со¬
общений между объектами для удовлетворения требований.Такое описание мало полезно на практике, поскольку в нем не учтены основопола¬
гающие принципы и вопросы, лежащие в основе этого процесса. Вопрос определения
способов взаимодействия объектов и принадлежности методов чрезвычайно важен и
отнюдь не тривиален. Освоение ООП требует изучения большого количества принци¬
пов, определяющих достаточно большое количество степеней свободы. В этом помо¬
жет применение шаблонов — именованных описаний типичных реализаций. Изучив
предлагаемые в книге примеры, попытайтесь воссоздать описанные здесь решения на
практике, применяя готовые шаблоны, например Information Expert.
300 Часть III. Первая итерация фазы развития — основыЧто дальше?После рассмотрения основных условных обозначений UML, используемых
для статического и динамического объектно-ориентированного проектирования,
в данной главе содержится описание основных принципов проектирования.В следующей главе приведены более подробные конкретные примеры применения
этих принципов и моделирования на языке UMLДиаграммы Диаграммывзаимодействия классов
UML UMLПроектирование
объектов
с помощью
шаблонов
GRASP
—•—\Примеры Проектирование
проектирования областейобъектов видимости17.1. UML и принципы проектированияПоскольку UML — это просто стандартный язык визуального моделирования, его
изучение не позволит вам мыслить объектами. В этом состоит основная идея этой
книги. Иногда UML описывают как средство проектирования, но это неверно.Важнейшим средством проектирования программных систем является чело¬
веческий мозг, вооруженный принципами проектирования, а вовсе не UML или
любая другая технология.17.2. Объектное проектирование — примеры )
входов, видов деятельности и выходовВ этом разделе приводится общая картина проектирования в рамках итеративно¬
го метода разработки. Здесь рассматриваются следующие вопросы.■ Что было сделано? — предшествующие виды деятельности (в том числе семи¬
нар) и выделенные артефакты.■ Как артефакты и виды деятельности связаны между собой? — влияние артефак¬
тов (в том числе прецедентов) на объектные проектные решения.■ Как и в каких объемах выполнять моделирование в процессе проектирования?■ Каковы ожидаемые результаты?Таким образом, автор поможет разобраться, как артефакты анализа связаны с
объектным проектным решением.Входные данные для объектного проектированияДля начала разберемся со входными данными. Рассмотрим процесс разработки
POS-системы NextGen.
Глава 17. GRASP: проектирование объектов на основе распределения обязанностей 301Завершен первый двухдневный семинар по
определению требованийТри из двадцати прецедентов (наиболее важные
с архитектурной точки зрения) детально проана¬
лизированы, в ТОМ числе прецедент Оформление
продажи. (Согласно принципам UP до начала ре¬
ализации проекта детально анализируются лишь
10-20% требований)Выполнены эксперименты по программирова¬
нию, призванные разрешить важные технические
вопросы, например, будет ли интерфейс пользо¬
вателя, реализованный на Java Swing, работать на
сенсорном экранеГлавный архитектор и разработчики пришли к сог¬
лашению реализовать и протестировать в течение
первой трехнедельной итерации несколько сце¬
нариев прецедентов Оформление продажиНачинается реализация других артефактов: до¬
полнительной спецификации, словаря терминов и
модели предметной областиГлавный архитектор обрисовал основные идеи
крупномасштабной логической архитектурыс использованием диаграммы пакетов UML. Это
уже часть модели проектирования в рамках UPКаковы входные данные артефактов и их взаимосвязи в объектном проектном ре¬
шении?1 Эти взаимосвязи показаны на рис. 17.1 ив следующей таблице.Описание прецедентов определяет видимое по¬
ведение программных объектов, реализующих эти
прецеденты. В рамках UP объектно-ориентиро-
ванное проектирование называется реализацией
прецедентовСистемные диаграммы последовательностейопределяют системные операции, которые яв¬
ляются начальными сообщениями для диаграмм
взаимодействияОписание операций могут дополнять описание
прецедентов и прояснять результаты системных
операций для программных объектов. Детальное
описание результатов приводится в постусловияхДополнительная спецификация определяет не¬
функциональные цели, например по поддержке
многоязычностиСловарь терминов проясняет детали параметров
или данных, поступающих с уровня интерфейса
пользователя, передаваемых в базу данных, а
также логику требований, в том числе допусти¬
мые форматы и способы проверки корректности
данныхМодель предметной области задает некоторые
имена и атрибуты программных объектов уровня
предметной области в архитектуре системыНе все эти артефакты являются необходимыми. Напомним, что в UP все элемен¬
ты являются необязательными. Их использование позволяет снизить некоторые ри¬
ски разработки системы.1 К другим входным данным относится проектная документация существующей системы,
которую можно модифицировать. Полезно также выполнить обратное проектирование суще¬
ствующего кода для получения диаграммы пакетов UML. Это позволит понять крупномасштаб¬
ную логическую структуру, а также получить некоторые диаграммы классов и последователь¬
ностей.
302 Часть III. Первая итерация фазы развития — основыПример взаимосвязи артефактов UPМодель предметной областиБизнес-
модели -
рованиеРис. 17.1. Пример взаимосвязи артефактов в процессе объектно-ориентированногопроектирования
Глава 17. GRASP: проектирование объектов на основе распределения обязанностей 303Виды деятельности в процессе объектного проектированияТеперь от задач анализа перейдем к рассмотрению вопросов моделирования и
проектирования.На данном этапе можно приступать к одному из следующих видов деятельности:
написанию кода (если разработка системы выполняется на основе тестирования), по¬
строению объектных моделей UML для объектного проектирования, использованию
другой технологии моделирования, например с помощью карт CRC.2Если моделирование выполняется на основе UML, то речь идет о визуальном мо¬
делировании. В этом случае в течение одного дня строятся диаграммы взаимодей¬
ствия и подробные диаграммы классов (динамические и статические модели). При
этом используются различные принципы объектно-ориентированного проектиро¬
вания, например шаблоны GRASP или GoF (Gang-of-Four) . Объектно-ориентированное
проектирование осуществляется на основе распределения обязанностей между взаи¬
модействующими объектами.Эта и последующие главы посвящены применению подхода RDD, а также шабло¬
нов проектирования GRASP и GoF.В течение дня, посвященного моделированию, команда разработчиков разбивает¬
ся на небольшие группы и строит модели (на доске или с помощью автоматизирован¬
ных средств моделирования) для наиболее сложных и неоднозначных фрагментов
проекта. При этом с помощью UML, средств прототипирования или просто каранда¬
ша и бумаги разрабатываются модели интерфейса пользователя, объектно-ориенти¬
рованной архитектуры и базы данных.Модели строятся для улучшения понимания проектного решения и облегчения взаимодей¬
ствия между разработчиками, а не с целью документирования. Некоторые модели,
однако, послужат хорошей отправной точкой для автоматической генерации кода.На следующий день моделирование завершается, и команда разработчиков “пере¬
квалифицируется” в группу кодировщиков. При излишнем внимании к этапу проекти¬
рования существует опасность скатиться к каскадному процессу разработки.РезультатыНа рис. 17.1 показаны некоторые входные артефакты и взаимосвязь между ними,
позволяющие получить результирующие диаграммы взаимодействия и классов UML.
К этим артефактам анализа приходится периодически возвращаться на этапе проек¬
тирования, например, перечитывать описания прецедентов или операций, сверяться
с моделью предметной области и пересматривать дополнительную спецификацию.Таким образом, в течение “дня моделирования” строятся следующие артефакты:■ диаграммы классов, взаимодействия, пакетов UML для сложных фрагментов
проектного решения;■ прототипы и зарисовки интерфейса пользователя;2 Выбор конкретного подхода зависит от контекста или личных предпочтений разработчи¬
ков.
304 Часть III. Первая итерация фазы развития — основы■ модели базы данных (с помощью специального набора обозначений UML, кото¬
рый будет описан в главе 38);■ зарисовки и прототипы отчетов.17.3. Обязанности и проектирование
на основе обязанностейЗачастую проектирование программных объектов и крупномасштабных компо¬
нентов описывают в терминах обязанностей, ролей и кооперации. Это часть бо¬
лее широкого подхода, получившего название проектирование на основе обязанностей
(responsibility-driven design — RDD) [123].В RDD считается, что программные объекты имеют определенные обязанности —
абстракции, реализуемые ими. В UML обязанность (responsibility) определяется как
“контракт или обязательство классификатора” [100]. Обязанности описывают пове¬
дение объекта в терминах его ролей. В общем случае можно выделить два типа обя¬
занностей: знание (knowing) и действие (doing).Ниже перечислены обязанности, относящиеся к действиям объекта.■ Выполнение некоторых действий самим объектом, например создание экзем¬
пляра или выполнение вычислений.■ Инициирование действий других объектов.■ Управление действиями других объектов и их координирование.Ниже перечислены обязанности, относящиеся к знаниям объекта.■ Наличие информации о закрытых инкапсулированных данных.■ Наличие информации о связанных объектах.■ Наличие информации о следствиях или вычисляемых величинах.Обязанности присваиваются объектам в процессе объектно-ориентированного
проектирования. Например, можно сказать, что объект Sale отвечает за создание
экземпляра SalesLineltems (действие) или что объект Sale отвечает за наличие ин¬
формации о стоимости покупки (знание).Совет. Обязанности, относящиеся к разряду “знаний”, зачастую вытекают из
модели предметной области, поскольку она иллюстрирует атрибуты и ассоциации.
Например, если в модели предметной области класс Sale содержит атрибут time, то
с целью уменьшения разрыва в представлениях программный класс Sale тоже дол¬
жен “знать” время соответствующей продажи.Возможность реализации обязанностей в виде классов и методов зависит от точ¬
ности их описаний. Реализация сложных обязанностей требует определения сотен
классов и методов. Для простых обязанностей достаточно одного метода. Например,
реализация обязанности “обеспечения доступа к реляционным базам данных” может
потребовать создания десятков классов и сотен методов, а для реализации обязанно¬
сти “создания экземпляра объекта Sale” достаточно одного метода одного класса.Между методами и обязанностями нельзя ставить знак равенства, однако можно
утверждать, что реализация метода обеспечивает выполнение обязанностей.
Глава 17. GRASP: проектирование объектов на основе распределения обязанностей 305В RDD существует идея кооперации (collaboration). Обязанности реализуются по¬
средством методов, действующих либо отдельно, либо во взаимодействии с другими
методами и объектами. Например, для класса Sale можно определить один или не¬
сколько методов вычисления стоимости (скажем, метод getTotal). Для выполнения
этой обязанности объект Sale должен взаимодействовать с другими объектами, в
том числе передавать сообщения getSubtotal каждому объекту SalesLineltem о не¬
обходимости предоставления соответствующей информации этими объектами.Основной принцип RDDRDD — это общий подход к проектированию программных объектов. Програм¬
мные объекты рассматриваются как люди, имеющие свои обязанности и сотруд¬
ничающие с другими людьми для их выполнения. Согласно основному принципу
RDD, объектное проектное решение представляет собой сообщество взаимодей¬
ствующих объектов, имеющих свои обязанности.Важный момент: шаблоны GRASP позволяют выявить и описать основные прин¬
ципы распределения обязанностей, положенные в основу RDD.17.4. GRASP — это методический подход
к объектному проектированиюGRASP как способ распределения обязанностей
и объектно-ориентированного проектированияПринципы объектного проектирования отражены в шаблонах проектирования
GRASP, изучение и применение которых позволит освоить методический подход и
снять завесу таинственности с процесса разработки. Шаблоны GRASP позволяют по¬
нять основные принципы объектного проектирования и методично применять их.
Эти шаблоны называют также шаблонами распределения обязанностей (pattern of assign¬
ing responsibilities).Назначение этой главы (и нескольких других) — помочь разработчику научиться
применять фундаментальные принципы распределения обязанностей между объекта¬
ми в рамках объектного проектирования на основе шаблонов GRASP.Понимание принципов применения шаблонов GRASP для объектного проектиро¬
вания — основная цель этой книги.Таким образом, шаблоны GRASP позволяют структурировать и именовать базовые
принципы проектирования, поэтому конкретные названия шаблонов (Information
Expert, Creator) не столь важны.
306 Часть III. Первая итерация фазы развития — основы17.5. Обязанности, GRASP и диаграммы UMLРаспределение обязанностей между объектами обычно выполняется на этапе про¬
граммирования или моделирования. В контексте артефактов UML обязанности (реа¬
лизованные в виде методов) рассматриваются в процессе создания диаграмм взаимо¬
действия.Из рис. 17.2 видно, что обязанностью объектов Sale является создание экземпля¬
ров Payment. Для выполнения этой обязанности передается сообщение, реализуемое
посредством метода makePayment. Более того, для ее выполнения требуется взаимо¬
действие с объектами SalesLineltem и вызов их конструктора.: SalemakePayment(cashTendered)
_Предполагается, ■что объектам Sale назначена
обязанность создавать
объекты PaymentРис. 17.2. Связь методов и обязанностейИтак, диаграммы взаимодействий отражают распределение обязанностей между
объектами. Распределенные обязанности отображаются в виде сообщений, отправля¬
емых различным классам объектов. В этой главе основное внимание уделяется фун¬
даментальным принципам распределения обязанностей, выраженным в терминах
шаблонов GRASP. Процесс распределения обязанностей иллюстрируется с помощью
диаграмм взаимодействия.17.6. ШаблоныОпытные разработчики объектно-ориентированных систем сформулировали об¬
щие принципы и стандартные решения, помогающие в разработке программного
обеспечения. Если эти принципы и идиомы систематизировать и структурировать,
а также присвоить им имена, то их можно применять в качестве шаблонов (patterns).
Приведем пример одного из таких шаблонов.Имя шаблонаInformation ExpertРешаемая проблемаКаков основной принцип распределения обязанностей между объектами?РешениеОбязанности назначаются классу, который имеет информацию, необходи¬мую для их выполненияiiicreate(cashTendered):Payment
Глава 17. GRASP: проектирование объектов на основе распределения обязанностей 307В объектно-ориентированной технологии проектирования шаблоном называют
именованное описание проблемы и ее решения, которые можно применить при раз¬
работке других систем. В идеале шаблон должен содержать советы по поводу его при¬
менения в различных ситуациях, а также описание его преимуществ и недостатков3.
Многие шаблоны содержат рекомендации по распределению обязанностей между
объектами с учетом специфики задачи.Проще говоря, шаблон — это именованная пара “проблема-решение”, содержащая
рекомендации для применения в различных конкретных ситуациях, которую
можно использовать в различных контекстах.Шаблоны имеют именаРазработка программного обеспечения — достаточно новая область знаний, а в
новых областях отсутствие фиксированных названий принципов затрудняет обще¬
ние и изучение. Шаблоны имеют осмысленные имена, например Information Expert
или Factory. Именование шаблонов, методов и принципов имеет следующие преиму¬
щества.■ Позволяет зафиксировать понятие в памяти■ Облегчает общениеЕсли шаблон имеет имя, то его легко обсуждать с другими разработчиками.
Рассмотрим пример дискуссии между двумя разработчиками программного обеспе¬
чения.Джил: “Привет, Джек. Я предлагаю для базы данных реализовать службы на
основе шаблона Facade. Можно также использовать шаблоны Abstract Factory
и Proxy.”Джек: “Что за чепуху ты несешь?”Джил: “Все понятно. Прочитай вот это.”Шаблоны не содержат новых идейШаблон можно назвать новым, если он описывает новую идею. Однако сам тер¬
мин “шаблон” означает стандартную, повторяющуюся сущность. Шаблоны не пред¬
назначены для изучения и выражения новых принципов разработки программного
обеспечения, скорее, наоборот. Они призваны систематизировать существующие зна¬
ния, идиомы и принципы. Чем шире они используются, тем лучше.Следовательно, шаблоны GRASP (с которыми мы вскоре познакомимся) не содер¬
жат новых идей, а лишь постулируют широко используемые базовые принципы.3 Родоначальником использования шаблонов в процессе проектирования можно считать
Кристофера Александера (Christopher Alexander) [2]. При разработке программного обеспече¬
ния их впервые начали применять в 80-х годах Кент Бек (Kent Beck) и Вард Каннингхем (Ward
Cunningham) [8, 11].
308 Часть III. Первая итерация фазы развития — основыКнига шаблонов проектирования GoFИдея именования шаблонов выдвинута в середи¬
не 1980-х годов Кентом Беком (Kent Beck), одним из
авторов экстремального программирования.4 Однако
в 1994 году была достигнута главная веха в истории
создания книг о шаблонах и объектно-ориентирован¬
ном проектировании программных систем — вышла в
свет книга [58]5. В книге, которую считают “библией
проектирования” на основе шаблонов, описано 23 ша¬
блона объектно-ориентированного проектирования, в
том числе шаблоны Strategy и Adapter. Эти 23 шаблона
были предложены четырьмя людьми, поэтому получи¬
ли название шаблонов проектирования “союза четы¬
рех”, или шаблонов GoF (Gang of Four).6Эта книга рассчитана на специалистов, обладаю¬
щих хорошими знаниями в области объектно-ориенти¬
рованного проектирования и программирования, и содержит много примеров кода
на C++.В последующих главах данной книги, особенно в главах 26, 35 и 38, описано мно¬
жество шаблонов проектирования GoF и примеров их применения.Главной задачей данной книги является изучение шаблонов GRASP и GoF.GRASP: шаблоны или принципы?Шаблоны GRASP описывают 9 базовых принципов или строительных блоков
объектно-ориентированного проектирования. У читателя может возникнуть вопрос:
“Что же все-таки описывает GRASP: шаблоны или принципы?”. Ответ на этот вопрос
в контексте разработки объектно-ориентированных систем очень удачно сформули¬
рован в [58].“Шаблон одного разработчика — это простейший строительный блок другого”.В этом утверждении ничего не говорится об именах шаблонов, а лишь делается
акцент на их практическом использовании. С этой точки зрения шаблоны являются
основным механизмом для накопления и повторного использования полезных прин¬
ципов разработки программного обеспечения.4 Первое упоминание о шаблонах связана с именем Кристофера Александера (Cristopher
Alexander) в контексте архитектурных шаблонов. Шаблоны для программирования придуманы
Кентом Беком на основе идеи архитектурных шаблонов Александера, а затем развиты Беком и
Уордом Канингемом (Ward Cunningham) в компании Tektronix [8, 11].5 Датой выхода книги считается 1995 год, однако, она увидела свет в 1994 году.6 Тонкий намек на китайскую политику.
Глава 17. GRASP: проектирование объектов на основе распределения обязанностей 30917.7. Где мы находимся?Таким образом, в этой главе описаны следующие основные составляющие объек¬
тно-ориентированного проектирования.1. Итеративный процесс разработки, определяющий связь созданных ранее арте¬
фактов с моделями объектно-ориентированного проектирования.2. RDD как главный принцип объектного проектирования, представляющий раз¬
рабатываемую систему как сообщество взаимодействующих объектов.3. Шаблоны как способ именования и объяснения идей объектно-ориентирован¬
ного проектирования. Шаблоны GRASP определяют базовые принципы распре¬
деления обязанностей, а шаблоны GoF— более сложные идеи проектирования.
Шаблоны можно применять как на этапе моделирования, так и на стадии на¬
писания кода.4. Язык UML для визуального моделирования объектно-ориентированного программ¬
ного решения, построенного на основе шаблонов GRASP и GoF.Теперь самое время перейти к рассмотрению деталей объектного проектирова¬
ния.17.8. Небольшой пример объектного
проектирования на основе шаблонов GRASPВ следующих разделах детально описаны шаблоны GRASP. Но для начала рассмо¬
трим небольшой пример применения этих шаблонов для создания программной мо¬
дели игры “Монополия”. Всего в состав GRASP входит 9 шаблонов, но в данном при¬
мере мы ограничимся следующим подмножеством.■ Creator■ Information Expert■ Low Coupling■ Controller■ High CohesionШаблон CreatorПроблема: какой класс должен отвечать за создание объекта Square?Одна из важнейших проблем при объектно-ориентированном проектировании —
кто создает объект X? Другими словами, какому классу следует назначить соответству¬
ющую обязанность? Например, какой класс должен отвечать за создание программ¬
ного объекта Square (клетка) в игре “Монополия”? Теоретически эту обязанность
можно назначить любому классу, но каким должен быть правильный выбор и почему?Возможно, создателем этого объекта должен стать некий произвольный объект
Dog (собака)? Вовсе нет. Он должен заниматься своими костями. Вы спросите, поче¬
му? Дело в том, и это очень важный момент, что такое распределение обязанностей
не свойственно объекта данной предметной области. Подобное проектное решение
310 Часть III. Первая итерация фазы развития — основыне позволит сократить брешь в представлении реальных объектов предметной об¬
ласти и соответствующих им программных объектов. Данный вопрос автор задавал
тысячам разработчиков во всем мире (в буквальном смысле) и получал однозначный
ответ: “Объекты Square должен создавать объект Board (доска).” Этот интуитивный
ответ свидетельствует о том, что зачастую разработчики объектно-ориентированно¬
го программного обеспечения (за исключением описанных ниже случаев) предпочи¬
тают назначать обязанность создания элементов их контейнерам (в данном случае
объект Board является контейнером для объектов Square).Кстати, почему этим объектам мы не присвоили имена АВ324 и ZC17? Ответ на
этот вопрос кроется в необходимости сократить разрыв между представлением объек¬
тов в предметной области и программной системе. Осмысленные имена приближают
модель проектирования к модели предметной области.Теперь можно определить шаблон проектирования Creator.7CreatorКто отвечает за создание нового экземпляра некоторого класса А?
Назначить классу В обязанность создавать экземпляры класса А, если
выполняется одно (или несколько) из следующих условий.■ Класс В содержит (contains) или агрегирует (aggregate) объекты А.■ Класс В записывает (records) экземпляры объектов А.■ Класс В активно использует (closely uses) объекты А.■ Класс В обладает данными инициализации (has the initializing data) для
объектов А.Шаблоны используются в процессе распределения обязанностей. Рассмотрим, как
применить этот шаблон в реальной ситуации.Во-первых, в данном случае А и В являются программными объектами, а не объек¬
тами из модели предметной области. Сначала нужно попытаться найти программный
объект В, удовлетворяющий перечисленным выше условиям. А что делать, если ника¬
кие программные классы еще не определены? В этом случае необходимо обратиться
к модели предметной области.Поскольку в момент решения проблемы создания объекта Square программные
классы еще не определены, обратимся к модели предметной области на рис. 17.3 и
зафиксируем для себя, объекты Square содержатся в объекте Board. Эта модель от¬
ражает концептуальный, а не программный ракурс системы, однако ее можно спро¬
ектировать на модель реализации и предположить, что программный объект Board
должен содержать программные объекты Square. Тогда, согласно шаблону Creator,
объект Board должен создавать объекты Square. Объекты Square всегда агрегиру¬
ются объектом Board, поэтому последний управляет их созданием и разрушением.
Таким образом, объекты Square состоят в отношении агрегации с объектом Board.Напомним, что в контексте гибкого проектирования статические и динамические
модели создаются параллельно. Следовательно, это проектное решение необходи¬
мо одновременно отразить и на диаграмме классов и на диаграмме взаимодействия
(рис. 17.14 и 17.15). Из рис. 17.14 видно, что при создании объекта Board сразу же
создаются и объекты Square. Для простоты на этой диаграмме не показан цикл соз¬
дания 40 экземпляров клеток.7 Ниже описаны другие шаблоны создания объектов, в том числе Concrete Factory и Abstract
Factory.Название
Проблема
Решение
(рассматри¬
ваемое как
совет)
Глава 17. GRASP: проектирование объектов на основе распределения обязанностейРис. 17.3. Модель предметной области игры “Монополия * на первой итерации\<JWс\Рис. 17.4. Применение шаблона Creator для динамической модели(jofcrAж.|» АW—- ^* * *Рис. 17.5. В модели предметной области отражена ассоциация агрегации для
объектов Board и Square. Применение шаблона Creator для статической модели
312 Часть III. Первая итерация фазы развития — основыШаблон Information ExpertПроблема: какой класс обладает информациейоб объекте Square?Шаблон Information Expert (который зачастую
сокращенно называют шаблоном Expert) является
одним из базовых принципов распределения обя¬
занностей при объектном проектировании. Допустим, некоторому объекту необходи¬
мо обратиться к конкретному объекту Square по имени. Какой класс должен обладать
ключевой информацией об объекте Square? В данном случае речь идет об обязанно¬
сти знания, но шаблон Expert также связан с распределением обязанностей действия.Эту обязанность тоже можно присвоить любому объекту, но к какому выводу при¬
дет большинство разработчиков и почему? Как и в случае шаблона Creator, большин¬
ство разработчиков назначат эту обязанность объекту Board. Такое решение кажется
очевидным, но оно имеет совершенно конкретное объяснение. Ниже будут приведе¬
ны более сложные примеры применения этого шаблона.Шаблон Information Expert сводится к следующему.Название Information ExpertПроблема Каков базовый принцип распределения обязанностей между объектами?Решение Назначить эту обязанность тому классу, который обладает достаточной
информацией для ее выполнения.Для выполнения этой обязанности объект должен обладать информацией о соб¬
ственном состоянии, его окружении, унаследованной информацией и т.п. В данном
случае каждую конкретную клетку на поле может представлять объект, обладающей
информацией обо всех клетках. Из рис. 17.5 видно, что таким объектом является
Board, агрегирующий все программные объекты Square. Следовательно, объект
Board обладает достаточной информацией для выполнения этой обязанности. На
рис. 17.6 показан результат применения шаблона Expert в данном контексте.А * l'CWc<k11v* VНчЧРис. 17. 6. Применение шаблона ExpertИзучив следующий шаблон, Low Coupling, вы поймете, почему шаблон Expert счи¬
тают ключевым принципом ООП.Шаблон Low CouplingВопрос: почему все же Board, а не Dog?Согласно шаблону Expert, обязанность обладания информацией о конкретном
объекте Square возлагается на объект Board, поскольку он содержит данные обо
Глава 17. GRASP: проектирование объектов на основе распределения обязанностей 313всех подобных объектах (значит, является информационным экспертом). Однако чем
мотивирована подобная рекомендация шаблона Expert?Ответ кроется в принципе Low Coupling (низкая степень связывания). Нефор¬
мально выражаясь, степень связанности (coupling) — это мера связанности одного эле¬
мента с другими. Под связыванием понимается обладание информацией или любая за¬
висимость. При высокой степени связывания изменение независимого объекта влечет
за собой изменение зависимого. Например, подкласс тесно связан с суперклассом. Если
объект А вызывает операции объекта В, значит, он связан со службами объекта В.Принцип минимизации степени связывания используется во многих контекстах
разработки программного обеспечения. Это одна из принципиальных задач построе¬
ния программных систем. В терминах объектного проектирования и распределения
обязанностей его можно описать следующим образом.Название Low CouplingПроблема Как уменьшить влияние вносимых изменений на другие объекты?Решение Минимизировать степень связывания в процессе распределения обязан¬
ностей. Этот принцип используется для оценки различных альтернатив.Принцип Low Coupling используется для оценки существующего проектного реше¬
ния или выбора решения из нескольких вариантов — при прочих равных условиях
следует предпочитать проектное решение с более низкой степенью связывания.Например, из рис. 17.5 видно, что объект Board содержит много объектов
Square. Почему не присвоить обязанность знания об объектах Square некоторому
произвольному классу Dog? Рассмотрим эти альтернативы в терминах шаблона Low
Coupling. Если класс Dog содержит метод getSquare (), как показано на рис. 17.7,
значит, он должен взаимодействовать с объектом Board для получения информации
о коллекции объектов Square. Вероятно, эти данные хранятся в объекте-коллекции
Мар, с помощью которого можно извлекать информацию по ключу. Тогда объект Dog
сможет получить доступ к этим данным по ключу name и вернуть информацию о кон¬
кретном объекте Square.• Do?X%T>«4»Рис. 17.7. Оценка степени связывания объектов в конкретном проектном решении
314 Часть III. Первая итерация фазы развития — основыДавайте оценим степень связывания объектов при данном неудачном проектном
решении с объектом Dog по сравнению с исходным проектным решением, при ко¬
тором метод getSquare () принадлежал объекту Board. При использовании объекта
Dog он наряду с Board должен обладать информацией об объекте Square (оба объек¬
та связаны со Square), а в исходном проектном решении с объектом Square связан
только объект Board. Поэтому в исходном проектном решении степень связывания
объектов ниже, чем в в случае использования объекта Dog.Чем полезен принцип минимизации связывания? Или, другими словами, почему
целесообразно минимизировать степень связывания объектов и влияние изменений
одних объектов на другие? Дело в том, что этот принцип позволяет сэкономить время,
усилия и уменьшить количество ошибок при модификации программной системы. Этот крат¬
кий ответ играет очень важную роль при разработке и поддержке программного обе¬
спечения.Важное замечание - шаблон Expert поддерживает принцип
минимизации связывания.Вспомним главный принцип шаблона Expert. Он сводится к поддержке шаблона
Low Coupling. Согласно шаблону Expert, необходимо определить объект, облада¬
ющий информацией для выполнения нужной обязанности (в рассматриваемом
примере таким объектом является Board).Если эту обязанность присвоить другому объекту (например, Dog), повышается
степень связывания объектов. При этом больший объем информации передается
посторонним объектам, в частности объекту Dog.Применение UML. Обратите внимание на некоторые элементы UML на диаграмме
последовательностей, показанной на рис. 17.7.■ Переменная sqs, которой присваивается возвращаемое значение метода get-
AllSquares (), используется также для именования объекта sqs :Map<Square> —
коллекции типа Мар, содержащей объекты Square.■ Переменная s в начальном сообщении getSquare () и переменная s в последу¬
ющем сообщении get () указывают на один и тот же объект.■ Выражение s = get (name): Square означает, что типом переменной s является
ссылка на экземпляр класса Square.Шаблон ControllerВ архитектуре типичного приложения содержатся уровни интерфейса пользо¬
вателя и логики приложения. Исполнитель, например, человек-наблюдатель игры
“Монополия”, генерирует событие интерфейса пользователя, например, щелчок мы¬
шью, инициирующий игру. Программные объекты интерфейса пользователя, напри¬
мер, оконный объект JFrame или объект кнопки JButton в Java, должны отреагиро¬
вать на действие пользователя.Согласно описанному в главе 13 принципу Model-View-Separation, объекты интер¬
фейса не должны реализовывать бизнес-логику приложения, например, вычислять
ходы пользователя. Они должны делегировать запрос (направить его другому объек¬
ту) на уровень объектов предметной области.
Глава 17. GRASP: проектирование объектов на основе распределения обязанностей 315Шаблон Controller (контроллер) позволяет ответить на следующий простой во¬
прос: какой объект за пределами уровня интерфейса пользователя (UI) должен по¬
лучать сообщения от уровня UI?Согласно диаграмме последовательностей, показанной на рис. 17.8, ключевой си¬
стемной операцией является play Game. Наблюдатель каким-то образом генерирует
запрос на выполнение этой операции (например, щелкнув на соответствующей кноп¬
ке в окне), а система должна отреагировать на него.На рис. 17.9 детализированы операции, выполняемые при использовании графи¬
ческого интерфейса Java Swing.8 При щелчке на кнопке объект JButton отправляет
сообщение actionPerformed некоторому объекту, зачастую самому объекту окна
JFrame (рис. 17.9). Затем, и это ключевой вопрос, объект JFrame должен преобра¬
зовать это сообщение в другое, семантически более значимое, например play Game
(в соответствии с системной диаграммой последовательностей), и делегировать его
выполнение объекту уровня предметной области.Улавливаете ли вы взаимосвязь между системными операциями на системной
диаграмме последовательностей и детализированным проектным решением? Это
очень важно.Таким образом, шаблон Controller позволяет ответить на сакраментальный вопрос
ООП: как связать уровни интерфейса пользователя и логики приложения? Должен
ли объект Board получать сообщение playGame непосредственно от уровня интер¬
фейса пользователя?Некоторые методы ООА/П предусматривают создание объекта controller на
уровне логики приложения, отвечающего за получение и управление обработкой за¬
просов.8 Аналогичные объекты, сообщения и шаблоны взаимодействия применимы для .NET,
Python и других парадигм программирования.Рис. 17.8. Системная диаграмма последовательностей для игры
“Монополия ”. Обратите внимание на операцию playGame
316 Часть III. Первая итерация фазы развития — основы-?• te»' шК \ Ша«*■штиг6е*г4?
S\g*rx. X
b\l!„уЦА«д » \Ьт\^ъшт
 1■гЗ£2)—'Рис. 17.9. Какой объект является контроллером для системной операции playGame?Шаблон Controller можно описать таким образом.Название ControllerПроблема Кто должен отвечать за получение и координацию выполнения систем¬
ных операций, поступающих от уровня интерфейса пользователя?Решение Присвоить эту обязанность классу, удовлетворяющему одному из следу¬
ющих условий.■ Класс представляет всю систему в целом, корневой объект, устрой¬
ство или важную подсистему (внешний контроллер).■ Класс представляет сценарий некоторого прецедента, в рамках кото¬
рого выполняется обработка этой системной операции (контроллер
прецедента или контроллер сеанса).'Рассмотрим указанные варианты.Вариант 1а. Класс представляет всю систему в целом или корневой объект. В роли
такого объекта может выступать MonopolyGame.Вариант 16. Класс представляет устройство, на котором работает данная про¬
граммная система. Этот вариант относится к специализированным аппаратным сред¬
ствам, например, телефону или кассовому аппарату (программный класс Phone или
CachMachine), и в данном случае неприменим.Вариант 2. Класс представляет сценарий прецедента или сеанс. Системная опе¬
рация playGame выполняется в рамках прецедента Игра Монополия. В роли такого
класса может выступать программный класс PlayMonopolyGameHandler (при исполь¬
зовании этой версии объектного решения к именам классов добавляется суффиксHandler или Session)Вариант 1а применим в том случае, когда в системе используется лишь несколько
системных операций. На рис. 17.10 показано проектное решение, основанное на ша¬
блоне Controller.
Глава 17. GRASP: проектирование объектов на основе распределения обязанностей 317Рис. 17.10. Использование класса MonopolyGame в контексте шаблона Controller
для связи уровня UI с программными объектами уровня предметной областиШаблон HighCohesionС учетом шаблона Controller рассмотрим следую¬
щую диаграмму. Детальное проектное решение для
этого случая будет приведено в следующей главе, а
сейчас остановимся на двух противоположных подхо¬
дах, проиллюстрированных на рис. 17.11.В приведенном сверху проектном решении всю ра¬
боту выполняет сам объект MonopolyGame, а в ситуации, показанной снизу, он делеги¬
рует запрос play Game и контролирует его выполнение. Неформально: зацепление (cohe¬
sion) в контексте проектирования программных систем представляет меру связанности
операций одного программного элемента и выполняемый им объем работы.???1 0 >Рис. 17.11. Проектные решения с разным уровнем зацепления
318 Часть III. Первая итерация фазы развития — основыГрубо говоря, объект Big, содержащий 100 методов и 2000 строк программного
кода, выполняет гораздо больше работы, чем объект Small, содержащий 10 методов
и 200 строк кода. Если 100 методов объекта Big охватывают широкий спектр обя¬
занностей (например, связь с базой данных и генерирование случайных чисел), то
этот объект обладает более низким зацеплением, чем объект Small. Таким образом,
индикатором уровня зацепления объекта является совокупность объема кода и его
взаимосвязанности.Слабое (плохое) зацепление означает, что объект не просто выполняет много ра¬
боты, а взаимодействует при этом со многими другими объектами. Важно отметить,
что взаимодействие с другими объектами приводит к сильному связыванию (что
тоже очень плохо). Слабое зацепление и высокая степень связывания зачастую идут
рука об руку.Проектное решение, приведенное на рис. 17.11, сверху, хуже, чем показанное сни¬
зу, поскольку сверху всю работу выполняет объект Monopoly Game, а не делегирует
обязанности другим объектам. На основе подобных рассуждений можно сформулиро¬
вать принцип High Cohesion (высокое зацепление), позволяющий оценить качество
проектного решения: при прочих равных условиях следует отдавать предпочтение
проектному решению с сильным зацеплением.Название High CohesionПроблема Как обеспечить сфокусированность обязанностей объектов, их управ¬
ляемость и ясность, а заодно выполнение принципа Low Coupling?Решение Обеспечивать высокий уровень зацепления в процессе распределенияобязанностей. Этот принцип нужно использовать для оценки различ¬
ных альтернатив.17.9. Применение шаблонов GRASP для
объектного проектированияАббревиатура GRASP означает General Responsibility Assignment Software Patterns
(Общие шаблоны распределения обязанностей в программных системах)9. Такая аб¬
бревиатура очень символична, поскольку подчеркивает важность изучения этих прин¬
ципов для успешного проектирования объектно-ориентированного приложения10.Очень важно понимать и уметь применять эти шаблоны при создании диаграмм
взаимодействия, поскольку неопытный разработчик объектно-ориентированного
программного обеспечения должен как можно скорее освоить базовые принципы.
Эти принципы составляют основу проектного решения.Существует 9 шаблонов GRASP.Creator Controller Pure FabricationInformation Expert High Cohesion IndirectionLow Coupling Polymorphism Protected VariationsВ остальных разделах данной главы детально описаны первые 5 шаблонов, а
остальные 4 вводятся в главе 25.9 На самом деле следовало бы писать “шаблоны GRAS”, но “шаблоны GRASP” звучит лучше.10 В переводе с английского “grasp” означает “схватывать”, “постигать”.— Примеч. перев.
Глава 17. GRASP: проектирование объектов на основе распределения обязанностей 31917.10. Шаблон CreatorПроблема: кто должен отвечать за создание нового экземпляра некоторого класса?Создание объектов в объектно-ориентированной системе является одним из наи¬
более стандартных видов деятельности. Следовательно, при назначении обязанно¬
стей, связанных с созданием объектов, полезно руководствоваться некоторым основ¬
ным принципом. Правильно распределив обязанности при проектировании, можно
создать слабо связанные независимые компоненты с возможностью их дальнейшего
использования, упростить их, а также обеспечить инкапсуляцию данных и их повтор¬
ное использование.Решение: назначить классу В обязанность создавать экземпляры класса А, если
выполняется одно из следующих условий.11■ Класс В содержит (contains) или агрегирует (aggregate) объекты А.■ Класс В записывает (records) экземпляры объектов А.■ Класс В активно использует (closely uses) объекты А.■ Класс В обладает данными инициализации (has the initializing data), которые будут
передаваться объектам А при их создании (т.е. при создании объектов А класс
В является экспертом).Класс В — создатель (creator) объектов А.Если выполняется несколько из этих условий, то лучше использовать класс В, агре-
гирующий или содержащий класс А.Пример. Кто в POS-системе должен отвечать за создание нового экземпляра объек¬
та SalesLineltem? В соответствии с шаблоном Creator, необходимо найти класс,
агрегирующий, содержащий и т.д. экземпляры объектов SalesLineltem. Рассмотрим
фрагмент модели предметной области, представленной на рис. 17.12.Рис. 17.12. Фрагмент модели предметной области11 Ниже описаны другие шаблоны создания объектов, в том числе Concrete Factory и Abstract
Factory.
320 Часть III. Первая итерация фазы развития — основыПоскольку объект Sale содержит (фактически — агрегирует) несколько объектов
SalesLineltem, согласно шаблону Creator, он является хорошим кандидатом для вы¬
полнения обязанности, связанной с созданием экземпляров объектов SalesLineltem.
Такой подход приводит к необходимости разработки взаимодействия объектов, пока¬
занного на следующей диаграмме (рис. 17.13).I IРис. 17.13. Создание экземпляра объекта SalesLineltemПри таком распределении обязанностей требуется, чтобы в объекте Sale был
определен метод makeLineltem. Рассмотрение и распределение обязанностей выпол¬
нялись в процессе создания диаграммы взаимодействий. Затем полученные резуль¬
таты могут быть реализованы в конкретных методах, помещенных в раздел методов
диаграммы классов.Обсуждение. Шаблон Creator определяет способ распределения обязанностей,
связанный с процессом создания объектов. В объектно-ориентированных системах
эта задача является одной из наиболее распространенных. Основным назначением
шаблона Creator является выявление объекта-создателя, который при возникновении
любого события должен быть связан со всеми созданными им объектами. При таком
подходе обеспечивается низкая степень связанности.Целое агрегирует свои части, контейнер хранит свое содержимое, регистратор
ведет учет. Все эти взаимосвязи являются очень распространенными способами
взаимодействия классов в диаграмме классов. В шаблоне Creator определяется, что
внешний контейнер или класс-регистратор — это хорошие кандидаты на выполнение
обязанностей, связанных с созданием сущностей, которые они будут содержать или
регистрировать. Конечно, это утверждение является лишь рекомендацией.Обратите внимание, что при рассмотрении шаблона Creator возникает понятие
композиции (composition). Композитный объект можно создавать по частям.В некоторых случаях в качестве создателя выбирается класс, который содержит
данные инициализации, передаваемые объекту во время его создания. На самом деле
это пример использования шаблона Expert. В процессе создания инициализируемые
данные передаются с помощью метода инициализации некоторого вида, такого как
конструктор языка Java с параметрами. Предположим, что при создании экземпляр
объекта Payment нужно инициализировать с использованием общей суммы, содер¬
жащейся в объекте Sale. Поскольку объекту Sale эта сумма известна, он является
Глава 17. GRASP: проектирование объектов на основе распределения обязанностей 321кандидатом на выполнение обязанности, связанной с созданием экземпляра объекта
Payment.Когда не следует применять шаблон. Зачастую создание экземпляра — это до¬
статочно сложная операция, выполняемая при реализации некоторого условия на
основе каких-либо внешних свойств. В этом случае предпочтительнее использовать
шаблон Factory (Фабрика) [58] и делегировать обязанность создания экземпляров
вспомогательному классу. Шаблон Factory описывается в главе 26.Преимущества■ Поддерживается шаблон Low Coupling (рассматриваемый ниже), способствую¬
щий снижению затрат на сопровождение и обеспечивающий возможность по¬
вторного использования созданных компонентов в дальнейшем. Применение
шаблона Creator не повышает степени связанности, поскольку созданный
(created) класс, как правило, оказывается видимым для класса-создателя посред¬
ством имеющихся ассоциаций.Связанные шаблоны и принципы■ Low Coupling.■ Concrete Factory и Abstract Factory.■ В [17] описывается шаблон, позволяющий определить объекты-агрегаты, кото¬
рые поддерживают инкапсуляцию составляющих их компонентов.17.11. Шаблон Information Expert (или Expert)Проблема: каков наиболее общий принцип распределения обязанностей между
объектами при объектно-ориентированном проектировании?В модели системы могут быть определены десятки или сотни программных клас¬
сов, а в приложении может потребоваться выполнение сотен или тысяч обязанно¬
стей. Во время объектно-ориентированного проектирования при формулировке
принципов взаимодействия объектов необхо)ц1МО распределить обязанности между
классами. При правильном выполнении этой задачи система становится гораздо про¬
ще для понимания, поддержки и расширения. Кроме того, появляется возможность
повторного использования уже разработанных компонентов в последующих прило¬
жениях.Решение: назначить обязанность информационному эксперту — классу, у которого
имеется информация, требуемая для выполнения обязанности.Пример. В приложении POS-системы NextGen некоторому классу необходимо
знать общую сумму продажи.Начинайте распределение обязанностей с их четкой формулировки.С этой точки зрения можно сформулировать следующее утверждение.Какой класс должен знать общую сумму продажи?Согласно шаблону Information Expert, нужно определить, объекты каких классов
содержат информацию, необходимую для вычисления общей суммы.11 Зак. 3357
322 Часть III. Первая итерация фазы развития — основыТеперь возникает ключевой вопрос: на основе какой модели нужно анализировать
информацию — модели предметной области или проектирования? Модель предмет¬
ной области иллюстрирует концептуальные классы из предметной области системы,
а в модели проектирования показаны программные классы.Ответ на этот вопрос сводится к следующему.1. Если в модели проектирования имеются соответствующие классы, в первую
очередь, следует использовать ее.2. В противном случае нужно обратиться к модели предметной области и поста¬
раться уточнить ее для облегчения создания соответствующих программных
классов.Предположим, мы находимся в самом начале этапа проектирования, когда модель
проектирования представлена в минимальном объеме. Следовательно, кандидатуру
на роль информационного эксперта следует искать в модели предметной области.
Вероятно, на эту роль подойдет концептуальный класс Sale. Тогда в модель проек¬
тирования нужно добавить соответствующий программный класс под именем Sale и
присвоить ему обязанность вычисления общей стоимости, реализуемую с помощью
вызова метода get Total. При таком подходе сокращается разрыв между организаци¬
ей программных объектов и соответствующих им понятий из предметной области.Чтобы рассмотреть этот пример подробнее, обратимся к фрагменту модели пред¬
метной области, представленному на рис. 17.14.Рис. 17.14. Ассоциации объекта SaleКакая информация требуется для вычисления общей суммы? Необходимо узнать
стоимость всех проданных товаров SalesLineltem и просуммировать эти про¬
межуточные суммы. Такой информацией обладает лишь экземпляр объекта Sale.
Следовательно, с точки зрения шаблона Information Expert объект Sale подходит
для выполнения этой обязанности, т.е. является информационным экспертом (informa¬
tion expert).Как уже упоминалось, подобные вопросы распределения обязанностей зачастую
возникают при создании диаграмм взаимодействий. Представьте, что вы приступили
к работе, начав создание диаграмм для распределения обязанностей между,объекта¬
ми. Принятые решения иллюстрируются на фрагменте диаграммы взаимодействий,
представленном на рис. 17.15.
Глава 17. GRASP: проектирование объектов на основе распределения обязанностей 323t=getTotal: SaleНовый методSaletimegetTotal()Рис. 17.15. Фрагмент диаграммы взаимодействия и диаграммы классовОднако на данном этапе выполнена не вся работа. Какая информация требу¬
ется для вычисления промежуточной суммы элементов продажи? Необходимы
значения атрибутов SalesLineltem.quantity и SalesLineltem.price. Объекту
SalesLineltem известно количество товара и известен связанный с ним объект
ProductDescription. Следовательно, в соответствии с шаблоном Expert, проме¬
жуточную сумму должен вычислять объект SalesLineltem. Другими словами, этот
объект является информационным экспертом.В терминах диаграмм взаимодействий это означает, что объект Sale должен пере¬
дать сообщения getSubtotal каждому объекту SalesLineltem, а затем просуммиро¬
вать полученные результаты. Этот процесс проиллюстрирован на рис. 17.16.Интерактивная обработка
элементов коллекцииo'* —►" -ot=getTotal: Sale1 *: st = getSubtotallineltems[i]:SalesLineltemSalegetTotal()Новый методSalesLineltemquantitygetSubtotal()Рис. 17.16. Вычисление общей суммы продажиДля выполнения обязанности, связанной со знанием и предоставлением промежу¬
точной суммы, объекту SalesLineltem должна быть известна стоимость товара.В данном случае в качестве информационного эксперта будет выступать объект
ProductDescription.Результаты проектирования представлены на рис. 17.17.В завершение можно сказать следующее. Для выполнения обязанности “знать и
предоставлять общую сумму продажи трем объектам классов” были следующим обра¬
зом присвоены три обязанности.Класс проектированияОбязанностьSaleЗнание общей суммы продажиSalesLineltemЗнание промежуточной суммы для данного товараProductDescriptionЗнание цены товара
324 Часть III. Первая итерация фазы развития — основыt=getTotal1.1:р:=getPrice():Product
DescriptionSaletimegetTotal()SalesLineltemquantitygetSubtotal()Новый методРис. 17.17. Вычисление общей суммы продажи (второй способ)Рассмотрение и распределение обязанностей выполнялись в процессе создания
диаграммы взаимодействий. Затем полученные результаты могут быть реализованы в
разделе методов диаграммы классов.При назначении обязанностей, согласно шаблону Expert, был применен следую¬
щий принцип: обязанности связываются с тем объектом, который имеет информа¬
цию, необходимую для их выполнения.Обсуждение. Шаблон Information Expert часто используется при распределении
обязанностей. В нем определены основные принципы, которые уже давно исполь¬
зуются в объектно-ориентированном проектировании. Шаблон Expert не содержит
неясных или запутанных идей и отражает обычный интуитивно понятный подход.
Он заключается в том, что объекты осуществляют действия, связанные с имеющейся
у них информацией.Обратите внимание, что для выполнения обязанности зачастую требуется инфор¬
мация, распределенная между различными классами или объектами. Это предпола¬
гает, что должно существовать много “частичных” экспертов, взаимодействующих
при выполнении общей задачи. Например, для вычисления общей суммы продажи в
конечном счете необходимо взаимодействие трех классов. Если информация распре¬
делена между различными объектами, то при выполнении общей задачи они должны
взаимодействовать с помощью сообщений.Применение шаблона Expert приводит к тому, что объекты выполняют операции
точно так, как они выполняются сущностями реального мира. Именно эти сущно¬
сти и моделируют объекты. Питер Код называет это стратегией “Сделай сам” (“Do
It Myself’) [34]. Например, в реальном мире без применения электромеханических
устройств покупка не сможет сообщить о своей стоимости. Она представляет собой
неодушевленное понятие. Каждый из покупателей вычисляет сумму покупки самосто¬ProductDescriptiondescriptionpriceitemIDgetPrice()
Глава 17. GRASP: проектирование объектов на основе распределения обязанностей 325ятельно. Однако в мире объектно-ориентированного программного обеспечения все
программные объекты являются живыми и одушевленными, поэтому могут выпол¬
нять обязанности и осуществлять действия. В основном они выполняют действия,
связанные с известной им информацией. В объектно-ориентированном проектирова¬
нии этот принцип называется “оживлением” (animation) (программные объекты по¬
добны “живым” персонажам мультипликационных фильмов).Шаблон Information Expert, как и многие другие понятия объектной технологии,
имеет соответствующую аналогию в реальном мире. Обычно мы распределяем обя¬
занности между теми служащими, у которых имеется необходимая для выполнения
поставленной задачи информация. Например, кто в коммерческом предприятии дол¬
жен нести ответственность за создание отчета о прибыли и убытках? Тот из служа¬
щих, кто имеет доступ ко всей информации, необходимой для создания такого отче¬
та. Возможно, лучше всего для выполнения этой обязанности подойдет руководитель
финансового отдела предприятия. Программные объекты взаимодействуют между со¬
бой и обмениваются информацией так же, как люди. Начальник финансового отдела
компании может запросить требуемые данные у бухгалтеров, работающих со счетами
по дебиторской и кредиторской задолженности, чтобы составить отдельные отчеты
по кредиту и дебиту.Когда не следует применять шаблон. В некоторых ситуациях применение ша¬
блона Expert нежелательно, например, в связи с проблемами со связыванием и заце¬
плением (эти принципы обсуждаются ниже в этой главе).Например, какой объект должен отвечать за сохранение информации о продажах
в базе данных? Безусловно, большая часть подлежащей сохранению информации “из¬
вестна” объекту Sale, а значит, согласно шаблону Expert, на этот класс следует воз¬
ложить обязанность по сохранению. Логическим следствием такого рассуждения яв¬
ляется вывод о том, что каждый объект должен отвечать за сохранение себя в базе
данных. Однако при этом возникают проблемы связывания, зацепления и дублиро¬
вания. В частности, класс Sale должен содержать методы обращения к базе данных,
т.е. быть связан с языком SQL или службами JDBC (Java Database Connectivity). Тогда
этот класс не будет относиться к логике приложения и моделировать “продажу”. При
этом расширяется круг его обязанностей и снижается зацепление. Этот класс должен
быть связан с техническими службами баз данных других подсистем, в частности со
службами JDBC, а не только с программными объектами уровня предметной области.
Кроме того, вероятно, подобная логика будет дублироваться во многих других клас¬
сах, информация о которых подлежит постоянному хранению.Все эти проблемы приводят к нарушению основного архитектурного принци¬
па — проектирования с разделением основных функций системы. Логика приложе¬
ния должна храниться в одном месте (на уровне программных объектов предметной
области), а логика связи с базой данных — в другом (в отдельной подсистеме служб
базы данных). Различные функции не должны реализовываться в одном и том же
компоненте.12Принцип разделения основных функций улучшает показатели связывания и заце¬
пления. С точки зрения этих категорий, класс Sale не должен отвечать за сохране¬
ние информации в базе данных.12 Разделение функций более подробно рассматривается в главе 33.
326 Часть III. Первая итерация фазы развития — основыПреимущества■ Шаблон Expert поддерживает инкапсуляцию. Для выполнения требуемых задач
объекты используют собственные данные. Подобную возможность обеспечи¬
вает также шаблон Low Coupling, применение которого приводит к созданию
более надежных и легко поддерживаемых систем. (Low Coupling является ша¬
блоном GRASP, который будет рассмотрен чуть ниже.)■ Соответствующее поведение системы обеспечивается несколькими классами,
содержащими требуемую информацию. Это приводит к определениям классов,
которые гораздо проще понимать и поддерживать. Кроме того, поддерживает¬
ся шаблон High Cohesion (рассматриваемый ниже в этой главе).Связанные шаблоны■ Low Coupling■ High CohesionДругие названия и аналогичные принципы. “Хранение обязанностей вместе с
данными”, “Кто знает, тот и выполняет”, “Сделай сам”, “Размещайте службы вместе
с их атрибутами”.17.12. Шаблон Low CouplingПроблема: как обеспечить зависимость, незначительное влияние изменений и по¬
высить возможность повторного использования? —^Степень связанности (coupling) — это мера, определяющая насколько жестко один
элемент связан с другими элементами, либо каким количеством данных о других эле¬
ментах он обладает. Элемент с низкой степенью связанности (или слабым связывани¬
ем) зависит от не очень большого числа других элементов. Выражение “очень много”
зависит от контекста, однако необходимо провести его оценку.Класс с высокой степенью связанности (или жестко связанный) зависит от мно¬
жества других классов. Однако наличие таких классов нежелательно, поскольку оно
приводит к возникновению следующих проблем.■ Изменения в связанных классах приводят к локальным изменениям в данном
классе.■ Затрудняется понимание каждого класса в отдельности.■ Усложняется повторное использование, поскольку для этого требуется дополни¬
тельный анализ классов, с которыми связан данный класс.Решение: распределить обязанности таким образом, чтобы степень связанности
оставалась низкой.Пример. Рассмотрим следующий фрагмент диаграммы классов для приложения
NextGen.PaymentRegisterSaleПредположим, что необходимо создать экземпляр класса Payment и связать его
с объектом Sale. Какой класс должен отвечать за выполнение этой операции? Пос¬
кольку в реальной предметной области регистрация объекта Payment выполняется
объектом Register, в соответствии с шаблоном Creator, объект Register является
Глава 17. GRASP: проектирование объектов на основе распределения обязанностей 327хорошим кандидатом для создания объекта Payment. Затем экземпляр объекта
Register должен передать сообщение addPayment объекту Sale, указав в качестве
параметра новый объект Payment. Приведенные рассуждения отражены на фрагмен¬
те диаграммы взаимодействий, представленной на рис. 17.18.Рис. 17.18. Новый экземпляр объекта Payment создается с помощью объекта RegisterТакое распределение обязанностей предполагает, что класс Register обладает
знаниями о данных класса Payment (т.е. связывается с ним).Обратите внимание на обозначения, принятые в языке UML. Экземпляру объекта
Payment присвоено явное имя р, чтобы его можно было использовать в качестве па¬
раметра сообщения 2.Альтернативный способ создания объекта Payment и его связывания с объектом
Sale показан на рис. 17.19.Рис. 17.19. Новый экземпляр объекта Payment создается с помощью объекта SaleКакой из методов проектирования, основанный на распределении обязанностей,
обеспечивает более низкую степень связывания? В обоих случаях предполагается,
что в конечном итоге объекту Sale должно быть известно о существовании объек¬
та Payment. При использовании первого способа, когда объект Payment создается с
помощью объекта Register, между этими двумя объектами добавляется новая связь,
тогда как второй способ степень связывания объектов не усиливает. С точки зрения
числа связей между объектами, более предпочтительным является второй способ, по¬
скольку в этом случае обеспечивается низкая степень связывания. Приведенная ил¬
люстрация является примером того, как при использовании двух различных шабло¬
нов — Low Coupling и Creator — можно прийти к двум различным решениям.На практике уровень связывания не рассматривается отдельно от других принци¬
пов, сформулированных в шаблонах Expert и High Cohesion. Тем не менее в ша¬
блоне Low Coupling описан один из факторов, с использованием которого можно
значительно улучшить весь проект в целом.
328 Часть III. Первая итерация фазы развития — основыОбсуждение. В шаблоне Low Coupling описывается принцип, о котором нельзя
забывать на протяжении всех стадий работы над проектом. Он является объектом
постоянного внимания. Шаблон Low Coupling представляет собой средство, которое
разработчик применяет при оценке всех принимаемых в процессе проектирования
решений.В объектно-ориентированных языках программирования, таких как C++, Java и
С#, имеются следующие стандартные способы связывания объектов ТуреХ и TypeY.■ Объект ТуреХ содержит атрибут (переменную-член), который ссылается на эк¬
земпляр объекта TypeY или сам объект TypeY.■ Объект ТуреХ вызывает службы объекта TypeY’■ Объект ТуреХ содержит метод, который каким-либо образом ссылается на эк¬
земпляр объекта TypeY или сам объект ТуреХ (обычно это подразумевает исполь¬
зование TypeY в качестве типа параметра, локальной переменной или возвраща¬
емого значения).■ Объект ТуреХ является прямым или непрямым подклассом объекта TypeY.■ Объект TypeY является интерфейсом, а 7)>/^Х"реализует этот интерфейс.Шаблон Low Coupling подразумевает такое распределение обязанностей, которое
не влечет за собой чрезмерное повышение степени связывания, приводящее к отри¬
цательным результатам.Шаблон Low Coupling поддерживает независимость классов, что, в свою очередь,
повышает возможности повторного использования и обеспечивает более высокую
эффективность приложения. Его нельзя рассматривать изолированно от других ша¬
блонов, таких как Expert и High Cohesion. Скорее, он обеспечивает один из основ¬
ных принципов проектирования, применяемых при распределении обязанностей.Подкласс жестко связан со своим суперклассом. Поэтому, принимая решение о
наследовании свойств объектов, следует учитывать, что отношение наследования
повышает степень связанности классов. Например, предположим, объекты необхо¬
димо постоянно хранить в реляционной или объектной базе данных. В этом случае
зачастую создают абстрактный суперкласс PersistentObject, от которого наследуют
свои свойства другие классы. Недостатком такого подхода является жесткое связыва¬
ние объектов с конкретной службой, а преимуществом — автоматическое наследова¬
ние поведения.Не существует абсолютной меры для определения слишком высокой степени свя¬
зывания. Важно лишь понимать степень связанности объектов на текущий момент и
не упустить тот момент, когда дальнейшее повышение степени связанности может
привести к возникновению проблем. В целом, следует руководствоваться таким прин¬
ципом: классы, которые являются достаточно общими по своей природе и с высокой
вероятностью будут повторно использоваться в дальнейшем, должны иметь мини¬
мальную степень связанности с другими классами.Крайним случаем при реализации шаблона Low Coupling является полное отсут¬
ствие связывания между классами. Такая ситуация тоже нежелательна, поскольку
базовой идеей объектного подхода является система связанных объектов, которые
“общаются” между собой посредством передачи сообщений. При слишком частом
использовании принципа слабого связывания система будет состоять из нескольких
изолированных сложных активных объектов, самостоятельно выполняющих все опе¬
рации, и множества пассивных объектов, основная функция которых сводится к хра¬
Глава 17. GRASP: проектирование объектов на основе распределения обязанностей 329нению данных. Поэтому при создании объектно-ориентированной системы должна
присутствовать некоторая оптимальная степень связывания между объектами, позво¬
ляющая выполнять основные функции посредством взаимодействия этих объектов.Когда не следует применять шаблон. Высокая степень связывания с устойчивы¬
ми элементами не представляет проблемы. Например, приложение J2EE можно жест¬
ко связать с библиотеками Java (j ava. util и т.п.), поскольку эти библиотеки широко
распространены и стабильны.Выбери свою игруВысокая степень связывания сама по себе не является проблемой. Проблемой яв¬
ляется жесткое связывание с неустойчивыми в некотором отношении элементами.Важно понимать следующее. Разработчик может обеспечивать гибкость програм¬
мы, реализовывать принцип инкапсуляции и придерживаться принципа слабого свя¬
зывания во многих аспектах системы. Однако без убедительной мотивации не следу¬
ет во что бы то ни стало бороться за уменьшение степени связывания объектов.Разработчики должны выбрать “свою игру”, чтобы снизить степень связывания и
обеспечить инкапсуляцию. При этом особое внимание нужно уделить неустойчивым
или быстро изменяющимся элементам. Например, в проекте NextGen к системе пла¬
нируется подключать различные программы вычисления налоговых платежей (с об¬
щим интерфейсом). Следовательно, в этой части системы нужно обеспечить низкую
степень связывания.Преимущества■ Изменения компонентов мало сказываются на других объектах.■ Принципы работы и функции компонентов можно понять, не изучая другие
объекты.■ Удобство повторного использования.Основы. Связывание и зацепление (описывается ниже) — действительно фунда¬
ментальные принципы проектирования, которые следует применять при разработке
всех программных систем. Ларри Константин, разработавший в 1970-х годах струк¬
турный подход к проектированию и изучающий в настоящее время принципы удоб¬
ства использования программ [31], в 1960-е годы занимался исследованием связыва¬
ния и зацепления, как важнейших принципов проектирования [32, 39].Связанные шаблоны■ Protected Variations (Защищенные вариации)17.13. Шаблон ControllerПроблема: кто должен отвечать за получение и координацию выполнения систем¬
ных операций, поступающих на уровне интерфейса пользователя?Системные операции ранее были описаны при рассмотрении системных диа¬
грамм последовательностей. Системные операции (system operation) являются основ¬
ными входными событиями в системе. Например, когда кассир в POS-системе щел¬
кнете на кнопке Оплатить, он генерирует системное событие, свидетельствующее о
завершении торговой операции. Аналогично, когда пользователь текстового процес¬
сора выбирает команду Орфография, он генерирует системное событие “выполнить
проверку орфографии”.
330 Часть III. Первая итерация фазы развития — основыКонтроллер (controller) — это объект, не относящийся к интерфейсу пользователя и
отвечающий за получение или обработку системных сообщений.Решение: делегирование обязанностей по обработке системных сообщений клас¬
су, удовлетворяющему одному из следующих условий.■ Класс представляет всю систему в целом, корневой объект, устройство или под¬
систему (внешний контроллер).■ Класс представляет сценарий некоторого прецедента, в рамках которого выпол¬
няется обработка всех системных событий, и обычно называется <Прецедент>
Handler, </7jb^£d£wm>Coordinator или <Прецедент>Session (контроллер преце¬
дента, или контроллер сеанса).• Для всех системных событий в рамках одного сценария прецедента использу¬
ется один и тот же класс-контроллер.• Неформально сеанс — это экземпляр взаимодействия с исполнителем. Сеансы
могут иметь произвольную длину, но зачастую они организованы в рамках
прецедента (сеансы прецедента).Следствие. Заметим, что в этот перечень не включаются
классы, реализующие окно, вид и документ. Такие классы не
выполняют задачи, связанные с системными событиями. Они
обычно получают сообщения и делегируют их контроллерам.Пример. Для лучшего понимания применения данного ша¬
блона воспользуемся примерами кода на Java, приведенными
ниже в разделе ’’Реализация графического интерфейса пользо¬
вателя на основе Java Swing" ниже в этой главе. Там описана
реализация Web-интерфейса системы на основе шаблона “тол¬
стого” клиента.В приложении NextGen существует несколько системных
операций (рис. 17.20). На этом рисунке сама система представ¬
лена в виде класса, что допустимо, а иногда и очень полезно.В процессе анализа поведения системы системные операции относятся к клас¬
су System. Однако это не означает, что их выполняет программный класс System.
Более того, обязанности по выполнению системных операций обычно возлагаются
на класс-контроллер (рис. 17.21).Какой класс должен выступать в роли контроллера для системных событий типа
enterltem или endSale?Согласно шаблону Controller, возможны следующие варианты.Класс, представляющий всю систему в целом, Register, POSSystemустройство или подсистему.Класс, представляющий получателя или искус- ProcessSaleHandler,ственный обработчик всех системных событий ProcessSaleSessionнекоторого сценария прецедента.Заметим, что в предметной области POS-систем объект Register (который также
называют терминалом) представляет собой специализированное устройство с соот¬
ветствующим программным обеспечением.SystemendSale()
enterltem()
makeNewSale()
makePayment()Рис. 17.20. Некото¬
рые системные опера¬
ции для приложения
NextGen
Глава 17. GRASP: проектирование объектов на основе распределения обязанностей 331Щелкает на кнопке:CashierУровень
интерфейсаУровеньобъектовпредметнойобластиИдентификатор товара |ОплатитьactionPerformed(actionEvent):SaleJFrameenterItem(itemID,qty) O-Сообщениео системном событииЬI I IКакой класс объектов должен отвечать за получение ■
этого сообщения о системном событии?Такой класс иногда называется контроллером
или координатором. Обычно этот класс не сам
выполняет все необходимые функции, а делегирует
их выполнение другим объектам.Контроллер выполняет роль “фасада” уровня
предметной области для объектов уровня интерфейсаРис. 17.21. Кто является контроллером для события enterltemfВ терминах диаграммы взаимодействий должен использоваться один из вариан¬
тов, представленных на рис. 17.22.Рис. 17.22. Варианты контроллеровВыбор наиболее подходящего контроллера определяется другими факторами,
в частности зацеплением и связыванием. Об этом более подробно рассказывается
ниже.
332 Часть III. Первая итерация фазы развития — основыСистемные операции, идентифицированные в процессе анализа поведения систе¬
мы, на этапе проектирования присваиваются одному или нескольким классам кон¬
троллеров, например Register (рис. 17.23.)SystemendSale()
enterltem()
makeNewSale()
makePayment()makeNewReturn()
enterReturnltem()►RegisterendSale()
enterltem()
makeNewSale()
makePayment()makeNewReturn()
enterReturnltem()Системные операции,
исследованные
в процессе анализа
поведения системыРазмещение системных Ьц
операций в процессе
проектирования
при использовании одного
внешнего контроллераSystemendSale()
enterltem()
makeNewSale()
makePayment()enterReturnltem()
makeNewReturn()►ProcessSaleHandlerendSale()
enterltem()
makeNewSale()
makePayment()HandleReturnsHandlerenterReturnltem()
makeNewReturn()Размещение системных I
операций в процессе
проектирования при
использовании нескольких
контроллеров прецедентовРис. 17.23. Распределение системных операцийОбсуждение. Применение этого шаблона лучше рассмотреть на конкретном при¬
мере, код которого приводится ниже в разделе “Реализация графического интерфей¬
са пользователя на основе Java Swing”.На самом деле это шаблон делегирования обязанностей. Поскольку объекты ин¬
терфейса пользователя не должны реализовывать логику приложения, они деле¬
гируют эти обязанности объектам следующего уровня. Если это уровень объектов
предметной области, то запросы на обработку сообщений, поступающих с уроЬня ин¬
терфейса пользователя, обрабатываются в соответствии с шаблоном Controller.
Глава 17. GRASP: проектирование объектов на основе распределения обязанностей 333Большинство систем получает внешние события. Обычно они связаны с графиче¬
ским интерфейсом пользователя. Кроме того, системе могут передаваться внешние
сообщения, например, при обработке телекоммуникационных сигналов или сигналов
от датчиков в системах управления.Во всех случаях при использовании объектно-ориентированного подхода для обра¬
ботки внешних событий применяются контроллеры. Шаблон Controller обеспечива¬
ет наиболее типичные проектные решения для этого случая. Как видно из рис. 17.21,
контроллер — это своеобразный вид интерфейса между уровнями предметной обла¬
сти и графического представления.Чтобы обеспечить возможность поддержки информации о состоянии прецедента,
для обработки всех системных событий в рамках одного прецедента должен исполь¬
зоваться один и тот же класс контроллера. Такая информация может понадобиться,
например, для идентификации момента нарушения последовательности системных со¬
бытий (например, выполнение операции makePayment перед выполнением операции
endSale). Для различных прецедентов можно использовать разные контроллеры.Типичной ошибкой при создании контроллеров является возложение на них
слишком большого числа обязанностей.СоветОбычно контроллер должен лишь делегировать функции другим объектам и коор¬
динировать их деятельность, а не выполнять эти действия самостоятельно.Об этом подробнее рассказывается ниже в данном разделе.Первым типом контроллеров является внешний контроллер (facade controller), пред¬
ставляющий всю “систему”, устройство или подсистему. Основная идея сводится к вы¬
бору некоторого класса, имя которого охватывает все слои приложения. Этот класс
обеспечивает главную точку вызова всех служб из интерфейса пользователя и обра¬
щения к остальным слоям. Этот класс может представлять физический объект, напри¬
мер систему Register,13 телекоммуникационный переключатель TelecommSwitch,
Phone или устройство Robot; всю программную часть системы, например POSSystem,
или любые другие понятия, выбранные разработчиком для представления системы в
целом.Внешние контроллеры удобно использовать в том случае, когда существует лишь
несколько системных событий или системные сообщения невозможно перенапра¬
вить другим контроллерам, наподобие системы обработки сообщений.Если применяется контроллер прецедента (use case controller), то для каждого пре¬
цедента должен существовать отдельный контроллер. Заметим, что это не объект
из предметной области, а искусственная конструкция, поддерживающая жизне¬
деятельность системы (среди шаблонов GRASP существует специальный шаблон
Pure Fabrication). Например, если в системе NextGen используются прецеденты
Оформление продажи и Возврат товара, то в ней может быть реализован класс
ProcessSaleHandler (Обработчик продажи).13 Для обозначения физического объекта POS-системы можно использовать разные тер¬
мины, в том числе реестр, терминал системы розничной торговли и т.д. Термин “реестр” при
этом может означать и физический объект, и логическую абстракцию, обеспечивающую реги¬
страцию информации о продажах и платежах.
334 Часть III. Первая итерация фазы развития — основыКогда следует использовать контроллеры прецедентов? В том случае, когда при¬
менение внешнего контроллера приводит к слабой степени зацепления или высокой
степени связывания. Контроллер прецедента вводится в том случае, если существу¬
ющий контроллер слишком “раздувается” при возложении на него дополнительных
обязанностей. Контроллеры прецедентов следует применять при наличии большого
числа системных событий, распределенных между различными процессами. Такие
контроллеры позволяют разделять обязанности их обработки между несколькими
классами и отслеживать состояние текущего сценария.В UP, а также более раннем методе Якобсона [72], существуют (необязательные)
понятия пограничных, управляющих классов и классов сущностей. Пограничные
объекты (boundary objects) — это абстракции интерфейсов, классы сущностей (entity
objects) — это независимые от приложения (и, как правило, сохраняемые в базе дан¬
ных) программные объекты, соответствующие понятиям из предметной области, а
управляющие объекты (control object) — это обработчики прецедентов, подобные
описываемым в шаблоне Controller.Важным следствием применения шаблона Controller является вынесение обязан¬
ностей по обработке системных событий за пределы уровня представления и внеш¬
него интерфейса объектов (например, объектов окон или кнопок). Другими словами,
системные операции, отражающие процессы в предметной области, должны обра¬
батываться на уровне логики приложения или реализации объектов, а не на уровне
интерфейса. Этот вопрос более подробно рассматривается ниже.Применение шаблона Controller для реализации
Web-интерфейса и серверной части приложенияВ одном из последующих разделов описан пример применения популярного кар¬
каса Java Struts для реализации серверной части приложения.Аналогичный подход к делегированию обязанностей можно использовать в ASP.
NET и WebForms: ссылка на объект-контроллер уровня предметной области (в при¬
мере POS-системы в его роли выступает объект Register) передается в файл, содер¬
жащий обработчики событий щелчков на кнопках Web-браузеров. Затем этому объ¬
екту делегируются права на выполнение запроса. Это не соответствует стандартному
стилю программирования на ASP.NET, при котором логика приложения реализуется
обработчикам событий пользовательского интерфейса, при этом смешиваются функ¬
ции уровня интерфейса пользователя и логики приложения.Серверные каркасы поддержки Web-интерфейса (например, Struts) соответствуют
“духу” шаблона Web-MVC (Model-View-Controller). При этом “контроллер” в контек¬
сте шаблона Web-MVC отличается от контроллера в понимании шаблонов GRASP.
Контроллер в контексте шаблона Web-MVC является частью уровня интерфейса поль¬
зователя и управляет взаимодействиями на этом уровне. Контроллер в понимании
шаблонов GRASP относится к уровню логики приложения. Он управляет обработкой
запросов, независимо от технологии реализации интерфейса пользователя (напри¬
мер, Web-интерфейса, Swing и т.п.).Для делегирования запросов от объектов уровня Web-интерфейса (например, от
класса Action каркаса Struct) при использовании технологий Java в серверной части
приложения зачастую используется компонент-обработчик сеанса EJB (Enterprise
JavaBeans) Session. Этот случай соответствует второму варианту реализации шабло¬
на Controller — с использованием контроллера прецедента или сеанса в серверной
Глава 17. GRASP: проектирование объектов на основе распределения обязанностей 335части приложения. В этом случае серверный объект-обработчик сеанса может даль¬
ше делегировать обязанности другим объектам уровня предметной области на основе
шаблона Controller.Из сказанного ясно, что способ обработки системных событий на стороне сервера
существенно зависит от выбора серверного технического каркаса. Однако при этом
всегда должен соблюдаться принцип отделения модели от представления (Model-View
Separation).Если интерфейс с пользователем обеспечивается не через Web-браузер (например,
через графическйй интерфейс Swing), но приложение вызывает удаленные службы,
то в этом случае тоже применим шаблон Controller. Из интерфейса пользователя на¬
правляется запрос локальному классу-контроллеру, относящемуся к клиентской части
приложения, а этот класс может перенаправить весь запрос или его часть удаленным
службам. При таком решении снижается степень связывания между интерфейсом
пользователя и удаленными службами, а также упрощается взаимодействие между
ними. Службы могут выполняться локально или удаленно, путем перенаправления от
клиентского контроллера.Преимущества■ Улучшение условий для повторного использования компонентов и подключения интер¬
фейсов. Применение этого шаблона обеспечивает обработку процессов пред¬
метной области на уровне реализации объектов, а не на уровне интерфейса.
Обязанности контроллера могут быть технически реализованы в объектах ин¬
терфейса, однако в этом случае программный код и логические решения, отно¬
сящиеся к процессам предметной области, будут жестко связаны с элементами
интерфейса, например с окнами. При этом снижается эффективность повтор¬
ного использования компонентов в других приложениях, поскольку процессы
предметной области ограничены рамками интерфейса (например, связаны с
оконным объектом), что может оказаться неприемлемым в других приложени¬
ях. Делегирование выполнения системных операций специальному контролле¬
ру облегчает повторное использование логики обработки подобных процессов
в последующих приложениях. Поскольку логика приложения при такой реали¬
зации не связана с уровнем интерфейса пользователя, последний можно легко
заменить.■ Контроль состояния прецедента. Иногда необходимо удостовериться, что систем¬
ные операции выполняются в некоторой определенной последовательности.
Например, необходимо гарантировать, чтобы операция makePayment выпол¬
нялась только после операции endSale, для чего необходимо накапливать ин¬
формацию о последовательности событий. Для этой цели удобно использовать
контроллер, особенно контроллер прецедента.РеализацияПриведем примеры использования технологий Java для реализации двух типов
клиентской части (на основе интерфейса Java Swing и Web-интерфейса) и серверной
части приложения на основе механизма сервлетов (каркаса Struts). Аналогичный
подход можно использовать для платформы .NET (на основе WinForm) и ASP.NET (на
основе WebForm). Хорошие проектные решения для платформы .NET не включают
логику приложения в обработчики событий (хотя программисты Microsoft зачастую
нарушают принцип Model-View Separation). Обработчикам событий интерфейса про¬
336 Часть III. Первая итерация фазы развития — основысто передается ссылка на объект уровня предметной области (например, Register),
которому делегируются поступающие запросы.Реализация графического интерфейса
пользователя на основе Java SwingВ данном разделе предполагается, что читатель знаком с пакетом Swing. Код со¬
держит комментарии, поясняющие основные положения. Обратите внимание на мет¬
ку 1. Из этого фрагмента видно, что окно ProcessSaleJFrame содержит ссылку на
объект-контроллер уровня предметной области Register. Во фрагменте с меткой 2
определен обработчик щелчков мышью. Во фрагменте 3 сообщение enterltem от¬
правляется контроллеру уровня объектов предметной области.package com.craiglarman.nextgen.ui.swing;// импортирование...//в Java объект JFrame задает обычное окно
public class ProcessSaleJFrame extends JFrame
{// оконный объект содержит ссылку на контроллер уровня предметной области
// 1private Register register;// при создании окна ему передается ссылка на контроллер
public ProcessSaleJFrame(Register _register){register=_register;}// для выполнения системной операции enterltem
// выполняется щелчок на этой кнопке
private JButton BTN_ENTER_ITEM;// это важный метод!// передача сообщения с уровня интерфейса на уровень
// логики приложения
private JButton getBTN_ENTER_ITEM(){// существует ли кнопка?
if (BTN_ENTER_ITEM!=null)
return BTN_ENTER_ITEM;//в противном случае надо инициализировать кнопку
BTN_ENTER_IТЕМ= new JButton();BTN_ENTER_ITEM.setText("Введите элемент");//ЭТО ВАЖНЕЙШИЙ РАЗДЕЛ;//в Java так определяется обработчик щелчков на кнопке
// 2BTN_ENTER_ITEM.addActionListener(new ActionListener(){
Глава 17. GRASP: проектирование объектов на основе распределения обязанностей 337public void actionPerformed(ActionEvent e){//Transformer — это класс-утилита для преобразования
// строк в другие типы данных.// Элемент GUI JTextField содержит строки
ItemID id = Transformer.toItemID(getTXT_ID().getTextO);
int qty = Transformer.tolnt(getTXT_QTY().getTextO);// переход с уровня UI на уровень логики приложения
// делегирование обязанностей контроллеру
// »> ЭТО ВАЖНЕЙШИЙ МОМЕНТ «<// 3register.enterltem(id, qty);}} ) ; // конец вызова addActionListener
return BTN_ENTER_ITEM;} // конец метода//...} // конец описания классаВзаимодействие с Web-интерфейсом на основе Java StrutsВ данном разделе предполагается, что читатель знаком с пакетом Struts. Обратите
внимание на метку 1. В этом фрагменте объект Action обращается к контексту
сервлета для получения ссылки на объект-контроллер уровня предметной области
Register. Во фрагменте 2 ключевое сообщение enterltem отправляется контролле¬
ру уровня объектов предметной области.package com.craiglarman.nextgen.ui.web;// импортирование...//в Struts объект Action связывается со щелчком// на кнопке в Web-браузере и активизируется (на сервере)// при щелчке на кнопкеpublic class EnterltemAction extends Action {// этот метод вызывается на сервере
// при щелчке на кнопке в браузере клиента
public ActionForward execute ( ActionMapping mapping,ActionForm form,
HttpServletRequest request,
HttpServletResponse response)
throws Exception{// в серверной части есть объект Repository,// содержащий ссылку на несколько объектов,// включая объект Register
338 Часть III. Первая итерация фазы развития — основыRepository repository = (Repository)getServlet().GetServletContext () .getAttribute(Constants.REPOSITORY_KEY);// 1Register register = repository.getRegister() ;// извлечение данных ItemID и qty из Web-формы
String txtld = ((SaleForm)form).getltemID() ;String txtQty = ( (SaleForm)form).getQuantity() ;//Transformer — это класс-утилита для преобразования
/ / строк в другие типы данных.ItemID id = Transformer.toItemID(txtld);
int qty = Transformer.tolnt(txtQty);// переход с уровня UI на уровень логики приложения,// делегирование обязанностей контроллеру.// »> ЭТО ВАЖНЕЙШИЙ МОМЕНТ «<// 2register.enterltem(id, qty);//} // конец метода
} // конец описания классаПроблемы и решения: раздутый контроллерПлохо спроектированный класс контроллера имеет низкую степень зацепления:
он выполняет слишком много обязанностей и является несфокусированным. Такой
контроллер называется раздутым (bloated controller). Признаки раздутого контролле¬
ра таковы.■ В системе имеется единственный класс контроллера, получающий все системные
сообщения, которых поступает слишком много. Такая ситуация зачастую воз¬
никает при использовании внешнего контроллера.■ Контроллер сам выполняет все задачи, не делегируя обязанности другим
классам. Обычно это приводит к нарушению основных принципов шаблонов
Information Expert и High Cohesion.■ Контроллер имеет много атрибутов и содержит значительный объем инфор¬
мации о системе или предметной области, которую необходимо распределить
между другими объектами, либо дублирует информацию, хранящуюся в других
объектах.Существует несколько рецептов для устранения проблемы раздутого контроллера.1. Добавьте несколько контроллеров; не нужно ограничиваться лишь одним.
Помимо внешних контроллеров, используйте контроллеры прецедентов. Напри¬
мер, в системе, имеющей много системных событий (скажем, в системе резер¬
вирования авиабилетов), можно использовать следующие контроллеры.
Глава 17. GRASP: проектирование объектов на основе распределения обязанностей 339Контроллеры прецедентовMakeReservationHandler (обработчик события резервирования)ManageSchedulesHandler (менеджер расписания)ManageFaresHandler (менеджер тарифов)2. Спроектируйте контроллер таким образом, чтобы он делегировал обязанности
по выполнению системных операций другим объектам.Системные события не обрабатываются на уровне представленияНапомним, что важным следствием применения шаблона Controller является та¬
кой факт: объекты интерфейса (например, окна) не обрабатывают системные собы¬
тия. Рассмотрим систему, написанную на языке Java и использующую объект JFrame
для отображения информации.Допустим, в системе розничной торговли имеется окно, отображающее инфор¬
мацию о продаже и позволяющее кассиру выполнять необходимые операции. На
рис. 17.24 показаны приемлемые отношения между объектом JFrame, контроллером
и другими объектами в упрощенной версии POS-системы.Щелкает на кнопке: CashierI МагазиншштИдентификатор товара |КоличествоВвод товара]Оплатить |УровеньинтерфейсаactionPerformed(actionEvent)I:SaleJFrame1:enterltem(itemID,qty)? I o-Сообщение
о системном событииbКонтроллерУровеньобъектовпредметнойобластио- :Registerl.l:makelineltem(itemID, qty): SalePuc. 17.24. Связывание уровней интерфейса и предметной области
340 Часть III. Первая итерация фазы развития — основыЗаметим, что класс Sale JFrame, относящийся к уровню интерфейса, передает со¬
общение enterltem объекту Register. Он не принимает участия в обработке этой
операции, а лишь делегирует функцию уровню реализации.Распределение обязанностей по выполнению системных операций между объекта¬
ми предметной области (согласно шаблону Controller), а не объектами уровня пред¬
ставления повышает эффективность повторного использования. Если объект ин¬
терфейса (скажем, SaleJFrame) обрабатывает системную операцию (составляющую
часть процесса предметной области), то логика процесса предметной области должна
быть заложена в интерфейсе (например, в оконном объекте). Такое проектное реше¬
ние снижает эффективность повторного использования, поскольку данное приложе¬
ние существенно связано с конкретным интерфейсом. Следовательно, на рис. 17.25
представлено неприемлемое проектное решение.Идентификатор товараКоличествоЩелкает на кнопке>* Ввод товараОплатить:CashieractionPerformed(actionEvent)IОбъекты уровня интерфейса, I
в частности окна, нежелательно
использовать для обработки
процессов предметной области.Уровеньинтерфейса:SaleJFrameБизнес-логику не стоит
реализовывать на уровне
представленияУровеньобъектовпредметнойобласти1 :makelineItem(itemID, qty)Р: SaleОбъект SaleJFrame И
не должен отправлять
это сообщениеVРис. 17.25. Нежелательное связывание уровня интерфейса с уровнем предметной области
Глава 17. GRASP: проектирование объектов на основе распределения обязанностей 341Возложение ответственности за выполнение системной операции на специальный
контроллер упрощает повторное использование логики программы в последующих
приложениях, а также облегчает возможность применения другого интерфейса для
данного приложения или использование приложения в неинтерактивном “пакетном”
режиме.Системы обработки сообщений и шаблоны командМногие приложения не содержат интерфейса пользователя, а получают сообще¬
ния от других внешних систем. Такие системы называются системами обработки
сообщений. Типичным примером такой системы является телекоммуникационный
переключатель. В таких системах термины “интерфейс” и “контроллер” имеют иное
значение. Более подробно этот вопрос будет изучен в последующих главах, одна¬
ко стоит отметить, что стандартным решением является использование шаблона
Command [58] и Command Processor [17], описываемых в главе 38.Похожие шаблоны■ Command (Команда) — в системах обработки сообщений каждое сообщение мо¬
жет представлять и обрабатывать отдельный объект Command [58].■ Facade (Фасад) — выбор объекта, представляющего всю систему или организа¬
цию в качестве внешнего контроллера [58].■ Layers (Слои) — шаблон, предложенный в [17]. Согласно шаблону Layers, логика
реализации размещается в слое реализации, а не в слое представления.■ Pure Fabrication (Чистая синтетика) — еще один шаблон GRASP, который подраз¬
умевает создание искусственного класса, не имеющего аналога в предметной об¬
ласти. Элементом шаблона Pure Fabrication является контроллер прецедента.17.14. Шаблон High CohesionПроблема: как обеспечить сфокусированность обязанностей объектов, их управ¬
ляемость и ясность, а заодно выполнение принципа Low Coupling?В терминах объектно-ориентированного проектирования зацепление (cohe¬
sion) (или, более точно, функциональное зацепление) — это мера связанности и
сфокусированности обязанностей класса. Считается, что элемент обладает высокой
степенью зацепления, если его обязанности тесно связаны между собой и он не вы¬
полняет непомерных объемов работы. В роли таких элементов могут выступать клас¬
сы, подсистемы и т.д.Решение: распределение обязанностей, поддерживающее высокую степень заце¬
пления. Этот принцип используется для оценки возможных альтернатив.Класс с низкой степенью зацепления выполняет много разнородных функций или
несвязанных между собой обязанностей. Такие классы создавать нежелательно, по¬
скольку они приводят к возникновению следующих проблем.■ Трудность понимания.■ Сложности при повторном использовании.■ Сложности поддержки.■ Ненадежность, постоянная подверженность изменениям.
342 Часть III. Первая итерация фазы развития — основыКлассы со слабым зацеплением, как правило, являются слишком “абстрактными”
или выполняют обязанности, которые можно легко распределить между другими
объектами.Пример. Для анализа шаблона High Cohesion можно использовать тот же пример,
что и для Low Coupling.Предположим, необходимо создать экземпляр объекта Payment и связать его
с текущей продажей. Какой класс должен выполнять эту обязанность? Поскольку в
реальной предметной области сведения о платежах записываются в реестре, соглас¬
но шаблону Creator, для создания экземпляра объекта Payment можно использовать
объект Register. Тогда экземпляр объекта Register сможет отправить сообщение
addPayment объекту Sale, передавая в качестве параметра новый экземпляр объекта
Payment, как показано на рис. 17.26.Рис. 17.26. Экземпляр объекта Register создает объект PaymentПри таком распределении обязанностей платежи выполняет объект Register,
т.е. объект Register частично несет ответственность за выполнение системной опе¬
рации makePayment.В данном обособленном примере это приемлемо. Однако если и далее возлагать
на класс Register обязанности по выполнению все новых и новых функций, связан¬
ных с другими системными операциями, то этот класс будет слишком перегружен и
будет обладать низкой степенью зацепления.Предположим, приложение должно выполнять пятьдесят системных операций и
все они возложены на класс Register. Если этот объект будет выполнять все опера¬
ции, то он станет чрезмерно “раздутым” и не будет обладать свойством зацепления.
И дело не в том, что одна задача создания экземпляра объекта Payment сама по себе
снизила степень зацепления объекта Register; она является частью общей картины
распределения обязанностей.Важно отметить, что, независимо от окончательного выбора проектного реше¬
ния, следует оценить степень зацепления объектов.На рис. 17.27 представлен другой вариант распределения обязанностей. Здесь
функция создания экземпляра платежа делегирована объекту Sale. Благодаря этому
поддерживается более высокая степень зацепления объекта Register.Поскольку такой вариант распределения обязанностей обеспечивает низкий уро¬
вень связывания и более высокую степень зацепления, он является более предпочти¬
тельным.
Глава 17. GRASP: проектирование объектов на основе распределения обязанностей 343Рис. 17.27. Объект Sale создает экземпляр объекта PaymentНа практике уровень зацепления не рассматривают изолированно от других обя¬
занностей и принципов, обеспечиваемых шаблонами Expert и Low Coupling.Обсуждение. Как и о принципе слабого связывания, о высокой степени зацепле¬
ния следует помнить в течение всего процесса проектирования. Этот шаблон необхо¬
димо применять при оценке эффективности каждого проектного решения.Гради Буч считает, что можно говорить о высоком функциональном зацеплении
между элементами одного компонента (например, класса), если “все они взаимодей¬
ствуют между собой с целью обеспечения некоторого определенного поведения”
[21].Вот несколько сценариев, иллюстрирующих различную степень функционального
зацепления.1. Очень слабое зацепление. Только класс отвечает за выполнение множества опера¬
ций в самых различных функциональных областях.• Допустим, существует класс RDB-RPC-Interface, полностью отвечающий за
взаимодействие между реляционными базами данных и вызов удаленных про¬
цедур. Это две абсолютно разные функциональные области, требующие боль¬
ших объемов кода. Такие обязанности можно распределить между семейст¬
вом классов, связанных с доступом к реляционной базе данных, и семейством
классов, отвечающих за поддержку удаленных процедур.2. Слабое зацепление. Класс несет единоличную ответственность за выполнение
сложной задачи из одной функциональной области.• Допустим, некий класс RDBInterface полностью отвечает за взаимодействие
с реляционными базами данных. Методы этого класса связаны между собой,
однако их слишком много, и их реализация требует огромных объемов кода.
Таких методов может быть несколько сотен или даже тысяч. Данный класс
следует разделить на несколько более мелких классов, совместно обеспечива¬
ющих доступ к реляционным базам данных.3. Сильное зацепление. Класс имеет среднее количество обязанностей из одной
функциональной области и для выполнения своих задач взаимодействует с дру¬
гими классами.• Допустим, некоторый класс RDBInterface лишь частично отвечает за взаи¬
модействие с реляционными базами данных. Для извлечения и сохранения
объектов в базе данных он взаимодействует с десятком других классов.
344 Часть III. Первая итерация фазы развития - основы4. Среднее зацепление. Класс имеет несложные обязанности в нескольких различных
областях, логически связанных с концепцией этого класса, но не связанных
между собой.• Допустим, существует класс Company, который несет полную ответственность
за (а) знание всех сотрудников компании и (б) всю финансовую информацию.
Эти две области не слишком связаны между собой, однако обе логически свя¬
заны с понятием “компания”. К тому же предполагается, что такой класс со¬
держит небольшое число открытых методов и требует незначительных объ¬
емов кода для их реализации.Как правило, класс с высокой степенью зацепления содержит сравнительно не¬
большое число методов, которые функционально тесно связаны между собой, и не
выполняет слишком много функций. Он взаимодействует с другими объектами для
выполнения более сложных задач.Предпочтительно создавать классы с высокой степенью зацепления, поскольку
они весьма просты в понимании, поддержке и повторном использовании. Высокая
степень однотипной функциональности в сочетании с небольшим числом операций
упрощают поддержку и модификацию класса, а также возможность его повторного
использования.Шаблон High Cohesion, как и другие понятия объектно-ориентированной техноло¬
гии проектирования, имеет аналогию в реальном мире. Всем известно, что человек,
выполняющий большое число разнородных обязанностей (особенно тех, которые
можно легко распределить между другими людьми), работает не очень эффективно.
Это касается менеджеров, которые не умеют распределять обязанности между сво¬
ими подчиненными. Такие люди страдают от “низкой степени зацепления” и могут
легко “расклеиться”.Еще один классический принцип: модульное проектированиеСвязывание и зацепление — это старые принципы проектирования программных
продуктов. Объектное проектирование не идет вразрез с устоявшимися подходами.
Еще одной особенностью, тесно связанной со связыванием и зацеплением, является
модульность (modular design). Приведем цитату.“Модульность — это свойство системы, разбитой на множество модулей с высо¬
кой степенью зацепления и слабым связыванием” [21].Модульное проектирование обеспечивается за счет создания методов и классов с
высоким зацеплением. На уровне базовых объектов модульность достигается за счет
проектирования каждого метода с явно выделенной конкретной целью и группирова¬
ния набора взаимосвязанных методов в рамках одного класса.Связывание и зацепление: инь и янь
проектирования программного обеспеченияНекорректное связывание порождает неправильное зацепление и наоборот.) Автор рассматривает связывание и зацепление как инь и янь проектирова-
ния программного обеспечения, поскольку эти понятия взаимозависимы.
Предположим, например, что класс уровня пользовательского интерфейса, представ¬
ляющий аплет, сохраняет данные в базе данных и вызывает удаленные службы. Такой
класс не только обладает слабым зацеплением, но и оказывается сильно связанным
со многими другими элементами.
Глава 17. GRASP: проектирование объектов на основе распределения обязанностей 345Когда не следует применять шаблон. Существует несколько случаев, когда низ¬
кое зацепление оказывается оправданным.Одна из таких ситуаций возникает в том случае, когда обязанности или код груп¬
пируются в одном классе или компоненте для упрощения его поддержки одним че¬
ловеком. Однако в данном случае необходимо помнить о том, что такая группировка
может привести и к усложнению поддержки. Предположим, что в приложении со¬
держатся внедренные операторы SQL, которые в соответствии с другими шаблона¬
ми проектирования нужно распределить по десяти классам работы с базой данных.
В этом случае лишь один или два эксперта в области SQL знают, как лучше всего
определять и поддерживать эти операторы SQL, даже несмотря на то, что в проек¬
те участвуют десятки программистов с опытом работы в области объектно-ориенти¬
рованного программирования. Некоторые из них могут иметь достаточно высокий
уровень знания объектно-ориентированных технологий. Предположим также, что
эксперт в области SQL не обладает навыками программиста по созданию объектно-
ориентированных программ. Архитектор программной системы может решить сгруп¬
пировать операторы SQL в одном классе RDBOpe rat ions, чтобы эксперту было легче
работать с этими операторами в одном месте.Другой пример слабого зацепления имеет отношение к распределенным сервер¬
ным объектам. Поскольку быстродействие системы определяется производительнос¬
тью удаленных объектов и их взаимодействием, иногда желательно создать несколько
более крупных серверных объектов со слабым зацеплением, предоставляющих интер¬
фейс многим операциям. Эта ситуация связана также с шаблоном Coarse-Grained Remote
Interface (Укрупненный удаленный интерфейс), в рамках которого создаются укрупнен¬
ные удаленные операции, выполняющие больше функций. Такое проектное решение
объясняется повышенным влиянием удаленных вызовов на производительность сети.
В качестве альтернативы вместо удаленного объекта с тремя операциями setName,
setSalary и setHireDate лучше реализовать одну укрупненную удаленную операцию
set Date, работающую с целым множеством данных. Это приведет к уменьшению чис¬
ла удаленных вызовов и, как следствие, к повышению производительности.Преимущества■ Повышаются ясность и простота проектных решений.■ Упрощаются поддержка и доработка.■ Зачастую обеспечивается слабое связывание.■ Улучшаются возможности повторного использования, поскольку класс с высо¬
кой степенью зацепления выполняет конкретную задачу.17.15. Дополнительные ресурсыИдея взаимодействия объектов при выполнении своих обязанностей (или проек¬
тирование на основе обязанностей) (Responsibility Driven Design) не нова. Она раз¬
вивалась еще в процессе программирования на языке Smalltalk в компании Tektronix
(Портленд) Кентом Беком (Kent Beck), Уордом Каннингемом (Ward Cunningham),
Ребеккой Вирфс-Брок (Rebecca Wirfs-Brock) и др. Основополагающим трудом в этой
области является [124], который в настоящее время столь же актуален, как и во вре¬
мя его написания. Позднее вышла еще одна книга по проектированию на основе обя¬
занностей— [123].Рекомендуем еще одну книгу, в которой основное внимание уделяется фундамен¬
тальным принципам объектного проектирования. Это книга Коада [34].
!I
Примеры объектного
проектирования на основе
шаблонов GRASPЧтобы изобрести нечто новое, нужно иметь хорошее воображение и кучу заготовок.Томас Эдисон (Thomas Edison)Основные задачи■ Спроектировать реализации прецедентов.■ Применить шаблоны GRASP для распределения обязанностей между
классами.■ Использовать UML для иллюстрации проектных решений.ВведениеВ этой главе рассказывается о применении принципов объектного проектирова¬
ния к рассматриваемым примерам систем. Приводятся сложные примеры взаимо¬
действия классов, выполняющих определенные обязанности. Стоит заметить, что
шаблоны GRASP сами по себе не очень важны, они лишь облегчают общение между
разработчиками и позволяют методически проектировать объекты.
348 Часть III. Первая итерация фазы развития — основыЧто дальше?ДиаграммыклассовUMLПосле ознакомления с основными принципами проектирования на основе шаблонов
GRASP в данной главе эти принципы применяются к конкретным примерам.В следующей главе рассматриваются важные вопросы проектирования видимости
между объектами/Проектирование
объектов
с помощью
шаблонов
GRASP о \ПримерыпроектированияобъектовПреобразование
Проектирование проектного
областей решениявидимости в программный
код о оРаспределение обязанностей и проектирование взаимодействия объектов — наи¬
более важные “творческие” факторы процесса проектирования. Они чрезвычай¬
но важны как для построения диаграмм, так и для программной реализации.И никакой магииВ этой главе детально обсуждаются принципы, на основе которых разработчик
распределяет обязанности между объектами и определяет механизмы их взаимодей¬
ствия. В процессе разработки объектно-ориентированных систем эти вопросы явля¬
ются наиболее важными.В первую очередь мы постараемся подробно показать, что в процессе объектно-
ориентированного проектирования нет ничего магического или необъяснимого.
Варианты распределения обязанностей и выбор способов взаимодействия между
объектами можно рационально объяснить и изучить. Объектно-ориентированное
проектирование — это наука, а не искусство, хотя и предоставляющая широкое поле
для креативной творческой деятельности.18.1. Реализация прецедентовВ предыдущей главе, посвященной базовым принципам объектного проектиро¬
вания, рассматривались небольшие фрагменты проектных решений. В данной главе
будет представлена общая картина объектного проектирования уровня предметной
области1 для целого сценария прецедента. Читатель увидит общую картину взаимо¬
действия объектов и ознакомится с более сложными диаграммами UML.Приведем цитату: “Реализация прецедента (use-case realization) показывает, как
определенный прецедент реализуется в рамках модели проектирования в терминах
взаимодействующих объектов” [112]. Если сказать более точно, разработчик может
описать проектное решение для одного или нескольких сценариев (scenario) прецеден¬
та, каждый из которых называется реализацией прецедента (хотя логичнее было бы
назвать его реализацией сценария (scenario realization)). Реализация прецедента — это
термин процесса UP или концепция, позволяющая сохранить связь между требова¬1 Напомним, что при рассмотрении примеров мы сосредоточимся на проектировании уров¬
ня предметной области, а не интерфейса пользователя или уровня служб, которые тоже игра¬
ют важную роль.
Глава 18. Примеры объектного проектирования на основе шаблонов GRASP 349ниями, выраженными в виде прецедентов, и процессом проектирования объектов,
которые этим требованиям удовлетворяют.Диаграммы взаимодействия UML являются стандартным средством, используе¬
мым для иллюстрации реализаций прецедента. Как упоминалось в предыдущей главе,
в процессе проектирования объектов можно использовать принципы и шаблоны, та¬
кие как Information Expert и Low Coupling.На рис. 18.1 иллюстрируется взаимосвязь между некоторыми артефактами UP в
процессе моделирования прецедентов и проектирования системы на основе реали¬
зации прецедентов.Отметим следующие моменты, связанные с реализацией артефактов.■ Системные события определяются на основе прецедентов и подробно отобра¬
жаются на диаграммах последовательностей.■ Системные операции являются начальными сообщениями диаграмм последова¬
тельностей. Для их выполнения на диаграммах взаимодействия объектов вво¬
дятся контроллеры для уровня предметной области (рис. 18.2).• Неопытные разработчики зачастую упускают из виду этот важный момент.■ Диаграммы взаимодействия для уровня предметной области иллюстрируют вза¬
имодействие объектов при выполнении их основных задач — реализации пре¬
цедентов.18.2. Комментарии к артефактамСДП, системные операции, диаграммы
взаимодействия и реализация прецедентовНа текущей итерации рассматриваются сценарии и системные события, опреде¬
ленные на системных диаграммах последовательностей для прецедента Оформление
продажи (Process Sale) приложения NextGen.■ makeNewSale■ enterltem■ endSale■ makePayment.Если диаграммы коммуникации используются для иллюстрации реализации пре¬
цедентов, то для отражения процесса обработки каждого сообщения, соответствую¬
щего системной операции, требуется отдельная диаграмма. Это же относится к диа¬
граммам последовательностей (рис. 18.2, 18.3).Важный моментСистемные операции на системных диаграммах последовательностей использу¬
ются как начальные сообщения, поступающие объектам-контроллерам уровня
предметной области.
350 Часть III. Первая итерация фазы развития — основыПример взаимосвязи артефактов UPМодель предметной областиSaledateSalesLineltemquantityМодель прецедентовОпре¬делениетребо¬ваний/ Идеи по
именованию
некоторых
программных
объектов
уровня
предметной
областиИсходная
информация
для проекти¬
рования
и детальное
описание
постусловий
которые
должны быть j
\выполнены I/ОформлениеЧ
Sad Ч^продаж^ Кассир Г ЧЯИмена
прецедентов
 ►Оформление
продаж
1. Покупатель
подходит...2..^ 3.Кассир вводит
идентификатор
.товара.Диаграмма прецедентовИдеи
по формулировке
постусловийЯТекст прецедентасистемные
события:SystemДополнительнаяспецификацияНефункциональные\
требования
Правила предметной \
областиФункциональные
требования,
которые должны
быть реализованы
с помощью
I объектовОперация; ,у/ : Кассир iС enterltem (...))j make (Системные i NewSaleOПостусловия:операции L- i^ enterltem ч j44 (id, quant i ty w i^Описания операцийСистемные диаграммы
последовательностейСловарьПодробные
описания
! элементов,
форматов
и процедур
верификацииМодель проектирования:RegisterProductCatalog:Saleenterltem
Проекти- | ^itemID, quantity^
рование ,spec = getProductSpec( itemID )addLine!tem( spec, quantity )RegistermakeNewSale()
enterltem(...)ProductCatalogJPuc. 18.1. Пример взаимосвязи артефактов UP в контексте реализации прецедентов
Глава 18. Примеры объектного проектирования на основе шаблонов GRASP 351Рис. 18.2. Диаграммы коммуникации и обработка системных событийОконные объекты
илиЭлементы управленияпользовательскогоинтерфейсаилиЭлементы управления
Web-приложенияUl LAYER:RegistermakeNewSale О Iт create()] ►: Sale:Register"Г:ProductCatalogspec=getProduct
Desc(itemID)DOMAIN LAYERPuc. 18.3. Диаграммы последовательностей и обработка системных операций
352 Насть III. Первая итерация фазы развития - основыПрецеденты и их реализацияРеализация прецедентов выполняется на основе их описаний, материалов допол¬
нительной спецификации, словаря терминов, прототипов интерфейса пользователя,
прототипов отчетов и т.д. При этом необходимо помнить, что любое описание тре¬
бований к системе (в виде перечисленных артефактов) является далеким от совер¬
шенства.Привлечение пользователей к процессу разработкиИз предыдущего раздела создается впечатление, что для разработки и проекти¬
рования программного обеспечения не обойтись без документально оформленного
описания требований. Это так, но процесс разработки невозможен также без актив¬
ного участия пользователей в тестировании прототипов, обсуждении требований,
оценке демонстрационных фрагментов. Один из главных принципов гибкой разра¬
ботки звучит так: “Разработчики и пользователи должны ежедневно работать вместе
в течение всего проекта”.Описания системных операций и реализация прецедентовСтоит еще раз напомнить, что реализацию прецедентов вполне возможно про¬
ектировать непосредственно на основе текста из описания прецедента. Кроме того,
описание некоторых системных операций может быть более подробным или содер¬
жать некоторые специфические особенности, как, например, показано ниже.Описание операции 0П2: enterltemОперация enterltem(itemID : ItemID, quantity : integer)Ссылки Прецеденты: Оформление продажи (Process Sale)Предусловия Инициирована продажаПостусловия - Создан экземпляр sli класса SalesLineltem (создание экземпляра)На основе этой информации анализа описаний прецедентов для каждого описания
определяются изменения состояния, приводящие к реализации постусловий, и про¬
ектируются виды взаимодействия по передаче сообщений с целью удовлетворения
требований. Например, на основе приведенного выше фрагмента описания систем¬
ной операции enterltem можно построить диаграмму взаимодействия, представлен¬
ную на рис. 18.4 и завершающуюся созданием экземпляра объекта SalesLineltem.Рис. 18.4. Фрагмент диаграммы взаимодействия с учетом постусловий описания операции
Глава 18. Примеры объектного проектирования на основе шаблонов GRASP 353Модель предметной области и реализация прецедентовНекоторые из программных объектов, взаимодействующих между собой посред¬
ством передачи сообщений и отображаемых на диаграммах взаимодействия, фор¬
мируются на основе модели предметной области. Так, концептуальному классу Sale
соответствует класс Sale модели проектирования. Обязанности между ними распре¬
деляются с учетом шаблонов GRASP, на основе информации о модели предметной
области. Как уже упоминалось, существующая модель предметной области имеет свои
недостатки. В ней возможны ошибки и упущения. Вам придется вводить новые поня¬
тия, которые были упущены ранее, а также выполнять аналогичные действия с ассо¬
циациями и атрибутами.Должны ли имена программных классов из модели проектирования в точности
соответствовать именам объектов модели предметной области? Вовсе нет. На эта¬
пе проектирования могут “всплыть” новые имена концептуальных классов, которые
были упущены на ранних стадиях анализа. Кроме того, могут появиться программные
классы, имена и назначение которых абсолютно не соответствуют модели предмет¬
ной области.18.3. Что дальше?Оставшаяся часть данной главы содержит следующий материал.1. Довольно детальное описание проектного решения POS-системы NextGen.2. Аналогичное описание проектного решения для игры “Монополия”.Рассмотрим особенности применения шаблонов GRASP в процессе проектирова¬
ния рассматриваемых систем.18.4. Реализация прецедентов для данной
итерации разработки системы NextGenРассмотрим процесс проектирования реализации прецедентов на основе шабло¬
нов GRASP. Это будет сделано достаточно подробно, чтобы проиллюстрировать, что
при построении диаграмм кооперации нет ничего сверхъестественного. Они базиру¬
ются на вполне обоснованных принципах.Инициализация работы системы
и прецедент Запуск системыРеализация прецедента Запуск системы (Start Up) — это контекст, в котором рас¬
сматривается создание большинства “корневых” и долго живущих объектов. Детали
проектного решения для данного прецедента будут рассмотрены ниже в этой главе.При написании кода системы нужно сразу же предусмотреть упрощенную реализа¬
цию прецедента Запуск системы. Однако в процессе объектного проектирования
диаграмма взаимодействия для системной операции startup разрабатывается по¬
следней. При таком подходе гарантируется, что к моменту разработки системной
операции startup известна вся существенная информация, связанная с инициали¬
зацией системы и необходимая для поддержки реализаций других прецедентов.12 Зак. 3357
354 Часть III. Первая итерация фазы развития — основыВоспользовавшись этой рекомендацией, рассмотрим сначала реализацию преце¬
дента Оформление продажи.Проектное решение: makeNewSaleСистемная операция makeNewSale инициируется в тот момент, когда кассир пере¬
дает запрос о начале новой продажи после того, как покупатель подходит к кассе с
выбранными покупками. Необходимую для реализации этой операции информацию
можно почерпнуть непосредственно из описания прецедента, однако при рассмотре¬
нии POS-системы мы условились составлять описания для всех системных операций.Описание операции 0П1: makeNewSaleОперация makeNewSale()Ссылки Прецеденты: Оформление продажиПредусловия ОтсутствуютПостусловия - Создан экземпляр s объекта Sale (создание экземпляра)-Экземпляр Sale связан с объектом Register (формирование ассоциации)- Инициализированы атрибуты экземпляра sВыбор класса-контроллераСначала необходимо выбрать контроллер для обработки сообщений системной
операции enterltem. Согласно шаблону Controller, в качестве контроллера может
выступать класс, удовлетворяющий одному из следующих условий.Класс представляет всю сис¬
тему в целом, “корневой объ¬
ект”, специализированное
устройство или подсистему.Класс является получателем
или обработчиком всех сис¬
темных событий для некото¬
рого сценария прецедента.Store — корневой объект, поскольку в его контексте
работает большинство объектов предметной области.
Register — представляет специализированное
устройство, на котором развернуто программное обе¬
спечение (зачастую называется POSTerminal).
POSSystem — объект, представляющий всю систему.ProcessSaleHandler — имя формируется по прин¬
ципу <имя_прецедента>Еап(11ег или <имя_преце-
MeHTa>Session.ProcessSaleSessionВыбор внешнего контроллера, например класса Register, обоснован в том случае,
если в приложении существует лишь несколько системных операций и на внешний
контроллер будет возложено не слишком много обязанностей (другими словами, не
нарушится зацепление). Контроллеры прецедентов удобно использовать при наличии
множества системных операций для распределения обязанностей между различными
классами во избежание перегрузки классов-контроллеров (другими словами, для обе¬
спечения зацепления). В данном случае, так как в системе существует лишь несколько
системных операций, в качестве контроллера можно выбрать класс Register.Важно понимать, что в данном случае Register — это программный объект из
модели проектирования, а не физический реестр системы розничной торговли.
Глава 18. Примеры объектного проектирования на основе шаблонов GRASP 355Таким образом, представленная на рис. 18.5 диаграмма взаимодействия начинает¬
ся с отправляемого сообщения makeNewSale программному объекту Register.:RegistermakeNewSale I ►rJlcreate: SalePuc. 18.5. Применение шаблона ControllerСоздание нового экземпляра объекта SaleДля создания программного объекта Sale воспользуемся шаблоном Creator, соглас¬
но которому обязанность по созданию новых экземпляров делегируется классу, содер¬
жащему, агрегирующему или записывающему информацию о создаваемых классах.Проанализировав модель предметной области, приходим к выводу, что запись
информации о продажах может выполнять объект Register. Заметим, что термин
“реестр” означает журнал, в который записываются (или регистрируются) сведения
о транзакциях, в частности о проданных товарах.Поэтому объекту Register целесообразно поручить создание экземпляров объек¬
тов Sale. Если экземпляры Sale будут создаваться объектом Register, то впослед¬
ствии объект Register будет содержать ссылку на текущий экземпляр Sale.Кроме того, после создания объекта Sale необходимо создать пустую коллекцию
(контейнер наподобие List в Java) для записи всех добавляемых впоследствии экзем¬
пляров SalesLineltem. Эта коллекция будет поддерживаться экземпляром Sale, ко¬
торый, согласно шаблону Creator, является наилучшим кандидатом для ее создания.Таким образом, объект Register создает экземпляры Sale, a Sale, в свою оче¬
редь, создает пустой контейнер, представленный на диаграмме взаимодействия как
сложный объект.Таким образом, получена диаграмма взаимодействия, представленная на рис. 18.6.ЗаключениеПроцесс проектирования оказался несложным, однако на его примере мы смог¬
ли продемонстрировать применение шаблонов Controller и Creator и методически
пояснить проектное решение в терминах принципов проектирования и шаблонов
GRASP.Проектное решение: enteritemСистемная операция enteritem начинается с ввода кассиром кода товара itemID
и количества покупаемых единиц. Приведем полное описание этой операции.
356 Часть III. Первая итерация фазы развития — основыПо шаблонам
Creator и ControllerОбъект Register В
создает объекты sale
в соответствии
с шаблоном Creator:RegisterТВ соответствии с шаблоном Creator Ik,
объект Sale создает пустую коллекцию
(например, List), в которой будут
храниться экземпляры SalesLineltemmakeNewSaledcreate: SaleTо-О'] create ^lineitems:J *List<SalesLineItem>Предполагается, что этот блок активации
будет размещаться внутри конструктора
экземпляра SaleРис. 18.6. Создание экземпляров Sale и сложного объектаОписание операции ОП2: enterltemОперация enterltem(itemID: ItemID, quantity: integer)Ссылки Прецеденты: Оформление продажиПредусловия Инициирована продажаПостусловия - Создан экземпляр sli класса SalesLineltem (создание экземпляра)- Экземпляр sli связан с текущим экземпляром класса Sale
(формирование ассоциации)-Атрибуту sli.quantity присвоено значение quantity (модификация
атрибута)- Экземпляр sli связан с классом ProductDescription на основе соот¬
ветствия идентификатора товара itemID (формирование ассоциации)Диаграмма взаимодействия должна обеспечивать выполнение постусловий опи¬
сания системной операции enterltem. Проектное решение принимается на основе
шаблонов GRASP.Выбор класса-контроллераКласс-контроллер должен обрабатывать сообщение системной операции
enterltem. Согласно шаблону Controller, в качестве контроллера будем использовать
класс Register, как и для операции makeNewSale.
Глава 18. Примеры объектного проектирования на основе шаблонов GRASP 357
Отображение описания товара и его ценыВ соответствии с шаблоном Model-View Separation, специальные объекты (такие,
как Register и Sale) не должны взаимодействовать с элементами уровня интерфей¬
са пользователя (например, графическими окнами). Поэтому на данном этапе ото¬
бражение описания товара и его цены не рассматривается.Пока достаточно лишь знать, что эти данные известны.Создание экземпляров SalesLineltemСреди постусловий в описании системной операции enterltem содержатся дан¬
ные о создании экземпляра объекта SalesLineltem, его инициализации и связи с
другими объектами. Анализируя модель предметной области, приходим к выводу, что
объект Sale содержит объекты SalesLineltem, в связи с чем именно этому классу
логично поручить создание экземпляров SalesLineltem.В таком случае со временем объект Sale будет связан с новым экземпляром кол¬
лекции продаваемых товаров. Из постусловий следует, что при создании экземпляра
SalesLineltem необходимо указывать количество единиц покупаемого товара, по¬
этому данное значение необходимо передавать из объекта Register объекту Sale,
который, в свою очередь, передаст его в качестве параметра сообщения create (на
языке Java это можно реализовать с помощью вызова конструктора с параметром).Таким образом, согласно шаблону Creator, для создания объекта SalesLineltem
объекту Sale передается сообщение makeLineltem. Объект Sale создает экземпляр
SalesLineltem, а затем хранит этот новый экземпляр в своем постоянном контей¬
нере.Параметрами сообщения makeLineltem являются количество единиц товара
quantity и спецификация товара ProductDescription, соответствующая коду това¬
ра itemID.Нахождение ProductDescriptionЭкземпляр SalesLineltem необходимо связать со спецификацией Product¬
Description, соответствующей коду данного товара itemID. Это означает, что не¬
обходимо уметь по коду товара находить значение ProductDescription.Прежде чем определять, как следует находить значение ProductDescription, не¬
обходимо решить, кто это будет делать. Для начала следует воспользоваться полез¬
ной рекомендацией.Распределение обязанностей необходимо начинать только после их изучения.Переформулируем задачу следующим образом.Кто должен отвечать за нахождение значения ProductDescription на основе
кода товара itemID?Эта проблема не является ни задачей создания экземпляра, ни задачей выбора
контроллера для системного события. Здесь впервые предоставляется возможность
использовать шаблон Information Expert.
358 Часть III. Первая итерация фазы развития — основыВ большинстве случаев здесь необходимо применить шаблон Expert, согласно кото¬
рому эта обязанность возлагается на объект, обладающий нужной информацией. Какой
класс обладает информацией о спецификациях товаров ProductDescription?Проанализировав модель предметной области, приходим к выводу, что класс
ProductCatalog логически содержит полную информацию о ProductDescription.
На основе структуры объектов предметной области можно разработать аналогичную
организацию программных классов: программный класс ProductCatalog будет со¬
держать программные классы ProductDescription.Следовательно, согласно шаблону Expert, класс ProductCatalog является хоро¬
шим кандидатом для реализации обязанности поиска, поскольку обладает полной ин¬
формацией обо всех объектах ProductDescription.Это можно реализовать, например, с помощью метода getProductDescription
(для краткости на некоторых диаграммах будем обозначать его getProductDesc).2Обеспечение видимости класса ProductCatalogКто должен отправлять сообщение getProductDescription классу ProductCatalog
с запросом на получение значения ProductDescription?Разумно предположить, что экземпляры объектов Register и ProductCatalog
должны быть созданы в процессе реализации прецедента Запуск системы (Start
Up), и между этими объектами должна устанавливаться постоянная связь. Согласно
такому предположению, отправку сообщения getProductDescription для класса
ProductCatalog можно поручить классу Register.Здесь возникает еще один важный вопрос объектно-ориентированного проекти¬
рования: вопрос видимости. Видимость (visibility) — это способность одного объекта
“видеть” другой объект или ссылаться на него.Для того чтобы один объект мог отправлять сообщения другому объекту, объект-
получатель должен находиться в области видимости объекта-отправителя.Поскольку мы предположили, что объект Register имеет постоянную связь с
объектом ProductCatalog (или ссылку на него), он может отправлять ему сообще¬
ния, в том числе сообщение getProductDescription.В следующей главе вопросы обеспечения видимости будут рассмотрены более под¬
робно.Окончательное проектное решениеНа диаграмме взаимодействия (рис. 18.7) и диаграмме классов (рис. 18.8) про¬
иллюстрированы описанные выше проектные решения и способы взаимодействия
объектов. На рис. 18.7 указано, какие шаблоны GRASP использованы в данном про¬
ектном решении.Заметим, что эта диаграмма построена в результате взвешенного применения шаб¬
лонов GRASP.2 В каждом языке приняты свои соглашения об именовании методов. В Java всегда исполь¬
зуется форма object.getFoo (), в C++ принято использовать обозначение object.foo (), а в
С# — object. Foo. В данной книге используется стиль Java.
Глава 18. Примеры объектного проектирования на основе шаблонов GRASP 359Рис. 18.7. Диаграмма взаимодействия (динамическая модель) для системной операции enteritemРис. 18.8. Диаграмма классов (статическая модель) для системной операции enteritemПолучение значения ProductDescription из базы данныхОчень нежелательно, чтобы в последней версии POS-системы NextGen все значе¬
ния ProductDescription хранились в оперативной памяти. Скорее всего, они будут
храниться в реляционной или объектной базе данных и извлекаться из нее по тре¬
бованию. Однако пока мы не будем рассматривать вопросы извлечения информации
из базы данных, а предположим, что все значения ProductDescription находятся в
оперативной памяти.
360 Часть III. Первая итерация фазы развития — основыВопросы обеспечения доступа к базе данных представляют особый интерес, тре¬
буют привлечения таких технологий, как Java или .NET. Они будут рассмотрены в
главе 38.Проектное решение: endSaleСистемная операция endSale выполняется при нажатии кассиром кнопки, свиде¬
тельствующем о завершении продажи. Вот полное описание этой операции.Описание операции ОПЗ: endSaleОперация endSale ()Ссылки Прецеденты: Оформление продажи
Предусловия Инициирована продажаПостусловия -Атрибут Sale.iscomplete принял значение true (модификация атрибута)Выбор класса-контроллераДля начала необходимо назначить обязанность, связанную с обработкой сообще¬
ния системной операции endSale. В соответствии с шаблоном Controller, в качестве
контроллера будем использовать класс Register, как и для системной операции
enterltem.Установка значения атрибута Sale.isCompleteЕдинственным постусловием в описании системной операции endSale является
следующее.■ Атрибут Sale.isComplete принял значение true (модификация атрибута).Если задача не сводится к созданию объекта или выбору контроллера (а в данном
случае так оно и есть), то первым шаблоном, который необходимо применить для ее
решения, является шаблон Expert.Какой класс должен отвечать за установку атрибута isComplete объекта Sale рав¬
ным значению true?Согласно шаблону Expert, эту обязанность следует возложить на класс Sale, по¬
скольку он владеет атрибутом isComplete. Тогда класс Register будет отправлять
объекту Sale сообщение becomeComplete, требующее установки этого атрибута в
значение true (рис. 18.9).3Рис. 18.9. Завершение продажи3 Это стиль программирования на Smalltalk. Для Java ближе использовать методsetComplete(true).
Глава 18. Примеры объектного проектирования на основе шаблонов GRASP 361
Вычисление общей стоимости покупкиРассмотрим фрагмент прецедента Оформление продажи.Основной успешный сценарий1. Покупатель подходит к кассовому аппарату POS-системы с выбранными товарами.2. Кассир открывает новую продажу.3. Кассир вводит идентификатор товара.4. Система записывает наименование товара и выдает его описание, цену и общую стоимость.
Цена вычисляется на основе набора правил.Кассир повторяет действия, описанные в пп. 3-4, для каждого наименования товара.5. Система вычисляет общую стоимость покупки с налогом.В соответствии с этим описанием, в п. 5 вычисляется общая стоимость товара.
Согласно шаблону Model-View Separation, на данном этапе не следует заботиться о
том, как будет отображаться общая стоимость покупки. Необходимо лишь удосто¬
вериться, что это значение известно. Заметим, что нельзя указать класс, которому
значение известно в данный момент, поэтому необходимо предусмотреть взаимодей¬
ствие между объектами, обеспечивающее выполнение данного требования, и постро¬
ить соответствующую диаграмму.Как обычно, если не ставится задача выбора контроллера и создания новых объек¬
тов (а в данном случае это именно так), следует применить шаблон Expert.Достаточно очевидно, что сам объект Sale должен отвечать за вычисление общей
стоимости покупки, однако для чистоты эксперимента проведем следующий анализ.1. Сформулируем обязанность.• Какой класс должен отвечать за вычисление общей стоимости покупки?2. Подытожим требуемую информацию.• Общая стоимость покупки равна сумме стоимостей каждого из покупаемых
товаров.• Стоимость каждого из покупаемых товаров равна произведению количества
единиц покупаемого товара и цены этого товара.3. Выпишем информацию, необходимую для выполнения данной процедуры, и
классы, обладающие этой информацией.Информация, необходимая для вычисления общей стоимости покупкиProductDescription.price
SalesLineltem.quantityВсе значения SalesLineltem для текущей продажи SaleПродолжим детальный анализ.■ Какой класс должен отвечать за вычисление общей стоимости продажи Sale?
Согласно шаблону Expert, это должен быть класс Sale, поскольку он обладает
информацией обо всех экземплярах SalesLineltem, стоимость которых сумми¬
руется при вычислении общей стоимости. Следовательно, класс Sale будет от-Классы-экспертыProductDescriptionSalesLineltemSale
362Часть III. Первая итерация фазы развития — основывечать за вычисление общей стоимости, и эта обязанность будет реализована в
виде метода getTotal.■ Для вычисления общей стоимости покупки Sale необходимо знать стоимость
каждого покупаемого товара SalesLineltem. Какой класс должен отвечать за
вычисление стоимости SalesLineltem? Согласно шаблону Expert, это должен
быть класс SalesLineltem, поскольку ему известно количество покупаемых еди¬
ниц товара и спецификация этого товара ProductDescription. Следовательно,
обязанность вычисления стоимости каждого товара, реализованная в виде ме¬
тода getSubtotal, должна возлагаться на класс SalesLineltem.■ Для вычисления стоимости каждого товара SalesLineltem необходимо знать
цену товара со спецификацией ProductDescription. Кто должен отвечать
за предоставление цены товара со спецификацией ProductDescription?
Согласно шаблону Expert, это должен быть класс ProductDescription, посколь¬
ку он инкапсулирует цену товара в качестве своего атрибута. Следовательно, эта
обязанность, реализованная в виде операции getPrice, возлагается на класс
ProductDescription.Хотя в данном конкретном случае проведенный анализ выглядит тривиальным, а
степень детализации избыточной, такую же стратегию следует применять и в бо¬
лее сложных ситуациях. Освоив эти принципы, вы сможете легко распределить
обязанности.Проектное решение Sale.getTotalОсновываясь на приведенных рассуждениях, можно построить диаграмму взаимо¬
действия, иллюстрирующую процесс передачи сообщения getTotal объекту Sale.
Первым на этой диаграмме является сообщение getTotal, однако это не сообщение
о системной операции (как enterltem или makeNewSale).Отсюда следует вывод.Не каждая диаграмма взаимодействия начинается с сообщения о системной опе¬
рации. Она может начинаться с любого сообщения, для которого необходимо по¬
казать виды взаимодействия между объектами.Диаграмма взаимодействия представлена на рис. 18.10. Сначала объекту Sale пере¬
дается сообщение getTotal. Затем объект Sale отправляет сообщение getSubtotal
каждому связанному с ним экземпляру SalesLineltem. В свою очередь, каждый эк¬
земпляр SalesLineltem отправляет сообщение getPrice связанному с ним объекту
ProductDescription.Поскольку арифметические действия обычно не изображаются с помощью сооб¬
щений, их можно проиллюстрировать путем добавления на диаграмму дополнитель¬
ной информации в виде ограничений или описаний алгоритма.Какой класс должен передавать сообщение getTotal объекту Sale? Скорее всего,
это должен быть объект уровня представления, например объект JFrame Java.Рис. 18.11 иллюстрирует использование обозначения метода в стиле UML2.0.
Глава 18. Примеры объектного проектирования на основе шаблонов GRASP 363Рис. 18.10. Диаграмма взаимодействия для метода Sale.getTotal«method»public void getTotal(){int tot = 0;for each SalesLineltem, sli
tot = tot + sli.getSubtotal();
return tot}Puc. 18.11. Использование обозначения метода
364 Часть III. Первая итерация фазы развития — основыПроектное решение: makePaymentСистемная операция makePayment выполняется при вводе кассиром внесенной за
покупку суммы. Вот полное описание этой операции.Описание операции ОП4: makePaymentОперация makePayment(amount: Money)Ссылки Прецеденты: Оформление продажиПредусловия Инициирована продажаПостусловия - Создан экземпляр р объекта Payment (создание экземпляра)-Атрибут p.amountTendered принял значение amount (модификацияатрибута)- Экземпляр р связан с текущим экземпляром класса Sale (формирование
ассоциации)- Текущий экземпляр Sale связан с экземпляром класса store для его до¬
бавления в журнал регистрации продаж (формирование ассоциации)Проектное решение должно обеспечить выполнение постусловий системной опе¬
рации makePayment.Создание экземпляра PaymentОдним из постусловий описания операции является следующее.■ Создан экземпляр р объекта Payment (создание экземпляра).При распределении обязанностей, связанных с созданием новых экземпляров, не¬
обходимо применять шаблон Creator.Какой класс записывает, агрегирует, наиболее активно использует или содержит
объекты Payment? Одним из кандидатов на выполнение этой обязанности может
быть класс Register, поскольку он по логике записывает сведения о платежах. При
таком проектном решении сокращается разрыв между терминологией предметной
области и именами программных классов. Еще одним кандидатом может высту¬
пать класс Sale, поскольку он наиболее активно использует информацию объекта
Payment.При определении класса, который должен создавать новые экземпляры, можно
также воспользоваться шаблоном Expert. При этом необходимо ответить на вопрос:
какой из классов является экспертом в смысле инициализации данных (в данном слу¬
чае— внесенной суммы)? Класс Register, выступающий в роли контроллера, получа¬
ет сообщение о системной операции makePayment, поэтому он изначально облада¬
ет информацией о внесенной сумме. Следовательно, класс Register снова является
кандидатом на выполнение этой обязанности.Таким образом, имеем двух кандидатов.■ Register■ SaleЭто приводит к необходимости применения главного принципа проектирования.
Глава 18. Примеры объектного проектирования на основе шаблонов GRASP 365СоветПри наличии двух альтернативных вариантов проектирования их следует рас¬
сматривать с точки зрения связывания и зацепления, г. также, по возможности,
будущих изменений. Выбор целесообразно остановить на варианте с хорошими
показателями в области связывания и зацепления, обладающем высокой устойчи¬
востью к возможным изменениям в будущем.Рассмотрим каждый из этих вариантов “с точки зрения” шаблонов High Cohesion
и Low Coupling. Если экземпляр объекта Payment создается классом Sale, то работа
(обязанности) класса Register облегчается. Кроме того, классу Register не нуж¬
но знать о существовании экземпляра Payment, поскольку он может записывать его
опосредованно через объект Sale. Это обеспечит низкий уровень связывания объек¬
та Register. Полученная диаграмма представлена на рис. 18.12.По шаблону ControllerПо шаблону Creator и Low Couplingо"-оО"""'••ОРис. 18.12. Диаграмма взаимодействия для операции Register.makePaymentЭта диаграмма взаимодействия удовлетворяет постусловиям, приведенным в опи¬
сании системной операции: создан экземпляр объекта Payment, связанный с объек¬
том Sale, и для данного платежа установлено значение amountTendered.Регистрация покупкиСведения о приобретенных покупках должны заноситься в журнал регистрации.
Как обычно, если задача не сводится к выбору контроллера или созданию новых
объектов (а в данном случае это именно так), при распределении обязанностей не¬
обходимо воспользоваться шаблоном Expert и ответить на следующий вопрос.Какой из классов обладает всей информацией о продажах и может выполнять
регистрацию?С точки зрения сокращения разрыва между терминологией предметной области и
именами программных классов лучше всего, чтобы всей необходимой информацией
обладал объект Store, поскольку он связан с финансовой деятельностью предприя¬
тия. В качестве второго варианта можно выбрать класс, реализующий традиционное
бухгалтерское понятие, например гроссбух Sales Ledge г. Однако вводить дополни¬
тельные объекты имеет смысл только при достаточном разрастании системы, когда
класс Store перестанет обладать свойством зацепления (рис. 18.13).
366 Часть III. Первая итерация фазы развития — основыРис. 18.13. Какой класс должен отвечать за информацию о совершен¬
ных покупках?Заметим, что среди постусловий в описании системной операции упоминается
связь объектов Sale и Store. Это пример ситуации, когда постусловие не обязатель¬
но нужно реализовывать в проекте. На ранних этапах разработки речь не шла об
объекте SalesLedger, однако сейчас стало ясно, что именно его можно использо¬
вать вместо Store. После принятия такого решения этот объект нужно будет также
добавить в модель предметной области, поскольку его имя соответствует понятию ре¬
ального мира. Это пример дополнительных исследований и изменений модели пред¬
метной области в процессе проектирования, предполагаемый в рамках итеративного
подхода к разработке системы.В данном случае мы будем придерживаться исходного плана и использовать
объект Store (рис. 18.14).
Глава 18. Примеры объектного проектирования на основе шаблонов GRASP 367Обратите внимание, что экземпляр sale
имеет имя s, так что его можно использовать
в качестве параметра сообщений 2 и 2.1""""ОРис. 18.14. Регистрация совершенной покупкиВычисление причитающейся сдачиТеперь необходимо реализовать процесс вычисления причитающейся сдачи, сум¬
ма которой должна отображаться на экране и печататься на чеке. Эта операция вы¬
полняется в рамках прецедента Оформление продажи.Согласно основному принципу шаблона Model-View Separation, сейчас не стоит
акцентировать внимание на способе отображения суммы сдачи, однако необходимо
убедиться, что эта сумма известна. Заметим, что в настоящее время ни один из клас¬
сов не обладает такой информацией, поэтому необходимо разработать диаграмму
взаимодействия, которая будет обеспечивать выполнение данного требования.Как обычно, если задача не сводится к выбору контроллера или к созданию но¬
вых объектов (а в данном случае это именно так), при распределении обязанностей
необходимо воспользоваться шаблоном Information Expert и ответить на следующий
вопрос.Какой из классов отвечает за вычисление суммы сдачи (баланса торговой опе¬
рации)?Для вычисления баланса необходимо знать общую стоимость покупки и внесен¬
ную покупателем сумму. Следовательно, при решении этой проблемы в качестве ча¬
стичных экспертов должны выступать классы Sale и Payment.Если основная обязанность по вычислению баланса возлагается на класс Payment,
то для него следует обеспечить видимость класса Sale, с помощью которого необ¬
ходимо получить общую стоимость покупки. Такой подход повышает уровень свя¬
зывания классов в проекте и не соответствует основному принципу шаблона Low
Coupling.Если же основная обязанность по вычислению баланса возлагается на класс Sale,
то для него следует обеспечить видимость класса Payment, от которого необходимо
получить внесенную покупателем сумму. Поскольку класс Sale является создателем
368 Часть III. Первая итерация фазы развития — основыэкземпляров Payment, такая видимость уже обеспечена, и данный подход не повы¬
шает уровень связывания классов в проекте, что соответствует основному принципу
шаблона Low Coupling и, следовательно, является более предпочтительным.Таким образом, диаграмма взаимодействия приобретает следующий вид (рис. 18.15).{ bal = pmt.amount - s.total }d2:t=getTotalPuc. 18.15. Диаграмма взаимодействия для операции Sale.getBalanceОкончательное проектное решение для первой
итерации разработки приложения NextGenНа рис. 18.16 показана диаграмма классов, иллюстрирующая описанные в этой
главе проектные решения, связанные с первой итерацией реализации прецедента
Оформление продажи. Конечно, в процессе написания кода предстоит еще много
работы по проектированию, в том числе касающейся проектирования интерфейса
пользователя и уровня служб.Storeaddress:Address
name:TextregistercatalogProductCataloggetProductDesc(descriptions{Map}1..*ProductDescriptiondescription:Text
price:Money
itemID:ItemIDRegisterendSale()
enterltem(...)
makeNewSale()
makePayment(...)currentSaleSaleisComplete:Boolean
time:DateTimebecomeComplete()
makeLineItem(...)
makePayment(...)
getTotal()completedSales{ordered}lineltems
{ordered}
 >1.SalesLineltemquantity:IntegergetSubtotal()payment
 >Paymentamount:MoneyPuc. 18.16. Более полная диаграмма классов, отражающая принятые проектные решения
Глава 18. Примеры объектного проектирования на основе шаблонов GRASP 369Подключение уровня интерфейса пользователя
к уровню предметной областиОсновные проектные решения, обеспечивающие видимость объектов уровня
предметной области для объектов уровня пользовательского интерфейса, сводятся к
следующему.■ Инициализирующий объект (например, объект Factory), вызываемый из мето¬
да запуска приложения (в Java — main), создает и объекты уровня пользователь¬
ского интерфейса, и объект предметной области, а затем передает этот объект
на уровень интерфейса пользователя.■ Объект пользовательского интерфейса получает объект предметной области из
стандартного источника, например, от объекта-фабрики, отвечающего за созда¬
ние объектов предметной области.Будучи связанным с экземпляром объекта Register (выступающим в данном при¬
ложении в роли внешнего контроллера), объект уровня пользовательского интер¬
фейса может направить ему сообщение о системном событии, такое как enterltem
или endSale (рис. 18.17).Рис. 18.17. Связь уровней предметной области и пользовательского интерфейса
370 Часть III. Первая итерация фазы развития — основыДля передачи сообщения enterltem необходимо иметь диалоговое окно, в кото¬
ром будет отображаться общая стоимость каждого товара. При этом можно использо¬
вать несколько проектных решений.■ Добавить объекту Register метод getTotal. Тогда с уровня пользовательско¬
го интерфейса объекту Register будет передаваться сообщение getTotal,
а этот объект, в свою очередь, перенаправит это сообщение объекту Sale.
Преимуществом такого подхода является низкая степень связывания между
уровнями пользовательского интерфейса и предметной области — пользова¬
тельскому интерфейсу известен лишь один объект Register. Однако при этом
“раздувается” интерфейс объекта Register, что приводит к слабой степени за¬
цепления этого объекта.■ Интерфейс пользователя запрашивает ссылку на текущий объект Sale, а затем
при необходимости вычисления общей стоимости (или для получения любой
другой информации о продаже) он передает сообщение напрямую объекту
Sale. Такое проектное решение повышает степень связывания между уровнями
пользовательского интерфейса и предметной области. Однако, как указывалось
при рассмотрении шаблона GRASP Low Coupling, высокая степень связывания
сама по себе не является проблемой. Проблема возникает при связывании с не¬
устойчивыми объектами. Объект Sale можно считать устойчивым, поскольку
он является неотъемлемой частью проектного решения. Следовательно, связы¬
вание с этим объектом не составляет проблемы.Как видно из рис. 18.18, в проектном решении для данного приложения выбран
второй подход.Рис. 18.18. Взаимодействие уровней пользовательского интерфейса и предметной области
Глава 18. Примеры объектного проектирования на основе шаблонов GRASP 371Инициализация приложения и прецедент Запуск системыКогда разрабатывать проектное решение
для инициализации системыПрактически все системы включают прецедент Запуск системы (Start Up) и не¬
которую исходную системную операцию, связанную с запуском приложения. Хотя си¬
стемная операция startup выполняется одной из первых, ее диаграмму взаимодей¬
ствия разрабатывают после рассмотрения всех остальных системных операций. При
таком подходе гарантируется, что к моменту разработки системной операции startup
известна вся существенная информация, связанная с инициализацией системы и необ¬
ходимая для поддержки диаграмм взаимодействия последующих системных операций.СоветПроектное решение для инициализации приложения разрабатывается в послед¬
нюю очередь.Как запускаются приложенияСистемная операция startup — это абстрактное представление этапа инициали¬
зации при запуске приложения. Чтобы разобраться, как разрабатывать диаграмму
взаимодействия для такой операции, необходимо понять основные принципы запу¬
ска приложения. Способ запуска приложения и инициализации данных зависит от
операционной системы и выбранного языка программирования.В любом случае, как правило, разрабатывается исходный объект предметной области
(initial domain object), который создается первым среди других объектов предметной
области. Операция создания объекта может выполняться явно в методе main либо в
объекте Factory, к которому обращается метод main.После создания исходного объекта предметной области ему в обязанность вменя¬
ется создание дочерних объектов предметной области. Например, если в качестве
исходного объекта предметной области выбран объект Store, то он может отвечать
за создание объекта Register.Например, в приложении Java для создания исходного объекта предметной обла¬
сти можно использовать метод main или делегировать обязанность создания этого
объекта, в соответствии с шаблоном Factory, объекту-фабрике.public class Main
{public static void main(String[] args){// Store - исходный объект предметной области.//Он отвечает за создание других объектов предметной области.Store store = new Store ();Register register = store.getRegister() ;ProcessSaleJFrame frame = new ProcessSaleJFrame(register);}}
372 Часть III. Первая итерация фазы развития — основыВыбор исходного объекта предметной областиКакой класс следует выбрать в качестве исходного объекта предметной области?СоветВ качестве исходного объекта предметной области выбирается класс, макси¬
мально приближенный к корню иерархии агрегации объектов предметной обла¬
сти. В качестве такого объекта можно выбрать внешний контроллер, такой как
Register, или любой другой объект, содержащий все или большую часть других
объектов предметной области, например Store.Выбор между этими объектами осуществляется на основе шаблонов High Cohesion
и Low Coupling. В рассматриваемом приложении выберем в качестве исходного
объекта класс Store.Проектное решение: Store, create ()Задачи создания и инициализации возникают в процессе проектирования прило¬
жения, в частности при разработке проектного решения для операции enterltem.
Из рассмотренных выше диаграмм взаимодействия следует необходимость инициа¬
лизации для следующих объектов.■ Необходимо создать экземпляры объектов Store, Register, ProductCatalog и
ProductDescription.■ Объект ProductCatalog необходимо связать с объектом ProductDescription.■ Объект Store необходимо связать с объектом ProductCatalog.■ Объект Store необходимо связать с объектом Register.■ Объект Register необходимо связать с объектом ProductCatalog.На рис. 18.19 показано соответствующее проектное решение. Для создания объек¬
тов ProductCatalog и Register, согласно шаблону Creator, был выбран объект Store.
В процессе аналогичных рассуждений для создания объектов ProductDescription
был выбран объект ProductCatalog. Напомним, что такой подход к созданию специ¬
фикации можно рассматривать лишь как временный. При окончательном проектиро¬
вании эти объекты при необходимости будут материализовываться из базы данных.Обозначение UML: обратите внимание, что создание всех экземпляров Product¬
Description и их добавление в контейнер обозначено символом *, следующим за по¬
рядковым номером операции.Интересное различие между этапами анализа и проектирования состоит в том,
что объект Store создает лишь один объект Register. В реальной жизни магазин мо¬
жет содержать множество терминалов POS-системы. Однако мы рассматриваем про¬
граммный продукт. Поэтому согласно требованиям к системе, программный объект
Store должен создать единственный экземпляр программного объекта Register.Количество классов и объектов в моделях предметной области и проектирования
может различаться.
Глава 18. Примеры объектного проектирования на основе шаблонов GRASP 373Рис. 18.19. Создание исходного объекта предметной области и последующих объектов18.5. Реализация прецедентов для игры “Монополия”Читателю может показаться, что данный пример можно пропустить, поскольку он
не имеет коммерческого значения. Однако это не так. При реализации данного при¬
ложения возникает множество логически непростых моментов, особенно на после¬
дующих итерациях. При разработке этого приложения иллюстрируется применение
базовых принципов проектирования — шаблонов Information Expert, High Cohesion
и Low Coupling.На первой итерации разрабатывается сценарий прецедента Игра Монополия в
упрощенном виде. В рамках этого сценария определяются две системные операции:
initialize (или startup и playGame). Следуя приведенным выше рекомендациям,
проектное решение для инициализации приложения будет разрабатываться в послед¬
нюю очередь, а сначала будет реализована операция playGame.Для сокращения разрыва в представлении объектов в моделях предметной обла¬
сти и проектирования обратимся к рис. 18.20, на котором представлена модель пред¬
метной области для данной игры. Принятые здесь обозначения будут учитываться
при создании модели проектирования.
374 Часть III. Первая итерация фазы развития — основыПроектное решение для реализации операции playGameСистемная операция playGame вызывается в тот момент, когда пользователь вы¬
бирает некоторую команду интерфейса, например щелкает на кнопке Начать игру,
чтобы запустить процесс игры.Мы не станем детально описывать прецеденты или системные операции для
данного примера, поскольку большинство читателей знакомы с правилами игры.
Сосредоточимся не на формулировке требований, а на проектном решении.Jit1RectMOI 0-% 1QРис. 18.20. Модель предметной области для первой итерации разработки игры “Монополия ”Выбор класса-контроллераСначала необходимо выбрать объект-контроллер для сообщения о системной опе¬
рации playGame, поступающего с уровня интерфейса пользователя на уровень пред¬
метной области. Согласно шаблону Controller, возможны следующие варианты про¬
ектных решений.Класс представляет всю систему в целом,
“корневой объект”, специализированное
устройство или подсистему.Класс является получателем или обработ¬
чиком всех системных событий для неко¬
торого сценария прецедента.MonopolyGame — корневой объект, в контек¬
сте которого работает большинство осталь¬
ных объектов предметной области.
MonopolyGameSystem— представляет всю
систему.PlayMonopolyGameHandler — имя формирует¬
ся по принципу <имя_прецедента>Handler.
PlayMonopolyGameSession
Глава 18. Примеры объектного проектирования на основе шаблонов GRASP 375Выбор корневого объекта в качестве внешнего контроллера, например класса
MonopolyGame (на рис. 18.21 — MGame), обоснован в том случае, если в приложении су¬
ществует лишь несколько системных операций и на внешний контроллер будет возло¬
жено не слишком много обязанностей (другими словами, не нарушится зацепление).Рис. 18.21. Применение шаблона Controller для системной операции playGameАлгоритм реализации главного циклаПрежде чем переходить к проектным решениям, рассмотрим базовый алгоритм
реализации игры. Сначала введем некоторые термины.■ Ход (turn) — это бросание игральной кости и перемещение фишки одним игро¬
ком.■ Круг (round) — однократная последовательность ходов всех игроков.Теперь опишем главный цикл игры.для N круговдля каждого игрока Player р
р делает один ходНапомним, что на первой итерации разработки победитель не определяется, по¬
этому игра просто продолжается в течение N кругов.Кто отвечает за управление главным циклом игрыРассмотрим этот алгоритм подробнее. Первая задача — управление главным ци¬
клом игры в течение N кругов, при котором на каждом круге каждый из игроков
делает один ход. Это обязанность действия, поэтому решение данной проблемы воз¬
лагается не на шаблоны Creator и Controller, а на шаблон Expert. При реализации
шаблона Expert необходимо ответить на вопрос: “Какая информация необходима для
выполнения данной обязанности?”. Приведем некоторые результаты анализа.Необходимая информация Кто ею обладаетКоличество пройденных кругов Такой объект пока не существует, но данную обязанность можновозложить на объект MonopolyGameСведения обо всех игроках (необ- Учитывая модель предметной области, эту обязанность следует
ходимые для выполнения ходов) возложить на объект MonopolyGame
376 Часть III. Первая итерация фазы развития — основыТаким образом, согласно шаблону Expert, контролировать главный цикл игры
и координировать действия игроков в течение каждого раунда должен объект
MonopolyGame. На рис. 18.22 эта ситуация проиллюстрирована средствами UML.
Обратите внимание на применение закрытого (внутреннего) вспомогательного мето¬
да playRound (сыграть круг). Он призван решить две задачи.1. Выделить логику организации одного круга игры в отдельный метод. Это спо¬
собствует повышению зацепления и выделению отдельных фрагментов поведе¬
ния.• При хорошем объектном проектном решении создают небольшие методы,
каждый из которых решает одну конкретную задачу. Это соответствует ша¬
блону High Cohesion на уровне методов.2. Имя playRound выбрано из словаря предметной области. Подобные решения
улучшают согласованность моделей предметной области и проектирования.Рис. 18.22. Цикл игрыКто делает ходКаждый ход предполагает бросание кубика и перемещение фишки на выпавшее
количество клеток.Какой объект должен отвечать за ход каждого игрока? Это тоже обязанность дей¬
ствия, поэтому для ее распределения применяется шаблон Expert.На первый взгляд, может показаться, что за каждый ход должен отвечать соот¬
ветствующий объект Player (Игрок), поскольку в реальном мире ход делает именно
участник игры. Однако (и это ключевой момент) объектно-ориентированное проек¬
тирование — это не слепая эмуляция предметной области, особенно с учетом специ¬
фики человеческого поведения. Если воспользоваться рекомендацией (ошибочной)
придерживаться аналогии и распределять обязанности между программными объек¬
тами в точном соответствии с выполнением обязанностей людьми, то в предметной
области POS-систем программный объект Cashier (Кассир) должен выполнять поч¬
ти всю работу. А это противоречит принципам High Cohesion и Low Coupling.
Глава 18. Примеры объектного проектирования на основе шаблонов GRASP 377Наоборот, при объектном проектировании обязанности распределяются между
многими объектам согласно принципу Information Expert и многим другим.Следовательно, для выполнения этой обязанности не нужно создавать объект
Player в соответствии с ситуацией с предметной областью.Шаблон Expert не учитывает особенности поведения объектов в предметной об¬
ласти, а требует ответа на вопрос: “Какая информация необходима для выполнения
данной обязанности?”. Приведем некоторые результаты анализа.Необходимая информацияКто ею обладаетТекущее положение игрока
(начальная точка для данного хода)Информация о двух объектах Die
(Игральная кость) (результата их вбра¬
сывания и сума выпавших очков)Данные обо всех клетках на поле
и их взаимное расположениеСогласно модели предметной области, объект Piece
(Фишка) обладает информацией о клетке Square, на которой
он расположен, а объект Player обладает всеми данными
о соответствующей фишке (объекте Piece). Таким образом
программный объект Player может получить информацию о
текущем положении фишкиУчитывая модель предметной области, эту обязанность сле¬
дует возложить на объект MonopolyGame, поскольку играль¬
ные кости являются частью игрыДля выполнения этой обязанности лучше всего подойдет
объект Board (Доска)Возникла интересная ситуация. Обнаружены три потенциальных информацион¬
ных эксперта, претендующих на выполнение обязанностей по обеспечению хода:
Player, MonopolyGame и Board. Для решения этой проблемы и выбора соответству¬
ющего проектного решения нужно принять во внимание несколько рекомендаций.Рекомендация. Если имеется несколько частичных информационных экспертов,
соответствующую обязанность необходимо возложить на доминантный объект, т.е.
объект, обладающий большей частью информации. Такой подход соответствует прин¬
ципу Low Coupling.К сожалению, в данном случае возможности всех информационных экспертов
примерно равны, поэтому доминантный объект выделить невозможно. Попробуем
воспользоваться еще одной рекомендацией.Рекомендация. При наличии нескольких вариантов выбора следует рассмотреть
степень связывания и зацепления при каждом из них, а затем выбрать наилучший
вариант.Эту рекомендацию можно применить в данной ситуации. Поскольку объект
MonopolyGame уже выполняет некоторые обязанности, дополнительные функции не¬
гативно повлияют на степень его зацепления, особенно по сравнению с объектами
Player и Board, которые пока не выполняют никаких действий. Однако даже с уче¬
том этого возникают две возможных альтернативы.Воспользуемся еще одной рекомендацией.Рекомендация. Если нельзя определить объект, наилучший с точки зрения связы¬
вания зацепления, следует принять во внимание возможную будущую эволюцию про¬
граммных объектов и их соответствие принципам Information Expert, High Cohesion
и Low Coupling.Например, на первой итерации для выполнения хода требуется совсем немного
информации. Однако рассмотрим полный набор правил игры, которые будут реа-
378 Часть III. Первая итерация фазы развития — основылизованы на последующих итерациях. Тогда каждый ход будет связан с покупкой не¬
движимости при наличии достаточного количества денег. При этом действия игрока
зависят от выбранной стратегии. Какой объект будет обладать информацией о плате¬
жеспособности игрока? Ответ прост: объект Player. Какой объект будет отвечать за
выбранную стратегию? Тот же ответ: объект Player.Таким образом, наилучшим кандидатом на выполнение этой обязанности в соот¬
ветствии с шаблоном Expert с учетом полных правил игры является объект Player.Наконец-то! Мы смогли это детализировать.Конечно же, данное обсуждение является чересчур детальным. Однако если чита¬
тель понял приведенные рекомендации и сможет воспользоваться ими в других
ситуациях, то усилия автора не пропали зря и данная книга послужит полезными
пособием по ООА/П.На рис. 18.23 показаны полученные решения в виде динамических и статических
диаграмм проектирования.Применение UML. Обратите внимание, что сообщение takeTurn (сделать ход) от¬
правляется каждому игроку в коллекции players.£+ИС«л«Рис. 18.23. Согласно шаблону Expert за выполнение хода отвечает объект Player
Глава 18. Примеры объектного проектирования на основе шаблонов GRASP 379Выполнение ходаВыполнение хода означает следующее.1. Вычисление случайного числа в диапазоне от 2 до 12 (сумма значений двух
игральных костей).2. Вычисление нового положения фишки.3. Перемещение фишки на новое место.Сначала решим проблему вычисления случайного числа. Согласно модели пред¬
метной области, следует создать объект Die с атрибутом faceValue. Вычисление но¬
вого случайного значения faceValue означает изменение значения атрибута объекта
Die, поэтому согласно принципу Expert этот объект должен содержать метод вбра¬
сывания (т.е. генерирование нового случайного значения), результаты которого при¬
сваиваются атрибуту faceValue.Теперь обратимся ко второй задаче. С учетом модели предметной области целесо¬
образно возложить обязанность знания обо всех клетках на объект Board. Тогда этот
объект будет отвечать и за вычисление нового положения фишки на основе ее пред¬
ыдущего положения и выпавшего значения игральных костей.Теперь рассмотрим третью задачу (перемещение фишки). Понятно, что объект
Player должен обладать информацией о своей фишке, которая, в свою очередь,
имеет данные о своем местоположении (можно даже напрямую связать местоположе¬
ние Square с объектом Player). Тогда, согласно шаблону Expert, объект Piece будет
определять новое положение фишки либо получать его от объекта-агрегата Player.Кто отвечает за координацию действий?Все три описанные выше задачи должен координировать некий объект. Поскольку
за выполнение хода отвечает объект Player, он должен также координировать реше¬
ние этих задач.Проблема видимостиПоскольку объект Player координирует несколько функций, он должен вступать
во взаимодействие с объектами Die, Board и Piece. При этом возникает проблема
видимости (visibility) — объект Player должен содержать ссылки на перечисленные
объекты.Учитывая сказанное, объект Player должен быть связан с другими объектами при
выполнении каждого хода, поэтому его нужно инициализировать при запуске игры и
обеспечить для него постоянные ссылки на другие объекты.Окончательное проектное решение для операции playGameОписанные проектные решения в полном виде представлены на рис. 18.24 (дина¬
мическая модель) и рис. 18.25 (статическая модель). Заметим, что каждое сообщение
и каждая обязанность были методически спланированы согласно шаблонам GRASP.
Освоив эти принципы, читатель сможет рассуждать и оценивать существующие про¬
ектные решения в терминах уровня связывания, степени зацепления и т.п.
380 Часть III. Первая итерация фазы развития — основынг)pU^.W*dljt«.k<T»u>fVttO: •^VgToKMсеУоАчс.:&OAr<(]шшяшшшшттшшш *т"м"т1*шятшшштшM4.u<» *р^*ШмЛЛА ViS^y »;
 * MsHamfrndi (new Uoc)Puc. 18.24. Динамическая модель для операции playGameПрименение UML.■ На рис. 18.24 показаны две диаграммы последовательностей. На первой из них
сообщение takeTurn объекту Player не детализировано. Такой стиль построе¬
ния диаграмм является довольно распространенным при быстром моделирова¬
нии вручную. Каждая подобная диаграмма должна быть не слишком большой.
Приведенные на рисунке диаграммы являются довольно неформальными. При
более формальном подходе необходимо использовать фреймы sd и ref. Это
легко сделать при использовании соответствующих средств автоматического
проектирования с использованием UML. Однако при построении диаграмм
вручную строго придерживаться всех обозначений необязательно.■ Обратите внимание на сообщения roll и getFaceValue объекту Die. Они по¬
мещены во фрейм цикла, чтобы указать, что данная операция выполняется для
каждого элемента коллекции.■ Обратите внимание на параметр fvTot в сообщении GetSquare. Здесь сделано
неформальное допущение, что данный параметр содержит значение атрибута
f aceValue объекта Die. Такая неформальность допустима при изображении диа¬
грамм на доске в предположении, что окружающие понимают, о чем идет речь.
Глава 18. Примеры объектного проектирования на основе шаблонов GRASP 381Принцип разделения команд и запросовОбратите внимание, что на рис. 18.24 за сообщением roll для объекта Die есть
еще одно сообщение, getFaceValue, предполагающее получение нового значения
faceValue. При этом метод roll не содержит возвращаемого значения (тип возвра¬
щаемого значения этого метода — void). Приведем пример.//стиль 1; используется в принятом проектном решении
public void roll (){facevalue = // генерация случайного числа}public int getFaceValue (){return faceValue;}Почему бы не объединить эти две функции в методе roll, возвращающем новое
значение faceValue?//стиль 2; почему это неправильно?
public int roll(){faceValue = // генерация случайного числа
return faceValue;}
382 Часть III. Первая итерация фазы развития — основыСуществует множество примеров кода, написанного в стиле 2, однако это пло¬
хие примеры, поскольку они не соответствуют принципу разделения команд и запросов
(CQS— Command Query Separation) [93]. Согласно этому принципу каждый метод
должен представлять собой:■ либо команду, выполняющую определенные действия (обновление, координа¬
цию и т.д.), возможно, сопровождаемую побочным эффектом в виде состояния
объекта; такой метод не должен возвращать значение;■ либо запрос, возвращающий данные в вызывающую среду и не сопровождае¬
мый побочными эффектами (он не должен изменять состояние какого-либо
объекта).Однако никакой метод не должен совмещать в себе и команду и запрос.Метод roll является командой, поскольку изменяет состояние атрибута faceValue
объекта Die. Следовательно, он не должен возвращать новое значение faceValue.
Эту обязанность необходимо возложить на метод-запрос, не возвращающий никакого
значения.В чем проблемаПринцип разделения команд и запросов широко распространен в теории компью¬
терных наук, поскольку он позволяет определить состояние объектов программной
системы без изменения этого состояния. Его применение упрощает проектное реше¬
ние для всей системы. Например, если приложение написано в стиле CQS, то мож¬
но быть уверенным, что все методы get не модифицируют никаких данных, а мето-
ды-команды не возвращают значений. Все довольно просто и соответствует другому
принципу разработки — принципу минимизации сюрпризов (principle of least surprise).Рассмотрим следующий контрпример, в котором метод-запрос нарушает принцип
CQS.Missile m = new Missile();//выглядит довольно безобидноString name = m.getName();public class Missile{ ...//. . .public String getName(){launch (); // запуск ракеты
return name;}} // конец классаИнициализация и прецедент Запуск системыОбычно операция инициализации реализуется в рамках прецедента Запуск
системы. При таком проектном решении сначала необходимо выбрать корневой объ¬
ект, который будет создавать другие объекты. Например, в качестве корневого объ¬
екта может выступать MonopolyGame. Этот объект может создавать объекты Board
Глава 18. Примеры объектного проектирования на основе шаблонов GRASP 383и Player, a Board в свою очередь может создавать объекты Square. Это проектное
решение можно отобразить на диаграмме взаимодействия, но автор предпочел вос¬
пользоваться диаграммой классов и стереотипом «create». На рис. 18.26 показана
статическая диаграмма, отражающая логику создания объектов без излишних дета¬
лей. В данном случае это допустимо, поскольку детали процедуры создания объектов
можно продумать уже на стадии написания кода.' - ^ Pitce"I—._____Рис. 18.26. Создание зависимостей18.6. Итеративное и эволюционное
объектное проектированиеВ последних нескольких главах много говорилось об итеративном и эволюцион¬
ном процессе реализации прецедентов.При этом следует придерживаться такого принципа: как можно скорее перехо¬
дить к написанию кода и тестированию, не стараясь слишком детализировать модели
UML. Моделируйте только наиболее нетривиальные и сложные фрагменты объект¬
ного решения.На рис. 18.27 приведены рекомендации по выполнению этой работы.Реализация прецедентов в рамках UPРеализация прецедентов — составная часть процесса создания модели проектиро¬
вания в рамках UP (табл. 18.1).
384 Часть III. Первая итерация фазы развития — основыКогдаВ начале каждой итерации, в течение
небольшого промежутка времени
перед началом программированияГдеВ специальном помещении
со средствами создания
диаграмм и их просмотраЯнварь/ Февралц/11«г///%гДве смежных области
просмотраВозможно, разработчики будут
выполнять работу по проектированию
попарно. Архитектор программной
системы будет взаимодействовать с
ними, руководить и контролировать
различные группы разработки/ Как: средстваПрограммное обеспечение: CASE-средство споддержкой UML, предоставляющее
1 возможности обратного проектирования
\ диаграмм на основе программного кода.\v Аппаратные средства.- Два проектора, подключенных к
видеоадаптерам с двумя входами.- Для диаграмм на доске, возможно,
потребуется цифровой фотоаппарат.- Плоттер для печати важных диаграмм
большого размера, которые можно
развесить на стенахРис. 18.27. Примерный график процесса разработки
Глава 18. Примеры объектного проектирования на основе шаблонов GRASP 385Таблица 18.1. Пример планирования сроков реализации артефактов UP
(н — начало, р — развитие)ДисциплинаАртефактИтерация-»НачалоИРазвитиеЕ1..ЕпКонструи- п
рование Vi т£г
C1..Cn Т1"Тп“Бизнес-Модель предметной областинмоделирование”“Требования”Модель прецедентовнРДополнительная спецификациянРСловарь терминовнР“Проектирование”Модель проектированиянРОписание архитектурынМодель данныхнРНачало — разработка модели проектирования и реализация прецедентов обычно
начинаются на стадии развития, поскольку эти виды деятельности требуют принятия
подробных проектных решений, для которых на начальной стадии отсутствует не¬
обходимая информация.Развитие — в течение этой фазы обеспечивается реализация прецедентов для
большинства архитектурно значимых или рискованных сценариев. Однако диаграм¬
мы UML строятся не для всех сценариев и необязательно прорабатываются в дета¬
лях. Главное построить диаграммы прецедентов для основных сценариев, сконцен¬
трировав внимание на важнейших проектных решениях.Конструирование — выполняется реализация остальных прецедентов.18.7. РезюмеРазработка способов взаимодействия между объектами для обработки сообщений
и распределение обязанностей — основные процессы объектно-ориентированного
проектирования. Решение этих задач оказывает существенное влияние на расширяе¬
мость, прозрачность объектно-ориентированной системы, а также на качество, воз¬
можность поддержки и повторного использования разрабатываемых компонентов.
Существуют строгие принципы распределения обязанностей. Наиболее важные и
типичные из них сформулированы в виде шаблонов GRASP.13 3ak. 3357
Области видимостиМатематик — это устройство для преобразования кофе в теоремы.Поль Эрдос (Paul Erdos)Основные задачи■ Ознакомиться с четырьмя типами видимости.■ Установить области видимости.ВведениеОбласти видимости обеспечивают способность одного объекта видеть другой
объект или ссылаться на него. В этой главе рассматриваются вопросы, связанные с
обеспечением видимости объектов в процессе проектирования.Что дальше?Проектирование
объектов
с помощью
шаблонов
GRASPо После изучения конкретных примеров в данной главе проясняются аспекты
проектирования видимости между объектами. Следующая глава посвящена
вопросу преобразования проектного решения в программный код на объектно-
ориентированном языке/Примерыпроектированияобъектов\ПроектированиеобластейвидимостиПреобразование
проектного
решения
в программный
код О Разработка
на основе
тестирования
и рефакторинг
388 Часть III. Первая итерация фазы развития — основы19.1. Видимость объектовОбъектные решения, разработанные для системных событий (enterltem и т.д.),
иллюстрируют процесс передачи сообщений между объектами. Но чтобы некоторый
объект-отправитель мог отослать сообщение объекту-получателю, получатель должен
быть виден отправителю, т.е. отправитель должен содержать некую ссылку или указа¬
тель на объект-получатель.Например, для отправки сообщения getProductDescription от объекта
Register к объекту ProductCatalog необходимо обеспечить видимость экземпляра
объекта ProductCatalog для экземпляра объекта Register (рис. 19.1).При разработке взаимодействующих между собой объектов следует обеспечить
необходимый для передачи сообщений уровень видимости.В языке UML для иллюстрации областей видимости существуют специальные обо¬
значения.class Register Щ{private ProductCatalog catalog;О "Оenterltem:Register:ProductCatalog(itemID,quantity)11ilОwdesc=getProductDesc(itemID)hr1►Ipublic void enterltem(itemID, qty){desc=catalog.getProductDesc(itemID)Puc. 19.1. Необходимость обеспечения видимости объекта ProductCatalog
для объекта Register11 В этом и последующих примерах фрагментов кода для обеспечения ясности изложения
может применяться упрощенный синтаксис языка программирования.
Глава 19. Области видимости 38919.2. Области видимостиВ обычном понимании область видимости (visibility) обеспечивает способность
одного объекта видеть другой объект или ссылаться на него. В более общем смысле
это понятие связано с понятием контекста (или области действия): попадает ли один
ресурс (например, экземпляр объекта) в контекст другого? Существует четыре основ¬
ных способа обеспечения видимости объекта В объектом А.1. Посредством атрибутов. Объект В является атрибутом объекта А.2. Посредством параметров. Объект В является параметром метода объекта А.3. Локальная видимость. Объект В объявлен как локальная переменная в методе
объекта А.4. Глобальная видимость. Объект В каким-то образом виден глобально.При рассмотрении вопросов видимости объектов используется следующая моти¬
вация.Для отправки сообщения от объекта А к объекту В необходимо, чтобы объект В
был виден объекту А.Например, для создания диаграммы взаимодействия, на которой сообщение пере¬
дается от экземпляра объекта Register к экземпляру ProductCatalog, необходимо,
чтобы объект ProductCatalog был виден объекту Register. Типичным решением
такой проблемы является использование ссылки на экземпляр ProductCatalog в ка¬
честве атрибута объекта Register.Обеспечение видимости посредством атрибутовВидимость посредством атрибутов (attribute visibility) между объектами А и В суще¬
ствует в том случае, когда В является атрибутом А. Такой тип видимости можно на¬
звать постоянным, поскольку видимость между объектами поддерживается до тех
пор, пока существуют сами объекты. В объектно-ориентированных системах это
очень популярная форма обеспечения видимости.В качестве примера рассмотрим определение класса Register на языке Java, в
котором обеспечивается видимость объекта ProductCatalog посредством атрибутов
(переменных-членов Java).public class Register{private ProductCatalog catalog;}Такая видимость между объектами необходима, поскольку на диаграмме взаимо¬
действия для события enterltem, представленной на рис. 19.2, объект Register от¬
правляет сообщение getProductDescription объекту ProductCatalog.
390 Часть III. Первая итерация фазы развития — основыclass Register I{private ProductCatalog catalog;-:;;,'
} "■кpublic void enterltem(itemID, qty){-O spec = catalog.getProductDesc(itemID)}enterltem:Register:ProductCatalog(itemID,quantity)desc=getProductDesc(itemID)Puc. 19.2. Видимость, обеспеченная с помощью атрибутовОбеспечение видимости посредством параметровВидимость между объектами А и В посредством параметров (parameter visibility) суще¬
ствует в том случае, если объект В передается в качестве параметра метода объекту
А. Это “вршенная” видимость, поскольку она существует только в контексте данного
метода. После видимости, обеспечиваемой с помощью атрибутов, это второй по рас¬
пространенности тип обеспечения видимости в объектно-ориентированных системах.В качестве примера можно привести процесс передачи сообщения make Line Item
экземпляру объекта Sale, когда экземпляр объекта ProductDescription передает¬
ся в качестве параметра. В контексте метода makeLineltem между объектами Sale и
ProductDescription существует видимость, обеспечиваемая с помощью параметров
(рис. 19.3).Рис. 19.3. Видимость, обеспечиваемая с помощью параметров
Глава 19. Области видимости 391Зачастую видимость, обеспечиваемую посредством параметров, преобразуют в
видимость, обеспечиваемую посредством атрибутов. Например, при создании ново¬
го экземпляра SalesLineltem объектом Sale методу инициализации (в языках C++
и Java это конструктор (constructor)) в качестве параметра передается экземпляр
ProductSpecification. В методе инициализации значение этого параметра присва¬
ивается атрибуту и видимость устанавливается посредством атрибутов (рис. 19.4).// метод инициализации' (например, конструктор Java)
SalesLineltem(ProductDescription desc, int qty){description=desc; // переход к видимости посредством атрибутов
}Рис. 19.4. Преобразование видимости посредством параметров в видимость посред¬
ством атрибутовЛокальная видимостьЛокальная видимость (local visibility) между объектами А и В существует в том слу¬
чае, если объект В объявлен в качестве локальной переменной в методе объекта А.
Это относительно “вршенная” видимость, поскольку она существует только в контек¬
сте одного метода. Это третий по распространенности способ обеспечения видимо¬
сти между объектами в объектно-ориентированных системах.Такая форма видимости между объектами достигается двумя следующими спосо¬
бами.■ Создается новый локальный экземпляр и присваивается в качестве значения
локальной переменной.■ Локальной переменной присваивается объект, возвращаемый другим методом.Как и в случае с обеспечением видимости посредством параметров, зачастую ло¬
кальная видимость преобразуется в видимость посредством атрибутов.В качестве примера второго варианта можно рассматривать метод enterltem
класса Register (рис. 19.5).Существует вариант второго способа, когда переменная явно не объявляется в ме¬
тоде, но неявно существует как возвращаемое значение метода. Например:
392 Часть III. Первая итерация фазы развития — основы//неявная локальная видимость объекта,
//возвращаемого при вызове метода getFooO
anObject.getFoo().doBar();enteritem(id,qty) в{// локальная видимость обеспечивается путем
// присваивания возвращаемого объекта
ProductDescription desc = catalog.getProductDesc(id);
}O' : Registerenteritem:ProductCatalog(itemID,quantity) |desc = getProductDesc(itemID)Puc. 19,5. Локальная видимостьГлобальная видимостьГлобальная видимость (global visibility) между объектами А и В существует в том слу¬
чае, когда объект В является глобальным по отношению к А. Это относительно по¬
стоянная видимость, поскольку она поддерживается до тех пор, пока существуют объ¬
екты А и В. Это наиболее редкий способ обеспечения видимости между объектами в
объектно-ориентированном программировании.Один из способов достижения глобальной видимости состоит в присваивании эк¬
земпляра объекта глобальной переменной. Однако такой подход возможен не во всех
языках (например, возможен в C++, но не в Java).Более предпочтительный способ состоит в использовании шаблона Singleton [58],
описанного в последующих главах.
Преобразование проектного
решения в программный кодСледите за ошибками в приведенном коде: я лишь доказал его корректность,но не протестировал.Дональд Кнут (Donald Knuth)Основная задача■ Преобразовать артефакты проектирования в код на объектно-ориен-
тированном языке программирования.ВведениеПосле завершения проектирования диаграмм классов и взаимодействия на теку¬
щей итерации разработки рассматриваемых примеров остался еще один существен¬
ный момент — генерация кода для объектов уровня предметной области.При этом в процессе генерации кода в качестве входной информации будут ис¬
пользоваться созданные на стадии проектирования артефакты языка UML — диаграм¬
мы взаимодействия и диаграммы классов.В контексте UP существует понятие “модель реализации” (implementation model).
К этой модели относятся такие артефакты реализации, как исходный код, структура
баз данных, страницы JSP/XML/HTML и т.п. Код, который будет рассмотрен в этой
главе, тоже составляет часть модели реализации.
394 Часть III. Первая итерация фазы развития — основыЧто дальше?После завершения проектирования видимости между объектами в данной главе
рассматриваются вопросы преобразования проектного решения в программный
код на объектно-ориентированном языке. В следующей главе вы познакомитесь
с важными приемами объектно-ориентированного программирования: разработкой
на основе тестирования и рефакторингом/Примеры Проектированиепроектирования областей
объектов видимостиПреобразование
проектного
решения
в программный
код\Разработка
на основе
тестирования
и рефакторингСредствапостроениядиаграммUMLВыбор языка программированияРассматриваемые примеры написаны на языке Java. Такой выбор объясняется по¬
пулярностью и широким распространением этого языка. Однако автор не выделяет
язык Java среди других языков. Языки С#, Visual Basic, C++, Smalltalk, Python и многие
другие тоже удовлетворяют принципам объектного проектирования и могут исполь¬
зоваться для преобразования разработанной модели в исходный код.20.1. Программирование и итеративный,
эволюционный процесс разработкиВыполнение предварительного проектирования совсем не означает, что в про¬
цессе программирования нельзя выполнять макетирование и проектирование.
Современные средства разработки предоставляют прекрасную среду для быстрого из¬
учения альтернативных подходов, а некоторые из них (или даже многие) позволяют
сочетать процессы проектирования и программирования.Написание кода на объектно-ориентированном языке программирования, наподо¬
бие Java или С#, не относится к процессу анализа или проектирования системы — это
конечная цель проектирования. Артефакты, создаваемые в контексте UP в рамках
модели проектирования, предоставляют часть информации, необходимой для гене¬
рирования кода.Преимущество объектно-ориентированного подхода к анализу, проектированию и
программированию в рамках UP состоит в том, что он обеспечивает полный цикл
разработки системы — от формулировки требований до программной реализации.
Артефакты последовательно трансформируются в артефакты следующей стадии раз¬
работки, постепенно обеспечивая превращение системы в работающее приложение.
Не стоит ожидать, что этот процесс окажется гладким или механическим — он доста¬
точно творческий и неоднозначный. Однако предлагаемый подход обеспечивает от¬
правную точку для экспериментирования и обсуждения.Внесение изменений на стадии реализацииЗначительная часть усилий и творческого потенциала была задействована на ста¬
дии проектирования. Как станет видно из последующего обсуждения, генерация про¬
граммного кода является относительно механическим процессом преобразования.
Глава 20. Преобразование проектного решения в программный код 395Тем не менее, процесс программирования не сводится к примитивной генерации
кода. Совсем наоборот: результаты, полученные на стадии проектирования, оказыва¬
ются далеко не совершенными. В процессе программирования и тестирования навер¬
няка потребуется внести многочисленные изменения, а также выявить и разрешить
возникшие проблемы.Идеи и уровень понимания (а не диаграммы или документы) будут составлять
эластичное ядро, которое можно масштабировать, сохраняя при этом изящность и
устойчивость, а также обеспечивая решение новых возникающих в процессе про¬
граммирования проблем. Поэтому на стадии построения и тестирования будьте гото¬
вы к изменению проектных решений.20.2. Преобразование результатов
проектирования в программный кодРеализация на объектно-ориентированном языке программирования требует на¬
писания исходного кода для:■ определений классов и интерфейсов;■ методов.В последующих разделах обсуждается генерация таких определений на языке Java
(как типичный случай). Изложенный материал не зависит от выбора автоматизиро¬
ванного средства проектирования с использованием UML.20.3. Создание определений классов
на основе диаграмм классовКоротко можно сказать, что на диаграммах классов отображаются имена классов
и интерфейсов, суперклассов, сигнатуры методов и простые атрибуты классов. Этого
вполне достаточно для создания базового определения класса на объектно-ориенти¬
рованном языке программирования. Если диаграмма классов строится с использова¬
нием специализированных средств, то базовые определения классов могут быть по¬
лучены из соответствующих диаграмм.Определение класса с сигнатурами методов и атрибутамиКак видно из рис. 20.1, преобразование диаграммы классов в базовые определения
атрибутов (поля в Java) и сигнатуры методов для определения класса SalesLineltem
на языке Java выполняется очень просто.Обратите внимание на добавление конструктора SalesLineltem (...). Это сде¬
лано на основании того, что в диаграмме взаимодействия для системной операции
enterltem объекту SalesLineltem передается сообщение create (spec, qty). При
переходе к языку Java это означает необходимость использования конструктора с
двумя указанными параметрами. Метод create зачастую исключается из диаграммы
классов, поскольку он является стандартным и имеет несколько интерпретаций, за¬
висящих от используемого языка программирования.
396 Часть III. Первая итерация фазы развития — основыРис. 20.1. Класс SalesLineltem на языке Java20.4. Создание методов на основе
диаграмм взаимодействияПоследовательность сообщений на диаграммах взаимодействия преобразуется
в серию операторов в определении метода. Для иллюстрации определения метода
enterltem на языке Java можно использовать диаграмму взаимодействия системной
операции enterltem (рис. 20.2). В приведенном примере будет использован класс
Register. Его определение на языке Java представлено на рис. 20.3.Рис. 20.2. Диаграмма взаимодействия для системной операции enterltem
Глава 20. Преобразование проектного решения в программный код 397Рис. 20.3. Класс RegisterМетод Register.enterltemСообщение enterltem передается экземпляру объекта Register. Следовательно,
метод enterltem определяется в этом классе.public void enterltem(ItemID itemID, int qty)Сообщение 1. Для получения объекта ProductDescription объекту
ProductCatalog передается сообщение getProductDescription.ProductDescription spec =catalog.getProductDescription (itemID);Сообщение 2. Объекту Sale передается сообщение makeLineltem.sale.makeLineltem(spec, qty);Подводя итоги, можно еще раз повторить, что каждое сообщение из последова¬
тельности внутри метода, как показано на диаграмме взаимодействия, преобразуется
в оператор метода на языке Java.Полученный метод enterltem и его связь с диаграммой взаимодействия представ¬
лены на рис. 20.4.
398 Часть III. Первая итерация фазы развития — основыРис. 20.4. Метод enteritem20.5. Классы коллекций в программном кодеЗачастую для объекта необходимо обеспечить видимость группы других объектов.
Например, для объекта Sale необходимо обеспечить видимость группы экземпляров
класса SalesLineltem (рис. 20.5). В объектно-ориентированных языках программи¬
рования такие взаимосвязи в основном реализуются с помощью объекта-коллекции,
например, List либо Мар, либо простого массива.Например, в библиотеках Java имеются такие классы коллекций, как ArrayList и
HashMap, реализующие интерфейсы List и Мар, соответственно. При использовании
класса ArrayList в классе Sale можно определить атрибут, указывающий на упоря¬
доченный список экземпляров SalesLineltem.public class Sale
{private List lineltems=
new ArrayList();} QSaleisComplete: Boolean
time: DateTimelineltems >1..*0SalesLineltembecomeComplete()
makeLineItem()
makePayment()
getTotal()quantity:IntegergetSubtotal()Класс-коллекция требуется для I
обеспечения видимости всех
объектов SalesLineltem
посредством атрибутовРис. 20.5. Добавление контейнера
Глава 20. Преобразование проектного решения в программный код 399Выбор подходящего класса коллекции определяется реальными требованиями.
Если планируется применять поиск по ключу, то лучше воспользоваться классом Мар;
при организации расширяемого упорядоченного списка потребуется класс List и т.д.
Заметим, что атрибут lineltems определен в терминах реализации интерфейса.
Рекомендация. Если объект реализует интерфейс, переменную следует объявлять в
терминах интерфейса, а не конкретного класса.Например, на рис. 20.5 этой рекомендации соответствует определение атрибута
lineltems.Private List lineltems = new ArrayList ();20.6. Исключения и обработка ошибокДо сих пор обработка ошибок в процессе разработки игнорировалась, поскольку
мы рассматривали основные вопросы распределения обязанностей и объектно-ори¬
ентированного проектирования. Однако при разработке реального приложения на
стадии проектирования, а особенно реализации, не лишним будет рассмотреть также
вопросы обработки ошибок. В языке UML для обозначения исключений используют¬
ся строки свойств сообщений и объявления операций. Эти вопросы более подробно
рассматриваются в главе 16.20.7. Определение метода Sale.makeLineltemВ качестве заключительного примера рассмотрим метод makeLineltem класса
Sale, который может быть описан на основе анализа диаграммы взаимодействия си¬
стемной операции enterltem. Фрагмент диаграммы взаимодействия и соответствую¬
щий метод на языке Java представлены на рис. 20.6.Рис. 20.6. Метод Sale.makeLineltem
400 Часть III. Первая итерация фазы развития — основы20.8. Порядок реализацииКлассы нужно реализовывать (и, в идеале, полностью тестировать в рамках мо¬
дулей) начиная от минимально связанных с другими классами до максимально свя¬
занных (рис. 20.7). Например, первым можно реализовать класс Payment либо
ProductDescription. Следующими должны реализовываться те классы, которые за¬
висят от уже реализованных классов: класс ProductCatalog либо SaleLineltem.StoreaddSale(...)1Registeraddress:Address
name:Text1ProductCataloggetProductDesc(...)ОбрабатываетendSale()
enterltem(...)
makeNewSale()
makePayment(...)11SaleisComplete:Boolean
time:DateTimebecomeComplete()
makeLineItem(...)
makePayment(...)
getTotal()11..*ProductDescriptiondescription:Text
price:Money
itemID:ItemIDSalesLineltemquantity:IntegergetSubtotal()Paymentamount:MoneyPuc. 20.7. Возможный порядок реализации и тестирования классов20.9. Программирование на основе тестированияВ рамках метода ХР (Extreme Programming) [12] предложен применимый к уни¬
фицированному процессу разработки подход к программированию на основе тестирова¬
ния (test-first programming). В рамках этого подхода код тестов для каждого модуля
пишется раньше, чем сам тестируемый код. При этом разработчик разрабатывает
код тестов для всех модулей приложения. При этом процесс реализации происходит
следующим образом. Разработчик пишет код для небольшого теста, затем реализу¬
ет часть приложения, тестирует его с помощью созданного теста, пишет код для
следующего теста и т.д. Этот подход будет более подробно рассмотрен в следующей
главе.
Глава 20. Преобразование проектного решения в программный код 40120.10. Еще несколько слов о преобразовании
проектного решения в кодПроцесс преобразования объектно-ориентированных диаграмм классов в их опре¬
деления и диаграмм взаимодействия в методы является относительно простым. При
этом на стадии программирования разработчик по-прежнему имеет достаточную сво¬
боду действий, чтобы принимать дополнительные решения и изменять уже принятые.20.11. Основное программное решение
для POS-системы NextGenВ этом разделе приводится пример программного описания объектов уровня
предметной области на языке Java для данной итерации. Генерация кода во многом
определяется диаграммами классов и диаграммами взаимодействия, разработанными
ранее на стадии проектирования, и основывается на принципах их отображения в
исходный код.Основной смысл приведенного примера заключается в том, что существует отно¬
сительно простой способ преобразования артефактов проектирования в “скелет”
программного кода. Этот код определяет контрольный пример, который не мо¬
жет претендовать на устойчивую, полноценную программу на Java с синхрониза¬
цией, обработкой исключений и т.д.Если код является достаточно простым, комментарии можно исключить.Класс Payment// Полные имена классов включают и имя пакета
package com.foo.nextgen.domain;public class Payment
{private Money amount;public Payment( Money cashTendered ) { amount = cashTendered; }
public Money getAmount() { return amount; }}Класс ProductCatalogpublic class ProductCatalog
{private Map<ItemID, ProductDescription>descriptions = new HashMap()<ItemID, ProductDescription>;
public ProductCatalog(){// тестовые данныеItemID idl = new ItemID ( 100 );ItemID id2 = new ItemID ( 200 );Money price = new Money ( 3 ) ;
402 Часть III. Первая итерация фазы развития — основыProductDescription desc;desc = new ProductDescription ( idl, price, "товар 1" );
descriptions.put ( idl, desc );desc = new ProductDescription ( id2, price, "товар 2" );
descriptions.put ( id2, desc );}public ProductDescription getProductDescription ( ItemID id )
{return descriptions.get ( id );}Класс Registerpublic class Register
{private ProductCatalog catalog;
private Sale currentSale;public Register ( ProductCatalog catalog )
{this.catalog = catalog;public void endSale (){currentSale.becomeComplete();public void enterltem( ItemID id, int quantity )
{ProductDescription desc =catalog.getProductDescription ( id;) ;
currentSale.makeLineltem( desc, quantity );public void makeNewSale (){currentSale = new Sale();public void makePayment( Money cashTendered )
{currentSale.makePayment ( cashTendered );Класс ProductDescriptionpublic class ProductDescription
{private ItemID id;
private Money price;
Глава 20. Преобразование проектного решения в программный код 403private String description;public ProductDescription( ItemID id, Money price, String description ){this . id = id;this.price = price;this.description = description;}public ItemID getltemlDO { return id; }public Money getPrice() { return price; }public String getDescription() { return description; }}Класс Salepublic class Sale
{private List<SalesLineItem> lineltems = new ArrayList()<SalesLineItem>;
private Date date = new Date() ;
private boolean isComplete = false;
private Payment payment;public Money getBalance(){return payment.getAmount().minus ( getTotal() );}public void becomeComplete () { isComplete = true; }public boolean isComplete () { return isComplete; }public void makeLineltem( ProductDescription desc, int quantity ){lineltems.add( new SalesLineltem(desc, quantity) );}public Money getTotal(){Money total = new Money();Money subtotal = null;for ( SalesLineltem lineltem : lineltems){subtotal = lineltem.getSubtotal();
total.add( subtotal );}return total;}
404 Часть III. Первая итерация фазы развития — основыpublic void makePayment(Money cashTendered)
{payment = new Payment(cashTendered);}Класс SalesLineltempublic class SalesLineltem
{private int quantity;private ProductDescription description;
public SalesLineltem( ProductDescription desc, int quantity ){this.description = desc;
this.quantity = quantity;}public Money getSubtotal(){return description.getPrice().times( quantity );}}Класс Storepublic class Store
{private ProductCatalog catalog =
new ProductCatalog();
private Register register = new Register( catalog );public Register getRegister () { return register; }}20.12. Основные программные решения
для игры “Монополия”В этом разделе представлены примеры классов предметной области для данной
итерации, реализованные на языке Java. На второй итерации разработки и код, и
проектные решения будут улучшены и модифицированы. Поскольку код является до¬
статочно простым, в нем содержится очень мало комментариев.Класс Square// Полные имена классов включают имя пакета
package com.foo.monopoly.domain;public class Square
{
Глава 20. Преобразование проектного решения в программный кодprivate String name;
private Square nextSquare;
private int index;public Square ( String name, int index ){this.name = name;
this.index = index;}public void setNextSquare( Square s ){nextSquare = s;}public Square getNextSquare( ){return nextSquare;}public String getName ( ){return name;}public int getlndex( ){return index;}}Класс Piecepublic class Piece
{private Square location;
public Piece(Square location){this.location = location;}public Square getLocation (){return location;}public void setLocation(Square location)
{this.location = location;
406 Часть III. Первая итерация фазы развития — основыКласс Diepublic class Die
{public static final int MAX = 6;
private int faceValue;public Die( ){roll( ) ;public void roll ( ){faceValue = (int) ( ( Math.random( ) * MAX ) + 1 );public int getFaceValue ( )
{return faceValue;Класс Boardpublic class Board
{private static final int SIZE = 40;
private List squares = new ArrayList(SIZE) ;public Board(){buildSquares();
linkSquares();}public Square getSquare(Square start, int distance){int endlndex = (start.getlndex() + distance) % SIZE
return (Square) squares.get(endlndex);}public Square getStartSquare (){return (Square) squares.get (0);}private void buildSquares (){for (int i = 1; i <= SIZE; i++){build(i);}}
Глава 20. Преобразование проектного решения в программный кодprivate void build(int i){Square s = new Square ("Square " + i, i - 1) ;
squares.add(s);}private void linkSquares(){for (int i = 0; i < (SIZE-1); i++){link(i);}Square first = (Square) squares.get (0);
Square last = (Square) squares.get(SIZE-1);
last.setNextSquare(first);}private void link(int i){Square current = (Square) squares.get (i);
Square next = (Square) squares.get(i+1);
current.setNextSquare(next);}Класс Playerpublic class Player
{private String name;
private Piece piece;
private Board board;
private Die[] dice;public Player(String name, Die[] dice, Board board){this, name = name;
this.dice = dice;
this.board = board;piece = new Piece(board.getStartSquare());}public void takeTurn(){/ / бросание кубиков
int rollTotal = 0;for (int i = 0; i < dice.length; i++){dice[i].roll ();rollTotal += dice[i].getFaceValue ();}Square newLoc = board.getSquare(piece.getLocation (), rollTotal)
piece.setLocation(newLoc);}
408 Часть III. Первая итерация фазы развития — основыpublic Square getLocation (){return piece.getLocation ();}public String getName(){return name;}}Класс MonopolyGamepublic class MonopolyGame
{private static final int ROUNDS_TOTAL =20;
private static final int PLAYERS_TOTAL = 2;
private List players = new ArrayList(PLAYERS_TOTAL);
private Board board = new Board();
private Die[] dice = { new Die(); new Die() };public MonopolyGame(){Player p;p = new Player("Лошадь", dice, board);
players.add(p);p = new Player("Автмобиль", dice, board);
players.add(p);}public void playGame(){for (int i = 0; i < ROUNDS_TOTAL; i++){playRound() ;}public List getPlayers(){return players;}private void playRound(){for(Iterator iter = players.iterator (); iter.hasNext (){Player player = (Player) iter.next();
player.takeTurn ();}}}
Разработка на основе
тестирования и рефакторингЛогика — это искусство обоснования неправильных действий.Джозеф Вуд Кратч (Joseph Wood Krutch)Основная задача■ Ознакомиться с двумя важнейшими аспектами разработки в контек¬
сте рассматриваемых примеров.ВведениеЭкстремальное программирование предполагает написание тестов до создания
основного кода приложения, а также непрерывный рефакторинг кода для улучшения
его качества — уменьшения дублирования кода, улучшение ясности и т.д. Эти процес¬
сы поддерживают многие современные средства объектно-ориентированной разра¬
ботки.Что дальше?Проекти¬рованиеобластейвидимостиПосле преобразования проектных решений в программный код в данной главе
рассматриваются два важных подхода к объектно-ориентированному
программированию. В следующей главе рассматриваются CASE-средства
построения диаграмм UML/Преобразование
проектного
решения
в программный
код о Разработка
на основе
тестирования
и рефакторинг
—•—\СредствапостроениядиаграммUMLУточнениеартефактованализа
410 Часть III. Первая итерация фазы развития — основы21.1. Разработка на основе тестированияВ рамках итеративного и гибкого метода ХР (Extreme Programming) предложен
применимый к унифицированному процессу подход к разработке на основе тестирова¬
ния (test-first development, test-driven development) [12]. Этот подход предполагает не
только модульное тестирование (unit testing), или тестирование отдельных компонен¬
тов. В данной главе мы сосредоточимся на вопросах модульного тестирования от¬
дельных классов.В рамках этого подхода код тестов для каждого модуля пишется раньше, чем сам
тестируемый код. При этом разработчик разрабатывает код тестов для всех модулей
приложения.При этом процесс реализации происходит следующим образом. Разработчик пи¬
шет код для небольшого теста, затем реализует часть приложения, тестирует его с
помощью созданного теста, пишет код для следующего теста и т.д.Важный момент: сначала разрабатывается тест в предположении, что тестируе¬
мый код уже написан.Такой подход имеет следующие преимущества.■ Тесты для модулей действительно разрабатываются. Разработчики (особен¬
но программисты) стремятся избежать необходимости программирования те¬
стов или оставить эту работу на более поздний срок.Ш Разработчик получает большее удовлетворение. Это гораздо важнее, чем мо¬
жет показаться на первый взгляд. Если разработчик, как обычно, реализует код
приложения, неформально его тестирует, а после этого вынужден разрабаты¬
вать формальные тесты — он не получает удовлетворения от своей деятельно¬
сти. Если же сначала создаются тесты, затем реализуется код приложения, ко¬
торый должен удовлетворить написанным ранее тестам, то разработчик после
прохождения теста получает “некоторое удовлетворение”. Такова человеческая
психология Этот философский аспект не стоит сбрасывать со счетов, посколь¬
ку программа — это результат человеческих усилий.■ Определение деталей интерфейса и поведения. Этот момент может показать¬
ся незначительным, но на самом деле он играет важную роль. В процессе соз¬
дания теста предполагается, что объект уже существует. Например, при созда¬
нии теста для метода makeLineltem необходимо продумать детали открытого
интерфейса этого метода — его имя, тип возвращаемого значения, параметры
и поведение. Если сначала разрабатывать код для тестов, то в процессе его соз¬
дания прояснится проектное решение класса.■ Обоснованная и автоматизированная верификация. Очевидно, наличие
сотен и тысяч модульных тестов обеспечивает некоторую гарантию коррект¬
ности кода. Еще лучше, если тесты можно будет запускать автоматически.
Преимущество раннего написания тестов проявляется при увеличении объема
приложения, поскольку довольно сложно разработать сразу 500 тестов для всех
созданных классов.■ Верификация кода при возможных изменениях. Если сначала разрабатыва¬
ются сотни или тысячи модульных тестов, то в итоге для каждого класса при¬
ложения существует свой отдельный тест. Если разработчик пожелает внести
изменения в существующий код, то модифицированный код он сможет прове¬
Глава 21. Разработка на основе тестирования и рефакторинг 411рить с помощью готового теста.1 При этом сразу же будут выявлены все несоот¬
ветствия и привнесенные ошибки.В качестве примера можно привести популярный и простой каркас из семейства
xUnit (www.junit.org) для модульного тестирования кода на многих языках.2 Для
Java используется популярная версия этого каркаса JUnit. Существует также система
NUnit для платформы .NET. Средство тестирования JUnit интегрировано в наиболее
популярные среды разработки на Java, в том числе Eclipse (www.eclipse.org).ПримерВоспользуемся средством JUnit для программирования класса Sale на основе те¬
стирования. Тогда до начала программной реализации класса Sale нужно разрабо¬
тать модульный тест, а именно написать соответствующий метод класса SaleTest,
выполняющий следующие действия.1. Создание нового экземпляра продажи Sale.2. Добавление к нему некоторого выбранного товара с помощью метода make-
Lineltem (открытого метода, подлежащего тестированию).3. Запрос на вычисление общей стоимости покупки и проверку корректности ее
вычисления с помощью метода assertTrue. Если этот метод не возвращает
значение true, система JUnit выдаст сообщение об ошибке.Каждый тестовый метод соответствует следующему шаблону.1. Создается тестируемый экземпляр.2. Над ним выполняются некоторые действия (тестируемые операции).3. Выполняется оценка результатов.Не следует писать сразу все модульные тесты для класса Sale. Пишется один те¬
стовый метод, с его помощью выполняется проверка класса Sale и т.д.Для использования JUnit необходимо создать тестовый класс, расширяющий класс
JUnit TestCase. Это тестовый класс наследует поведение класса модульного теста.В JUnit для каждого метода тестируемого класса Sale создается отдельный тесто¬
вый метод. Таким образом, методы модульных тестов пишутся для каждого открыто¬
го метода класса Sale. Исключение могут составить только тривиальные методы get
и set (обычно генерируемые автоматически).Чтобы протестировать метод doFoo, необходимо создать тестовый метод testDoFoo.Модульный тест может выглядеть следующим образом.public class SaleTest extends TestCase{// ...// тестирование метода Sale.makeLineltem
public void testMakeLineltem ()1 Популярным бесплатным средством с открытым кодом для автоматического запуска мо¬
дульных тестов является CruiseControl.2 Семейство xUnit было разработано создателем метода ХР Кентом Беком (Kent Beck) и
Эриком Гамма (Eric Gamma), одним из авторов шаблонов GoF и главным архитектором попу¬
лярного средства разработки Eclipse.
412 Часть III. Первая итерация фазы развития — основы{// ШАГ 1: создание экземпляра новой продажи
// это тестируемый объект// зачастую он определяется как поле экземпляра,// а не локальная переменная
Sale fixture = new Sale();/ / создание дополнительных объектов для тестирования
Money total = new Money ( 7.5 ) ;Money price = new Money ( 2.5 ) ;ItemID id = new ItemlD(l);ProductDescription desc =new ProductDescription (id, price, "товар 1");/ / ШАГ 2: выполнение тестируемого метода// Этот код создается в предположении, что метод
// makeLineltem уже существует. Это улучшает
/ / понимание интерфейса объекта.// тестирование метода makeLineltem
sale.makeLineltem( desc, 1);
sale.makeLineltem( desc, 2);// ШАГ 3: проверка правильности результатов// для сложной оценки можно использовать
// несколько экземпляров assertTrue// верификация общей стоимости покупки
assertTrue(sale.getTotal().equals ( total ));}}Только после разработки тестового метода testMakeLineltem можно приступать
к реализации метода Sale.makeLineltem, который должен удовлетворять созданно¬
му тесту. В этом состоит смысл разработки на основе тестирования.Интегрированные среды для разработки
на основе тестирования и xUnitБольшинство интегрированных сред разработки обеспечивает встроенную под¬
держку некоторого средства из семейства xUnit. Например, Eclipse поддерживает
JUnit, которое в свою очередь использует цветовую индикацию. Если все тесты вы¬
полнены успешно, отображается зеленая панель. Таким образом, наличие зеленой па¬
нели свидетельствует о корректности программного кода (рис. 21.1).
Глава 21. Разработка на основе тестирования и рефакторинг 413Java - DieTest.java - Eclipse PlatformPfe ЕЛ Source fcefecfcor ЬШ&к& Search Project Run Window HelplQ-иа j 5 j ^ - o - % - j ш « © ч * * j j m J й ъ фP^rn'^^PKfayEx..,=ir*hed»ft*r 0.2514 ^ m | % aH0F^ures [ y&iKcrardiy |‘BHons J/t Q&roiK 0 BMvcs 0£1 Falure Trace[>*r2] DfeTestjavapackage tcst.comxroiglarmanrnonopoty.domoin;► import com.craiglaiTnan.monopoiy.doma»n.*;[]^public class DieTest extends TestCase
{private Die fixture = new Die! );
private static final int ROLLS_MAX = 100;// every roll should produce a face Value between 1 and 6.
r public void testRoU( ){for (int i — 0“ I < ROLLS_MAX; И-+ ){fixhire.roi( );int faceValue = fixture_ getFaceValue( );
assertTrue( (faceVaioe > 0) && (faceVatue < 7));}>Puc. 21.1. Поддержка разработки на основе тестирования и средства JUnit в популярнойинтегрированной среде Eclipse21.2. РефакторингРефакторинг (refactoring) [51] — это структурированный метод для модификации и
реорганизации существующего кода без изменения внешнего поведения. Он состоит
в поэтапном преобразовании кода с повторным тестированием на каждом шаге пре¬
образования. Рефакторинг — это еще одно свойство ХР, применимое к любым итера¬
тивным методам разработки (включая UP).3Смысл рефакторинга состоит в последовательном применении небольших преоб¬
разований, после каждого из которых выполняются модульные тесты. Следовательно,
рефакторинг неразрывно связан с разработкой на основе тестирования.Каждая операция рефакторинга является незначительным преобразованием кода.
Однако в результате последовательности таких преобразований, сопровождаемых
модульными тестами, можно получить существенно реструктурированный код и об¬
новленное проектное решение. При этом поведение объектов остается прежним.3 Термин “рефакторинг” в 1990 году ввели Ральф Джонсон (Ralph Johnson), один из авторов
шаблонов GoF, и Билл Обдик (Bill Obdyke). Кроме того, пионерами рефакторинга являются
Кент Бек (создатель ХР) и Мартин Фаулер (Martin Fowler).
414 Часть III. Первая итерация фазы развития — основыВ процессе рефакторинга выполняются следующие действия.■ Удаление повторяющихся фрагментов кода.■ Повышение ясности кода.■ Сокращение слишком длинных методов.■ Устранение жестко заданных литеральных констант и т.д.В результате рефакторинга код становится короче и прозрачнее. Он не содержит
некорректностей и выглядит профессионально. Он больше не требует улучшений.
К некорректностям кода относят следующее.■ Повторяющиеся фрагменты.■ Длинные методы.■ Классы, атрибутами которых является множество экземпляров других классов.■ Длинные описания классов.■ Очень схожие подклассы.■ Отсутствие интерфейсов.■ Высокая степень связывания между многими объектами и т.д.4Подобно шаблонам приемы рефакторинга имеют свои названия, например вы¬
деление методов (extract method). Всего существует около 100 именованных приемов
рефакторинга, в том числе следующие.Прием рефакторингаОписаниеВыделение методаВыделение константы
Введение поясняющей переменнойЗамещение вызова конструктора
методом фабрикиПреобразование длинного метода в более короткий путем выде¬
ления его части в отдельный закрытый вспомогательный методЗамещение литеральной константы константной переменнойРезультат выражения или его части помещается во временную
переменную с осмысленным именемВ Java вызов оператора new или конструктора заменяется вспо¬
могательным методом создания объекта (скрывающим детали
реализации)ПримерВ данном примере демонстрируется типичный прием рефакторинга, состоящий
в выделении метода. В следующем фрагменте кода в начале метода takeTurn класса
Player содержится фрагмент, моделирующий бросание кубиков и вычисление сум¬
марного значения. Данный фрагмент кода является независимым элементом пове¬
дения. Поэтому его можно выделить в отдельный закрытый вспомогательный метод
roll Dice, сократив тем самым метод takeTurn и обеспечив поддержку принципа
High Cohesion. Заметим, что в методе takeTurn требуется значение rollTotal, по¬
этому его должен возвращать вновь созданный вспомогательный метод.54 Изъяны кода и приемы рефакторинга описаны на страницах Wiki по адресу c2.com/cgi/
wiki.5 Такое решение нарушает принцип разделения команд и запросов, но это допустимо для
закрытых методов. Этот принцип является рекомендацией, а не правилом.
Глава 21. Разработка на основе тестирования и рефакторинг 415public class Player
{private Piece piece;
private Board board;
private Die[] dice;// ...public void takeTurn(){// бросание кубиков
int rollTotal = 0;for(int i = 0; i < dice.length; i++){dice[i].roll();rollTotal += dice[i].getFaceValue();}Square newLoc = board.getSquare(piece.getLocation(), rollTotal);
piece.setLocation(newLoc);}} 11 конец описания классаТеперь приведем код, полученный в результате приема рефакторинга, состоящего
в выделении метода.public class Player
{private Piece piece;
private Board board;
private Die[] dice;// ...public void takeTurn(){// результат рефакторинга
int rollTotal = rollDice();Square newLoc = board.getSquare(piece.getLocation(), rollTotal);
piece.setLocation(newLoc);}private int rollDiceO
{int rollTotal = 0;for(int i = 0; i < dice.length; i++){dice[i].roll ();rollTotal += dice[i].getFaceValue();}return rollTotal;}} // конец описания класса
416 Часть III. Первая итерация фазы развития — основыПри рассмотрении второй итерации разработки данной системы станет ясно, что
подобное решение не является идеальным. Шаблон Pure Fabrication предполагает
альтернативное решение, вполне соответствующее принципу разделения команд и
запросов. Однако в данном случае просто иллюстрируется прием рефакторинга.Приведем еще один короткий пример применения простого приема рефакторин¬
га, состоящего в выделении поясняющей переменной. Это существенно упрощается
код, снижая необходимость в комментариях. Рассмотрим следующий фрагмент.// метод с хорошим именем, но непонятной логикой
boolean isLeapYear( int year ){return ( ( ( year % 400 ) == 0 ) | |( ( ( year % 4 ) == 0 ) && ( ( year % 100 ) != 0 ) ) ) ;}В результате введения поясняющей переменной получим следующий код.// так гораздо лучше
boolean isLeapYear ( int year ){boolean isFourthYear = ( ( year % 4 ) == 0 ) ;boolean isHundrethYear = ( ( year % 100 ) == 0 ) ;boolean is4HundrethYear = ( ( year % 400 ) == 0 ) ;return (is4HundrethYear ||(isFourthYear && ! isHundrethYear ) ) ;}Поддержка рефакторинга в интегрированных средахБольшинство интегрированных сред разработки включает автоматическую под¬
держку рефакторинга. На рис. 21.2 и 21.3 показан пример применения приема вы¬
деления метода в среде Eclipse. Метод rollDice и его вызов в методе takeTurn гене¬
рируются автоматически. Обратите внимание, что средство рефакторинга является
настолько интеллектуальным, что формирует возвращаемое значение rollTotal.
Замечательно!21.3. Дополнительные ресурсыВопросам разработки на основе тестирования посвящены следующие Web-pecypcbi.■ www.junit.org■ www.testdriven.comПодробную информацию о рефакторинге можно узнать по следующим адресам.■ www.refactoring.com■ c2.com/cgi/wiki?WhatIsRefactoring
Классической книгой по рефакторингу является [51].
Глава 21. Разработка на основе тестирования и рефакторинг 417Square rewLoc = board getSquare(piece getLocation(), rollTotal);
piece. setLocation(newLoc);}public Piayer(String name, DieQ dice, Board board){this narre = пяте
this dice = dice;
this board = board;piece = new Piece(board.getStartSquareQ),}public void takeTum()□Method none: J гоЕнсеAccess modifier: Г pubic С protected С default (• private
Г Add thrown runtime exceptions to method signature
Г~ Generate Javadoc commentГ Replace duplicate code fragmentsMethod signature preview:
private int roHDir.ftQPreview > j | OK j Cancel |Puc. 21.2. До рефакторинга^ public void takeTum(){|nf rollTotal - rolDicei);Square newLoc ~ board.getSquare(piecegetLocation(), rolfTotat);
piece setLocation(newLoc);}^ private int rollDiceQ{// roll dice
int rollTotal = 0;for (int i = 0; i < dice length; И-+){dce[i].rott();rollTotal += dtce[i]_getFaceValue():}return rollTotal;}Puc. 21.3. После рефакторинга4 3ak. 3357
ЧастьIVВторая итерация
фазы развития —
дополнительные шаблоныВ этой части...Глава 22. Средства построения диаграмм UMLГлава 23. Быстрый дополнительный анализГлава 24. Вторая итерация и дополнительные шаблоныГлава 25. Дополнительные шаблоны GRASP для распределения
обязанностейГлава 26. Применение шаблонов проектирования GoF
Средства построения
диаграмм UMLОпыт — это замечательная штука, позволяющая распознать ошибку,когда ты допускаешь ее снова.Ф.П. Джонс (F.P. Jones)Основные задачи■ Определить понятия прямого, обратного и циклического проектиро¬
вания.■ Ознакомиться с советами по выбору средства автоматизированного
построения диаграмм UML.■ Ознакомиться с рекомендациями по объединению диаграмм, постро¬
енных вручную, с диаграммами, созданными с помощью средств авто¬
матизированного проектирования.ВведениеНе имеет смысла детально обсуждать конкретные средства построения диаграмм
UML, поскольку они очень быстро изменяются и информация о них мгновенно уста¬
ревает. Однако в этой главе рассматриваются некоторые стандартные свойства по¬
добных средств и особенности их использования для построения диаграмм UML.
422 Часть IV. Вторая итерация фазы развития — дополнительные шаблоныЧто дальше?Преобразование
проектного
решения
в программный
кодО После краткого знакомства с разработкой на основе тестирования и рефакторингом
в данной главе рассматриваются CASE-средства, поддерживающие UML.В следующей главе определяются новые требования для итерации 2/Разработка
на основе
тестирования
и рефакторинг\СредствапостроениядиаграммUMLУточнениеартефактованализаТребования
на итерации 2Как уже упоминалось, UML можно использовать в трех контекстах.■ Для построения диаграмм вручную.■ Для автоматизированного построения диаграмм с последующей автоматиче¬
ской генерацией кода. Диаграммы можно генерировать на основе исходного
кода для иллюстрации готовых проектных решений. Даже при автоматической
генерации кода многие детали обычно дополняются разработчиками вручную.■ Использование UML как языка программирования. На UML можно создать
полную спецификацию программной системы. На основе этой спецификации
можно сгенерировать выполняемый код (либо интерпретировать ее напрямую
с помощью виртуальной машины). Однако этот код разработчики зачастую мо¬
дифицируют вручную, используя при этом UML как язык программирования.Первый и второй контексты определяют типичные способы использования UML.
Средства автоматического построения диаграмм UML обычно поддерживают второй
подход, а не третий.22.1. Прямое, обратное и циклическое
проектированиеВ среде разработчиков, работающих с СЛЖ-средствами (Computer Aided Software
Engineering), прямым проектированием (forward engineering) называют генерацию кода
на основе диаграмм. Под обратным проектированием (reverse engineering) понимают
генерацию диаграмм на основе кода, а под циклическим проектированием (round-trip
engineering) — синхронизацию диаграмм UML и кода в автоматическом режиме сразу
же после изменения одного из этих артефактов.Разработчики всех UML-средств декларируют поддержку этих возможностей, од¬
нако эти обещания далеко не всегда выполняются. Почему? Дело в том, что многие из
средств работают только со статическими моделями: они позволяют сгенерировать
на основе кода диаграмму классов, но не диаграммы взаимодействия. При прямом
проектировании они генерируют базовые определения классов на основе соответ¬
ствующих диаграмм, но не реализации методов на основе диаграмм взаимодействия.Однако код — это не просто объявления переменных, а реализация динамическо¬
го поведения! Например, если вы пытаетесь разобраться в структуре вызовов суще¬
ствующего приложения, необходимо на основе кода сгенерировать диаграмму после¬
довательности. Это позволит легко понять логику работы системы и разобраться со
взаимодействием объектов.
Глава 22. Средства построения диаграмм UML 42322.2. Важнейшие свойства UML-средствАвтор книги имеет многолетний опыт консультирования больших компаний, ис¬
пользующих автоматизированные средства построения диаграмм UML. Обычно раз¬
работчики таких средств преувеличивают их возможности. На основе своего жизнен¬
ного опыта автор может утверждать, что каждое новое поколение средств разработки
обладает все более широкими возможностями. Наиболее важным свойством с точки
зрения пользователей является возможность обратного проектирования или визуали¬
зации существующего кода. Пользователи рассчитывают, что CASE-средства позволят
строить диаграммы классов, пакетов и взаимодействия, распечатывать их на плот¬
тере или выводить на монитор. Это действительно важнейшие свойства подобных
систем.В будущем, по-видимому, пользователям потребуется интеграция подобных средств
с интегрированными средами разработки, такими как Eclipse и Visual Studio, и реали¬
зация возможностей прямого и циклического проектирования.22.3. Как выбрать систему проектированияОсновываясь на приведенных выше комментариях, сформулируем несколько со¬
ветов по выбору средства автоматизации проектирования. Эти советы базируются на
опыте автора и его клиентов, затративших немалые средства на приобретение си¬
стем автоматизации проектирования.■ В первую очередь постарайтесь найти бесплатное средство проектирования.
Покупайте систему только в том случае, если вам не удалось найти бесплатную
систему с требуемыми возможностями.■ Выбрав систему, испытайте ее на реальном проекте, привлекая к эксперименту
как можно больше участников. Послушайте отзывы и примите решение с уче¬
том реального опыта использования системы, а не просто совета архитектора.■ Выбирайте средство, интегрированное с используемой вами средой разработки.■ Далеко не все CASE-средства обеспечивают возможность обратного проектиро¬
вания диаграмм последовательностей (а не только диаграмм классов). Если вам
не удалось найти бесплатное средство с поддержкой этой функциональности,
используйте его для решения других задач и приобретите минимальное коли¬
чество копий коммерческого продукта, удовлетворяющего вашим повышенным
требованиям.■ Выбирайте средство, поддерживающее вывод диаграмм на плоттер с использо¬
ванием крупных шрифтов и диаграмм, обеспечивающее хорошее масштабиро¬
вание документации.
424 Часть IV. Вторая итерация фазы развития — дополнительные шаблоны22.4. Как обновлять диаграммы на основе кода,
если они изначально были построены вручнуюЕсли вы используете UML-средство, интегрированное со средой разработки, то
для синхронизации диаграмм и кода достаточно просто выполнить операцию обрат¬
ного проектирования в среде разработки.Однако если вы работаете в группе и на каждой итерации разработки системы хо¬
тите проводить “день моделирования” с построением диаграмм на доске, то можете
воспользоваться следующим сценарием.1. В начале трехнедельной итерации необходимо выделить один день на построе¬
ние диаграмм UML на доске.2. Затем три недели необходимо посвятить написанию кода и тестированию.3. И наконец, в начале следующей итерации можно провести еще один “день мо¬
делирования”.Как при этом синхронизировать диаграммы и программный код? Дадим одну ре¬
комендацию. Непосредственно перед днем моделирования можно воспользоваться
средством обратного проектирования для построения диаграмм UML на основе суще¬
ствующего кода. Наиболее важные диаграммы можно распечатать на большом листе
бумаги с помощью плоттера. Повесьте их на стену, чтобы в течение дня моделирова¬
ния разработчики могли обращаться к этим диаграммам, дополняя и уточняя их.22.5. Дополнительные ресурсыПрограммные средства развиваются и изменяются очень быстро. Относительно
полный список существующих на сегодняшний день UML-средств можно найти по
адресу www.objectsbydesign.com/tools/umltools _ byCompany.html.
Быстрый дополнительный
анализЛюбое достаточно серьезное упущение неотличимо от свойства.Рич Кулавьек (Rich Kulawiec)Основная задача■ Быстро выделить некоторые изменения артефактов анализа, особен¬
но для модели предметной области игры “Монополия”,ВведениеВ этой главе кратко рассматриваются некоторые изменения требований и резуль¬
таты анализа предметной области. Советы по моделированию касаются в первую
очередь системных диаграмм последовательностей для системы NextGen и модели
предметной области игры “Монополия”.Что дальше?Разработка
на основе
тестирования
и рефакторинго В данной главе рассматриваются некоторые важные изменения в артефактах
анализа. В следующей главе рассматриваются требования для итерации 2./СредствапостроениядиаграммUML\Анализ
на итерации 2Требования
итерации 2Шаблоны GRASP:
дополнительные
объекты
426 Часть IV. Вторая итерация фазы развития — дополнительные шаблоны23.1. POS-система NextGenПрецедентыНикакая модификация описания прецедентов с точки зрения требований для дан¬
ной итерации не выполняется.Однако на этой итерации, помимо проектирования и реализации, проводится
одно- или двухдневный семинар по определению новых требований к системе и раз¬
вернутому описанию новых прецедентов. Описанные ранее прецеденты (например,
Оформление продажи), возможно, тоже будут пересмотрены на основе полученного
на первой итерации опыта разработки и результатов тестирования. Не забывайте о
том, что в итеративных методах ранее программирование и тестирование тесно пе¬
реплетается с анализом требований. На ранних итерациях разработки это позволяет
существенно улучшить обратную связь.Системные диаграммы последовательностейНа этой итерации будет добавлена поддержка внешних систем с различными ин¬
терфейсами, в том числе системы вычисления налоговых платежей. POS-система
Next Gen будет удаленно взаимодействовать с внешними системами. Следовательно,
необходимо обновить диаграммы последовательностей и отразить на них межсистем-
ное взаимодействие с целью прояснения специфики новых системных событий.На рис. 23.1 показана системная диаграмма последовательностей для одного сце¬
нария оплаты по кредитной карточке, в рамках которого происходит взаимодействие
с несколькими внешними системами. И хотя вопросы оплаты по кредитной карточке
не рассматриваются на данной итерации, разработчик (автор книги) построил для
этого сценария диаграмму последовательностей (а может быть, и несколько диа¬
грамм), чтобы лучше понять специфику межсистемного взаимодействия и обеспе¬
чить поддержку внешних систем с разными интерфейсами.Модель предметной областиИмея минимальный опыт моделирования предметной области, разработчик мо¬
жет оценить степень влияния новых требований на модель предметной области с
точки зрения появления новых понятий, ассоциаций и атрибутов. В отличие от пред¬
ыдущей итерации, новые требования не приводят к необходимости рассмотрения
множества новых понятий предметной области. Краткий анализ новых требований
показывает, что в модель предметной области следует добавить лишь несколько по¬
нятий, в том числе PriceRule (правило вычисления стоимости).Поэтому можно не останавливаться на модификации модели предметной области,
а сразу перейти к проектированию, в процессе которого разработчики и введут но¬
вые понятия предметной области.В контексте UP главное определить, добавляет ли артефакт новое качество. Если
создание артефакта сводится к выполнению механической работы, то его лучше про¬
пустить.Такая гибкость имеет обратную сторону. Очень часто разработчикам начинает ка¬
заться, что можно пропустить все предшествующие программированию этапы раз-
Глава 23. Быстрый дополнительный анализ 427работки и сразу же приступить к созданию кода. Это, конечно, можно, поскольку
самым важным этапом является именно программирование, а не создание модели
предметной области. Однако большинство разработчиков могут привести примеры
из своего опыта, когда небольшое исследование проблемы до начала программиро¬
вания значительно упрощало процесс разработки системы и способствовало устране¬
нию множества проблем.Описание системных операцийНа этой итерации новые операции не рассматриваются, поэтому ничего описы¬
вать не нужно. Описание любой системной операции — это лишь возможность ее де¬
тального рассмотрения, более точного, чем при описании прецедентов.Рис. 23.1. Системная диаграмма последовательностей, иллюстрирующая взаимодействиес внешними системами
428 Часть IV. Вторая итерация фазы развития — дополнительные шаблоны23.2. Игра “Монополия”ПрецедентыПоскольку правила игры всем известны, описание прецедентов можно опустить.
Не требуется также построения дополнительных системных диаграмм последователь¬
ностей и описания операций.Понятия Square, GoSquare, IncomeTaxSquare и GoToJailSquare являются раз¬
новидностями клеток игральной доски. Поэтому их можно (и даже нужно) реализо¬
вать в виде иерархии классов (class hierarchy), определяющей отношение “обобщения-
специализации(generalization-specialization). При этом суперкласс (superclass) Square
будет представлять общее понятие клетки, а его подклассы (subclass) — конкретные
виды клеток.В UML отношение “обобщения-специализации” изображается в виде большой
треугольной стрелки, указывающей в направлении от более частных классов к более
общему (рис. 23.2).Обобщение (generalization) — это процесс, связанный с идентификацией общности
между понятиями и определением суперкласса (основного понятия) и связанных с
ним подклассов (специализированных понятий). Обобщение предоставляет метод
систематизированной классификации понятий и их представления в виде иерархии
классов.Вопросы обобщения и специализации более подробно рассмотрены в главе 32.Идентификация супер- и подклассов осуществляется с использованием модели
предметной области, поскольку она позволяет проанализировать понятия в более
обобщенных, переопределенных и абстрактных терминах. В результате выражения
становятся более емкими, улучшается понимание и уменьшается объем повторяе¬
мой информации. И хотя в данный момент наше внимание сосредоточено на моде¬
ли предметной области, а не на модели проектирования, последующая реализацияМодель предметной областиРис. 23.2. Уточнение модели предметной области для второй итерации разработкиигры йМонополия ”
Глава 23. Быстрый дополнительный анализ 429суперклассов и подклассов в форме дерева наследования классов позволит значитель¬
но улучшить качество программного кода.Рассмотрим случаи, когда класс нужно разделять на подклассы.СоветСоздавайте подкласс суперкласса в следующих случаях.1. Подкласс имеет дополнительные атрибуты, интересующие разработчика.2. Подкласс имеет дополнительные ассоциации, интересующие разработчика.3. Подклассу соответствует понятие, управляемое, обрабатываемое, реагиру¬
ющее или используемое способом, отличным от способа, определенного
суперклассом или другими подклассами.Пункт 3 из приведенного выше перечня соответствует случаю разных типов кле¬
ток, попадание на которые обрабатываются по-разному в соответствии с правилами
игры. Основные понятия данной модели определяются правилами предметной об¬
ласти.Обновленная модель предметной области показана на рис. 23.2, на котором каж¬
дый конкретный вид клеток представлен в виде отдельного класса.Рекомендация. Приведем еще несколько советов по уточнению модели предметной
области.■ Класс Square следует объявить абстрактным.• Суперклассы обычно объявляют абстрактными. Хотя в данном случае супер¬
класс определяет понятие предметной области, программные суперклассы
обычно создают абстрактными.■ Имя суперкласса обычно добавляется к имени подкласса. Например,
IncomeTaxSquare, а не просто IncomeTax. Это соглашение отражает реальную
ситуацию, поскольку данный программный класс моделирует не налог, а клетку
оплаты налога в игре “Монополия”.■ Объект Regular Square, не предполагающий выполнение никаких специаль¬
ных действий, тоже моделируется с помощью отдельного понятия.■ В обновленной модели предметной области к классу Player добавлен атрибут
cash, поскольку на данной итерации реализуются денежные операции.
Вторая итерация
и дополнительные шаблоны■ Определить требования для второй итерации.Основная задачаВведениеВ главах, посвященных начальной фазе и первой итерации фазы развития, рас¬
сматривался ряд фундаментальных вопросов анализа и объектного проектирования,
на которых базируется построение объектных систем.При описании данной итерации основное внимание будет уделяться следующим
вопросам.■ Базовое объектное проектирование■ Использование шаблонов для получения единого проектного решения■ Применение UML для визуализации моделейЭти вопросы позволяют решить основные задачи данной книги и получить навы¬
ки грамотного проектирования.Что дальше?После завершения итерации 1 в данной главе определяются новые требования
для итерации 2. В следующей главе рассматривается применение шаблонов
GRASP для распределения обязанностей.СредствапостроениядиаграммUMLАнализ
на итерации 2Требования
итерации 2Шаблоны GRASP:
дополнительные
объектыПрименениешаблоновGoF
432 Часть IV. Вторая итерация фазы развития — дополнительные шаблоныСначала кратко будет описан этап анализа требований и построения модели пред¬
метной области, затем более пристальное внимание будет уделено вопросам проекти¬
рования. При описании первой итерации были изложены основные идеи и принци¬
пы проектирования. Конечно, на данной итерации выполняется и множество других
функций, связанных с анализом, проектированием и реализацией системы, однако
они не будут затронуты в данной книге, поскольку не оказывают решающего влияния
на процесс проектирования объектов.24.1. От первой ко второй итерацииК моменту завершения первой итерации получены следующие результаты.■ Все существующее на данный момент программное обеспечение протестирова¬
но с помощью модульных тестов, тестов загрузки, с точки зрения удобства ис¬
пользования и т.д. Одна из основных идей UP состоит в ранней, реалистичной
и непрерывной верификации качества и корректности кода. Ранняя обратная
связь обеспечивает возможность адаптации и модификации системы и нахож¬
дения “пути истинного”.■ Пользователи регулярно привлекались к оцениванию разработанной части си¬
стемы, обеспечению обратной связи с целью прояснения требований и адап¬
тации системы. Таким образом пользователи знают о текущем состоянии раз¬
работки системы.■ Все подсистемы интегрированы между собой и стабилизированы.Многие процессы в рамках первой итерации и перехода ко второй итерации не
будут рассмотрены детально, поскольку основное внимание в этой книге уделяется
вопросам ООА/П. Кратко остановимся на некоторых из них.■ Главные задачи следующей итерации определяются на семинаре, посвященном
вопросам планирования.■ В начале новой итерации с помощью CASE-средства выполняется обратное про¬
ектирование диаграмм UML на основе исходного кода, написанного во время
предыдущей итерации (в результате обновляется модель проектирования UP).
Полученную модель можно распечатать с высоким разрешением на плоттере и
повесить на стене для иллюстрации отправной точки для логического проекти¬
рования на следующей итерации.■ Продолжается анализ удобства использования и разработка пользовательского
интерфейса. Это чрезвычайно важный этап, определяющий успех многих при¬
ложений. Однако разработка интерфейса пользователя — это отдельный и не-
трцвиальный вопрос, изложение которого не входит в тему данной книги.■ Продолжается моделирование и разработка базы данных.■ Проводится очередной двухдневный семинар, в течение которого выполняется
развернутое описание следующих прецедентов. В течение фазы развития долж¬
ны быть реализованы 10% наиболее важных прецедентов с высокой степенью
риска. Одновременно происходит более глубокое изучение и определение 80%
прецедентов системы, большая часть которых будет реализована на более позд¬
них итерациях.
Глава 24. Вторая итерация и дополнительные шаблоны 433• К участию в семинаре привлекаются несколько разработчиков (в том числе
архитектор программной системы), выполнявших реализацию системы на
первой итерации. Тогда на семинаре будет учитываться реальное состояние
дел. Ключевая идея UP и итеративной разработки состоит в том, что для
прояснения требований не разрабатывается никакое дополнительное про¬
граммное обеспечение.Упрощения, принятые при рассмотрении примераВ реальных проектах в рамках UP требования к первым итерациям разрабатыва¬
ются с учетом риска и реального значения каждого прецедента в системе. Сначала
реализуются наиболее важные и критичные из них. Однако при рассмотрении основ¬
ного примера данной книги будет сделано отступление от этого принципа. Оно объ¬
ясняется необходимостью проиллюстрировать фундаментальные идеи и принципы
ООА/П на начальных итерациях. Поэтому для реализации на начальных итерациях
будут выбраны те требования, которые максимально способствуют решению задачи
обучения читателей, а не достижению целей проекта.24.2. Требования для второй итерации
POS-система NextGenНа второй итерации разработки POS-приложения NextGen будут реализованы сле¬
дующие требования.1. Поддержка различных внешних служб. Например, необходимо обеспечить воз¬
можность подключения к системе различных компонентов для вычисления на¬
логовых платежей с различными интерфейсами, различных бухгалтерских про¬
грамм и т.д. Все внешние программы имеют разные программные интерфейсы,
и их базовые функции реализуются по различным протоколам.2. Сложные правила вычисления стоимости.3. Обновление окна интерфейса пользователя при изменении общей стоимости
покупки.Эти требования будут рассмотрены в рамках реализации сценариев прецедента
Оформление продажи.Заметим, что эти требования не новы. Они были определены на начальной ста¬
дии реализации проекта. Например, проблема вычисления общей стоимости упоми¬
налась в исходном описании прецедента Оформление продажи.Основной успешный сценарий1. Покупатель подходит к кассовому аппарату POS-системы с выбранными товарами.2. Кассир открывает новую продажу.3. Кассир вводит идентификатор товара.4. Система записывает наименование товара и выдает его описание, цену и общую стоимость.
Цена вычисляется на основе набора правил.
434 Часть IV. Вторая итерация фазы развития — дополнительные шаблоныБолее того, в дополнительной спецификации содержится раздел, в котором опи¬
саны правила для вычисления стоимости и указана необходимость поддержки раз¬
личных внешних систем.Дополнительная спецификацияИнтерфейсы
Программные интерфейсыДля большинства внешних систем (вычисления налоговых платежей, системы складского учета,
бухгалтерской системы и т.д.) необходимо обеспечить возможность подключения через различные
интерфейсы.Бизнес-правилаНазваниеПравилоВозможность измененияИсточникПРАВ4Правила вычисления скидок (примеры)
Работник компании — скидка 20%
Привилегированный покупатель — 10%
Владелец “Золотой карты” — 15%Высокая вероятность из¬
менения. Каждая торговая
организация устанавливает
свои скидкиПолитикаторговыхорганизацийИнформация из предметной области
Ценовая политикаПомимо описанных выше правил ценообразования, каждому товару могут соответствовать две
цены: исходная и постоянная сниженная цена. Указанная цена товара (без вычисления положенных
скидок) соответствует постоянной сниженной цене, если таковая имеется. Однако организации со¬
храняют исходную цену даже при наличии постоянной сниженной для бухгалтерской отчетности.Инкрементальная разработка одного и того же
прецедента в течение нескольких итерацийНа основе этих требований на второй итерации продолжается реализация преце¬
дента Оформление продажи. Однако теперь реализуются новые сценарии. Таким об¬
разом система постепенно разрастается. Ситуация, когда различные сценарии одного
и того же прецедента рассматриваются в течение нескольких итераций, встречается
довольно часто. Система постепенно расширяется до тех пор, пока не будут реали¬
зованы все требования. В то же время простые прецеденты могут быть полностью
реализованы в течение одной итерации.Однако реализацию одного сценария не нужно растягивать на несколько итера¬
ций. В течение каждой итерации один или несколько сценариев должны быть реа¬
лизованы полностью.На первой итерации были приняты некоторые упрощения, чтобы проблема не
оказалась слишком сложной для решения в течение одной итерации. По этой же
причине для второй итерации было определено лишь несколько функциональных
требований.
Глава 24. Вторая итерация и дополнительные шаблоны 435Игра “Монополия”На второй итерации разработки игры “Монополия” реализуются следующие тре¬
бования.■ Продолжается реализация основного сценария прецедента Игра "Монополия":
фишки перемещаются по клеткам игральной доски. Как и ранее, игра происхо¬
дит в режиме эмуляции. Пользователь лишь задает количество игроков. Однако
на второй итерации реализуются некоторые специальные правила игры, опи¬
санные ниже.■ В начале игры каждый игрок получает $1500. Считается, что общая сумма денег
в игре не ограничена.■ При попадании на клетку Переход (Go) игрок получает $200.■ При попадании на клетку В тюрьму (Go to Jail) игрок перемещается на клетку
Тюрьма (Jail).• Однако, в отличие от реальных правил игры, отсюда легко выбраться. При
следующем ходе игрок бросает кубики и перемещается в позицию, определя¬
емую выпавшими значениями.■ При попадании на клетку Income Tax (Налог) игрок платит сумму, равную мини¬
муму из двух значений: 10% своих средств или $200.
Дополнительные шаблоны
GRASP для распределения
обязанностейУдача — это основа проектирования.Бранч Рики (Branch Rickey)Основная задача■ Научиться применять остальные шаблоны GRASP.ВведениеРанее были рассмотрены основные пять шаблонов GRASP.■ Information Expert (Информационный эксперт), Creator (Создатель), High
Cohesion (Высокое зацепление), Low Coupling (Слабое связывание) и Controller
(Контроллер)В состав шаблонов GRASP входят еще четыре шаблона.■ Polymorphism (Полиморфизм)■ Indirection (Перенаправление)■ Pure Fabrication (Чистая синтетика)■ Protected variations (Защищенные вариации)
438 Часть IV. Вторая итерация фазы развития — дополнительные шаблоныЧто дальше?После рассмотрения некоторых изменений в артефактах анализа и т ребований
для итерации 2 в данной главе описаны оставшиеся принципы GRASP и их
применение на конкретных примерах. В следующей главе рассматриваются
шаблоны проектирования GoF и способы их реального применения\Анализ
на итерации 2Требования
итерации 2Шаблоны GRASP:
дополнительные
объектыПрименениешаблоновпроектированияGoF О Требования
итерации 3На основе этих шаблонов можно значительно обогатить свой опыт проектирова¬
ния программных систем. В последующих главах будут также рассмотрены шаблоны
из набора GoF, разработанные так называемым “союзом четырех”. К шаблонам GoF
относятся Strategy (Стратегия) и Factory (Фабрика). После знакомства с этими шабло¬
нами фраза о том, что нужно применить шаблон Strategy на основе шаблона Factory
для удовлетворения требований шаблона Protected Variations и обеспечения низкой
степени связывания обретет новый смысл и информационную емкость, поскольку за
обычными именами шаблонов стоят сложные концепции проектирования.В последующих главах вводятся другие полезные шаблоны, применяемые на вто¬
рой итерации разработки рассматриваемых в книге примеров приложений.25.1. Шаблон PolymorphismПроблема: как обрабатывать альтернативные варианты поведения на основе
типа? Как создавать подключаемые программные компоненты?Альтернативные варианты поведения на основе типа. Условная передача управления —
это основная отличительная особенность любой программы. Если программа разра¬
ботана с использованием условных операторов типа if-then-else (если-то-иначе)
или операторов условного перехода по ключу, то при добавлении новых вариантов
поведения приходится модифицировать логику условных операторов. Такой подход
затрудняет процесс модификации программ в соответствии с новыми вариантами по¬
ведения, поскольку изменения приходится вносить сразу в нескольких местах про¬
граммного кода — там, где используются условные операторы.Подключаемые программные компоненты. Если рассматривать компоненты с точки
зрения отношения клиент/сервер, то как можно заменить один серверный компо¬
нент другим, не затрагивая при этом клиентские компоненты?Решение: если поведение объектов одного типа (класса) может изменяться, обя¬
занности распределяются для различных вариантов поведения с использованием по¬
лиморфных операций для этого класса1.1 Термин полиморфизм (polymorphism) имеет несколько взаимосвязанных значений. В дан¬
ном контексте он означает “присваивание одинаковых имен службам различных объектов”
[34], если эти службы однотипны или взаимосвязаны. Различные типы объектов зачастую ре¬
ализуют общий интерфейс или связываются между собой посредством иерархии и наследова¬
ния свойств общего суперкласса, однако такая реализация зависит от выбранного языка про¬
граммирования. Например, в языках с динамическим связыванием, таких как Smalltalk, этого
не требуется.
Глава 25. Дополнительные шаблоны GRASP для распределения обязанностей 439Совет. Используйте не проверку для типа объекта, а условную логику для реализа¬
ции различных альтернативных вариантов поведения на основе типа.ПримерыПриложение NextGen: как поддерживать работу внешних
систем вычисления налоговых платежей?POS-система NextGen должна поддерживать работу различных внешних систем
вычисления налоговых платежей (в том числе Tax-Master и Good-As-Gold ТахРго) и
интеграцию с другими внешними системами. Каждая система вычисления налоговых
платежей имеет свой интерфейс и обладает собственным поведением (хотя и ана¬
логичным поведению других систем). Один продукт может поддерживать протокол
TCP, другой — интерфейс SOAP, а третий — интерфейс Java RMI.Какие объекты должны отвечать за обработку различных внешних интерфейсов
систем вычисления налоговых платежей?Поскольку поведение службы адаптации внешней системы вычисления налоговых
платежей зависит от типа исподьзуемой программы вычисления (условно говоря,
калькулятора), согласно шаблону Polymorphism, необходимо каким-то образом рас¬
пределить обязанности по адаптации к различным типам калькуляторов. Для этого
можно использовать полиморфную операцию getTaxes (рис. 25.1).По шаблону Polymorphism несколько
адаптеров вычисления налоговых платежей
выполняют действия, соответствующие
различным внешним системам вычисления
налоговых платежейРис. 25.1. Использование полиморфизма при адаптации к различным внешним системам вы¬
числения налоговых платежей
440 Часть IV. Вторая итерация фазы развития — дополнительные шаблоныОбъекты, обеспечивающие адаптацию, — это не внешние калькуляторы, а локаль¬
ные программные объекты, представляющие внешние системы вычисления налого¬
вых платежей. При отправке сообщения локальному объекту выполняется обращение
к внешней системе с использованием ее собственного программного интерфейса.Каждому методу getTaxes в качестве параметра передается объект Sale, чтобы си¬
стема вычисления налоговых платежей могла проанализировать продажу. Реализации
каждого такого метода отличаются. Например, объект TaxMasterAdapter может
адаптировать запросы к системе Tax-Master и т.п.Система обозначений UML. Обратите внимание на обозначения UML для задания
интерфейсов (interface) (дескрипторов операций без реализации) и их реализации на
рис. 25.1.Игра “Монополия”: как спроектировать различное
поведение разных клеток игральной доски?Согласно правилам игры “Монополия”, когда игрок попадает на поле Go (Пере¬
ход), он получает $200. При попадании на другие клетки выполняются совсем другие
действия. То есть, для разных клеток действуют разные правила. Вспомним принцип
полиморфизма.Если поведение объектов одного типа (класса) может изменяться, обязанности
распределяются для различных вариантов поведения с использованием поли¬
морфных операций для этого класса. Следствие. Используйте не проверку для
типа объекта, а условную логику для реализации различных альтернативных
вариантов поведения на основе типа.Следовательно, для реализации вариантного поведения не следует использовать
оператор switch (для Java или С#), как в следующем примере.// неудачное проектное решениеSWITCH ON square.typeCASE GoSquare: игрок получает 200$CASE IncomeTaxSquare: игрок платит штрафСогласно принципу полиморфизма, для каждого типа с вариантным поведением
необходимо создать полиморфную операцию. К таким типам (классам) относятся
RegularSquare, GoSquare и т.д. Что это за операция? Она определяет действие,
выполняемое при попадании игрока в конкретную клетку. Эту полиморфную опера¬
цию можно назвать landedOn. Таким образом, согласно принципу полиморфизма,
для каждого типа клетки необходимо создать отдельный класс со своей операцией
landedOn и переопределить эту операцию в каждом из классов. Статическая диа¬
грамма классов, отражающая это проектное решение, показана на рис. 25.2.Применение UML. Обратите внимание на использование ключевого слова
{abstract} для операции landedOn на рис. 25.2.Рекомендация. Если в суперклассе не определяется поведение по умолчанию, по¬
лиморфную операцию в нем следует объявлять абстрактной.
Глава 25. Дополнительные шаблоны GRASP для распределения обязанностей 441РЦиег 1 !*“£>•* ,* jUftA*AO»\*1 J L • ••...Ofs,UndftiOrtРис. 25.2. Применение принципа полиморфизма при моделировании игры “Монополия ”Остается еще один интересный вопрос: как при этом изменятся диаграммы взаи¬
модействия? Какой объект должен отправлять сообщения landedOn клетке, на кото¬
рую попал игрок? Поскольку программный объект Player знает о текущем местона¬
хождении игрока, то согласно принципам Low Coupling и Expert именно он должен
отправлять это сообщение.Данное сообщение необходимо передавать по завершении метода takeTurn.
В главе 18 приводится проектное решение для операции takeTurn на первой итера¬
ции разработки. На рис. 25.3 и 25.4 показаны модифицированные динамические диа¬
граммы.0«г1оСЛ Л’1 1 —*Рис. 25.3. Применение принципа полиморфизма
442 Часть IV. Вторая итерация фазы развития — дополнительные шаблоныv*f СТ)<МТ)в 6*^Рис. 25.4. Операция landedOn для класса GoSquareПрименение UML■ На рис. 25.3 и 25.4 приводятся неформальные обозначения, приемлемые при
построении диаграмм UML вручную. При использовании автоматизированных
средств проектирования необходимо применять фреймы sd и ref.■ На рис. 25.3 объект Player помечен меткой р, которая используется в дальней¬
шем в качестве параметра сообщения landedOn. Из рис. 25.4 видно, что для
классов Square и Player желательно обеспечить видимость с помощью пара¬
метров.■ На рис. 25.3 объект Square помечен меткой 1ос (сокращение от location), ко¬
торая используется в дальнейшем в качестве возвращаемого значения сообще¬
ния getSquare.Рассмотрим каждый случай реализации полиморфной операции в терминах ша¬
блонов GRASP и проектных решений.■ GoSquare (рис. 25.4). Объект Player должен обладать информацией о финансо¬
вых возможностях игрока. Поэтому согласно шаблону Expert ему должно пере
даваться сообщение addCash. Значит, между объектами клетки и игрока должен
быть обеспечен необходимый уровень видимости, чтобы в качестве параметра
сообщения landedOn можно было передать значение р.■ RegularSquare (рис. 25.5). В данном случае ничего не происходит, что и от¬
мечено на диаграмме. Для этого можно было использовать специальный блок
комментария. В коде тело данного метода должно остаться пустым.■ IncomeTaxSquare (рис. 25.6). При попадании на эту клетку необходимо вычис¬
лить 10% от общей суммы, которой располагает игрок. Этой информацией об¬
ладает объект Player. Поэтому объект клетки должен обратиться к нему за не¬
обходимыми данными, чтобы иметь возможность вычислить соответствующую
сумму налога или штрафа.■ GoToJailSquare (рис. 25.7). При попадании на эту клетку изменится местопо¬
ложение игрока, поэтому согласно шаблону Expert он должен получить сообще¬
ние setLocation. При этом координаты клетки должны передаваться в каче¬
стве параметра объекту Player.
Глава 25. Дополнительные шаблоны GRASP для распределения обязанностей 443П 4U.Рис. 25.5. Операция landedOn для класса RegularSquareТ|«Т)« wJwyЬ р—tr— ^Рис. 25.6. Операция landedOn для класса IncomeTaxSquare<Л1--ioтT)«4btSwbfЦ*4Рис. 25.7. Операция landedOn для класса GoToJailSquareОбозначения UML. На рис. 25.4 вертикальные линии жизни изображены в виде
сплошной черты, а не пунктиром. Это более удобно для построения диаграмм вруч¬
ную. Более того, UML 2 допускает оба формата обозначений. Главное, чтобы участ¬
ники команды разработчиков понимали друг друга.Улучшение уровня связыванияВ главе 18 речь шла о том, что на первой итерации разработки информацией о
местоположении клетки обладает объект Piece, а не Player (см. рис. 18.25). Поэтому
объекту Player для получения местонахождения клетки приходилось отправлять со¬
общение getSquare объекту Board, а затем новое местоположение присваивалось
444 Часть IV. Вторая итерация фазы развития — дополнительные шаблоныобъекту Piece. Это довольно неудачное проектное решение, особенно теперь, когда
объекту Player приходит сообщение landedOn, соответствующее объекту Square.
В чем недостаток этого решения? Проблема состоит в уровне связывания.Очевидно, объект Player должен постоянно обладать информацией о соответ¬
ствующем ему объекте Square, поскольку он с ним взаимодействует. Этот момент мо¬
жет стать одной из задач рефакторинга.Следовательно, на второй итерации разработки проектное решение следует улуч¬
шить, поместив информацию о местоположении клетки в объект Player, а не Piece.
Эта ситуация отображена на рис. 25.2 и 25.3.У читателя может возникнуть вопрос: а нужен ли в модели проектирования объект
Piece? В реальной жизни маленькая пластиковая фишка является удобным объектом-
посредником при взаимодействии человека с игральной доской, поскольку сам игрок
вряд ли станет передвигаться по доске. (Лучше он сходит на кухню за холодным пи¬
вом.) Однако в программной реализации роль такой фишки может выполнять объект
Player.Обсуждение. Полиморфизм — это основной принцип проектирования поведения
системы в рамках обработки аналогичных ситуаций. Если обязанности в системе рас¬
пределены на основе шаблона Polymorphism, то такую систему можно легко модифи¬
цировать, добавляя в нее новые вариации. Например, добавив класс для адаптации
новой системы вычисления налоговых платежей со своим полиморфным методом
getTaxes, разработчик никак не повлияет на дееспособность уже существующей ча¬
сти системы.Когда применять интерфейсыПолиморфизм предполагает реализацию с помощью абстрактных суперклассов
или интерфейсов. Когда следует применять интерфейсы? Общая рекомендация со¬
стоит в том, что интерфейсы добавляются для поддержки полиморфизма при неиз¬
вестной заранее иерархии классов. Если абстрактный суперкласс АС используется без
интерфейса, то любые новые полиморфные ситуации необходимо реализовывать с
помощью его подкласса. Это достаточно неудобно в таких языках, как Java или С#,
поддерживающих только одиночное наследование. Если в иерархии классов содер¬
жится абстрактный класс С1, попытайтесь создать интерфейс II, содержащий сигна¬
туры открытых методов С1, а затем объявите, что С1 реализует II. Более того, интер¬
фейсы обеспечивают “гибкую точку” вариаций для неизвестных ситуаций.Когда не нужно использовать шаблон. Иногда разработчики систем злоупо¬
требляют добавлением интерфейсов и применением принципа полиморфизма с це¬
лью обеспечения дееспособности системы в неизвестных заранее новых ситуациях.
Если точка вариаций известна и обоснована, если существует высокая вероятность
вариантного поведения, то такие усилия по обеспечению гибкости системы и при¬
менению принципа полиморфизма вполне оправданны. Однако к применению этого
принципа нужно подходить критически, поскольку зачастую усилия по обеспечению
вариантов поведения “на все случаи жизни” затрачиваются впустую. Реально оцени¬
вайте вероятность вариантного поведения.Преимущества■ С помощью шаблона впоследствии можно легко расширять систему, добавляя в
нее новые вариации.
Глава 25. Дополнительные шаблоны GRASP для распределения обязанностей 445■ Новые реализации можно вводить без модификации клиентской части прило¬
жения.Связанные шаблоны■ Protected Variations (Защищенные вариации).■ Множество популярных шаблонов GoF [58], которые будут описаны в после¬
дующих главах, основаны на применении принципа полиморфизма. К числу
таких шаблонов относятся Adapter (Адаптер), Command (Команда), Composite
(Композит), Proxy (Прокси), State (Состояние) и Strategy (Стратегия).Также известен как; аналогичен. Choosing Message (Выбор сообщения), Don’t
Ask “What Kind?” (He спрашивай “Что это?”).25.2. Шаблон Pure FabricationПроблема: какой класс должен обеспечить реализацию шаблонов High Cohesion
и Low Coupling или других принципов проектирования, если шаблон Expert (напри¬
мер) не обеспечивает подходящего решения?Объектно-ориентированные системы отличаются тем, что программные классы
реализуют понятия предметной области, как, например, классы Sale и Customer.
Однако существует множество ситуаций, когда распределение обязанностей только
между такими классами приводит к проблемам с зацеплением и связыванием, т.е. с
невозможностью повторного использования кода.Решение: присвоить группу обязанностей с высокой степенью зацепления искус¬
ственному классу, не представляющему конкретного понятия предметной области,
т.е. синтезировать искусственную сущность для поддержки высокого зацепления, сла¬
бого связывания и повторного использования.Такой класс является продуктом нашего воображения и представляет собой син¬
тетику (fabrication). В идеале присвоенные этому классу обязанности поддерживают
высокую степень зацепления и низкое связывание, так что структура этого синтети¬
ческого класса является очень прозрачной, или чистой (pure). Отсюда и название:
Pure Fabrication (“чистая синтетика”).И наконец, словосочетание “чистая синтетика” подразумевает создание некото¬
рой сущности в тот момент, когда разработчик “близок к отчаянию”.ПримерыПриложение NextGen: сохранение объекта Sale в базе данныхПредположим, необходимо сохранять экземпляры класса Sale в реляционной
базе данных. Согласно шаблону Information Expert, эту обязанность можно присвоить
самому классу Sale. Однако следует принять во внимание следующие моменты.■ Данная задача требует достаточно большого числа специализированных опе¬
раций, связанных со взаимодействием с базой данных и никак не связанных с
понятием самой продажи. Поэтому класс Sale получает низкую степень заце¬
пления.■ Класс Sale должен быть связан с интерфейсом реляционной базы данных (та¬
ким, как JDBC для технологии Java). Поэтому возрастает степень связывания,
446 Часть IV. Вторая итерация фазы развития — дополнительные шаблоныпричем даже не с другим объектом предметной области, а с интерфейсом базы
данных.■ Хранение объектов в реляционной базе данных — это достаточно общая задача,
решение которой необходимо для многих классов. Возлагая эту обязанность на
класс Sale, разработчик не обеспечивает возможности повторного использова¬
ния этих операций и вынужден дублировать их в других классах.Поэтому, несмотря на то, что по логике вещей класс Sale является хорошим кан¬
дидатом для выполнения обязанности самосохранения в базе данных, согласно ша¬
блону Information Expert, такое распределение обязанностей приводит к низкой сте¬
пени зацепления, сильному связыванию и невозможности повторного использования
кода. Это именно та безвыходная ситуация, в которой необходимо “синтезировать”
нечто новое.Естественным решением данной проблемы является создание нового класса,
ответственного за сохранение объектов некоторого вида на постоянном носите¬
ле, например в реляционной базе данных. Его можно назвать PersistentStorage2
(Постоянное хранилище). Этот класс является продуктом нашего воображения, что
полностью соответствует шаблону Pure Fabrication.В соответствии
с шаблоном
Pure FabricationОбратите внимание на имя класса PersistentStorage, оно вполне понятно, хотя
объект с аналогичным названием отсутствует в модели предметной области. Если
разработчик спросит сотрудников магазина, работают ли они с объектами из посто¬
янного хранилища, то его, скорее всего, не поймут. Им известны понятия “продажа”
или “платеж”. PersistentStorage — это не понятие из предметной области, а нечто,
синтезированное для удобства разработчика программы.Этот чисто синтетический объект решает следующие задачи.■ Класс Sale сохраняет высокую степень зацепления и слабое связывание.■ Класс PersistentStorage также обладает этими свойствами, выполняя един¬
ственную задачу: сохранение объектов на постоянном носителе.■ Класс PersistentStorage является достаточно общим и допускает повторное
использование.Этот пример — типичная ситуация для создания “чисто синтетического” класса.
Он позволяет избежать проблем с зацеплением и связыванием и обеспечивает новые
возможности для повторного использования.PersistentStorageinsert(Object)
update(Object)2 В реальных задачах, как правило, требуется несколько “чисто синтетических” классов.
Такие объекты обеспечивают интерфейсы взаимодействия для множества вспомогательных
объектов.
Глава 25. Дополнительные шаблоны GRASP для распределения обязанностей 447Обратите внимание, что, подобно остальным шаблонам GRASP, в данном шаблоне
основное внимание уделяется распределению обязанностей. В нашем примере обя¬
занности передаются от класса Sale (выбранного согласно шаблону Expert) новому
“чисто синтетическому” классу.Игра “Монополия”: обработка процедуры бросания кубиковПри обсуждении проблемы рефакторинга рассматривался пример реализации
процедуры бросания кубиков и применения приема извлечения метода из существу¬
ющего метода Player.takeTurn. В завершение рассмотренного примера отмечалось,
что принятое решение является неидеальным и позднее будет представлено более
предпочтительное решение.В текущей реализации системы за бросание кубиков и вычисление общей суммы
очков отвечает объект Player. Кубики являются достаточно распространенными
объектам и используются во многих играх. Однако если процедура бросания и вы¬
числения полученных значений реализуется в объекте Player, то поведение кубиков
нельзя обобщить для использования в других играх. Кроме того, выпавшую сумму
значений нельзя получить без повторного бросания кубиков.Реализация этой функции с помощью другого объекта из предметной области
игры “Монополия” приводит к тем же проблемам. Следовательно, необходимо вос¬
пользоваться шаблоном Pure Fabrication.В игре “Монополия” кубики вбрасываются без использования дополнительной
емкости. Однако во многих играх кубики сначала помещаются в некоторую емкость
(например, в стакан, горлышко которого прикрыто ладонью), перемешиваются, а за¬
тем выбрасываются на стол. Поэтому можно ввести “чисто синтетический” объект
Сир, в котором будут содержаться кубики. Этот объект будет отвечать за вбрасывание
кубиков и вычисление общей суммы очков. Новое проектное решение показано на
рис. 25.8 и 25.9. Объект Сир содержит коллекцию объектов Die. Когда ему передается
сообщение roll, он перенаправляет его всем объектам Die.Обсуждение. Проектируемые объекты делятся на две следующие группы.1. Создаваемые на основе декомпозиции представления.2. Создаваемые на основе декомпозиции поведения.Например, программный класс Sale был создан на основе декомпозиции представ¬
ления, поскольку он представляет понятие предметной области (или связан с ним).Рис. 25.8. Диаграмма классов с учетом класса Сир
448 Часть IV. Вторая итерация фазы развития — дополнительные шаблоны»I4Рис. 25.9. Использование класса Сир в игре иМонополия ”Декомпозиция представления — это типичная стратегия объектного проектирова¬
ния, позволяющая сократить разрыв между реальными объектами и их программным
представлением. Однако иногда возникает потребность распределить обязанности на
основе однотипного поведения или реализации некоторого алгоритма, не привязы¬
ваясь к понятиям реального мира.Хорошим примером объекта-алгоритма является генератор оглавления TableOf-
ContentsGenerator. Это вспомогательный класс, не имеющий аналога в словаре тер¬
минов из предметной области книг или документов. Он предназначен для удобства
разработчиков, поскольку в нем сосредоточены методы, реализующие некоторое
однотипное поведение. То есть, этот класс создан на основе декомпозиции поведения.В отличие от рассмотренного примера, класс TableOfContents основан на деком¬
позиции представления, поскольку он реализует конкретное понятие из реального
мира (список наименований глав).Вспомогательный класс не обязательно должен быть “чисто синтетическим”. Это
название служит скорее целям обучения, поскольку отражает общую идею распреде¬
ления обязанностей между программными классами: некоторые классы представляют
понятия предметной области, а другие создаются просто для удобства разработчиков.
Эти вспомогательные классы зачастую объединяются в группы на основе общности
поведения и соответствуют принципу декомпозиции поведения, а не представления.Другими словами, согласно шаблону Pure Fabrication, классы проектируются на
основе общей функциональности и представляют собой поведенческие или функцио¬
нально-ориентированные объекты.Многие существующие шаблоны объектно-ориентированного проектирования яв¬
ляются примерами использования шаблона Pure Fabrication. К ним можно отнести
шаблоны Adapter, Strategy, Command и т.д. [58].Напоследок вспомним основное назначение шаблона Pure Fabrication. Иногда ре¬
шение, соответствующее шаблону Information Expert, не подходит для других шабло¬
нов проектирования. С одной стороны, объект является хорошим кандидатом на вы¬
полнение некоторой обязанности, поскольку обладает всей необходимой для этого
Глава 25. Дополнительные шаблоны GRASP для распределения обязанностей 449информацией, а с другой — такое распределение обязанностей приводит к наруше¬
нию принципов зацепления и связывания.Преимущества■ При использовании шаблона Pure Fabrication реализуется шаблон High Cohe¬
sion, поскольку обязанности передаются отдельному классу, сконцентрирован¬
ному на решении специфического набора взаимосвязанных задач.■ Повышается потенциал повторного использования, поскольку чисто синтети¬
ческие классы можно применять в других приложениях.Когда не нужно использовать шаблон. Новички в области объектно-ориенти¬
рованного проектирования, имеющие опыт разработки программ в рамках струк¬
турного или функционального подхода, зачастую “злоупотребляют” использованием
шаблона Pure Fabrication. В их трактовке функции просто превращаются в объекты.
Нет ничего предосудительного в создании функционально-ориентированных или
алгоритмически-ориентированных объектов. Однако необходимо соблюдать пропор¬
ции между количеством таких объектов и объектов, созданных на основе декомпо¬
зиции представления, согласно шаблону Information Expert. Класс Sale тоже имеет
право на существование и должен выполнять свои обязанности. Созданные на основе
шаблона Information Expert объекты обладают информацией, необходимой для вы¬
полнения своих обязанностей, и соответствуют принципу слабого связывания объек¬
тов. При “злоупотреблении” применением шаблона Pure Fabrication нарушаются
требования к слабому связыванию объектов. Типичным симптомом такой ситуации
является необходимость передачи данных одного объекта другим объектам для вы¬
полнения действий над ними.Связанные шаблоны■ Low Coupling.■ High Cohesion.■ Классы, созданные согласно шаблону Pure Fabrication, обычно имеют обязан¬
ности, которые, в соответствии с шаблоном Expert, должны быть возложены на
классы предметной области.■ Многие шаблоны проектирования GoF являются примерами использования
шаблона Pure Fabrication (к их числу относятся Adapter (Адаптер), Command
(Команда), Strategy (Стратегия) и т.д. [58]).■ Все остальные шаблоны проектирования также реализуют принципы шаблона
Pure Fabrication.25.3. Шаблон IndirectionПроблема: как распределить обязанности, чтобы обеспечить отсутствие прямого
связывания; снизить уровень связывания объектов, согласно шаблону Low Coupling,
и сохранить высокий потенциал повторного использования?Решение: присвоить обязанности промежуточному объекту для обеспечения свя¬
зи между другими компонентами или службами, которые не связаны между собой на¬
прямую.При таком подходе связи перенаправляются к другим компонентам или службам.15 3ак. 3357
450 Часть IV. Вторая итерация фазы развития — дополнительные шаблоны
ПримерыКласс TaxCalculatorAdapterЭти объекты обеспечивают связь с внешними службами вычисления налоговых
платежей. Согласно шаблону Polymorphism, они обеспечивают единый интерфейс
взаимодействия с внутренними объектами и скрывают вариации программных интер¬
фейсов внешних систем. Добавляя возможность перенаправления и обеспечивая реа¬
лизацию принципов полиморфизма, объекты-адаптеры защищают внутренние объек¬
ты системы от возможного изменения интерфейсов внешних систем (рис. 25.10).: Sale:TaxMasterAdaptert = getTotal ,
 ►г1taxes := getTaxes(s)Взаимодействие
с сокетом TCP1 сь..«actor»:TaxMasterAdapter...OАдаптер функционирует
как средствоперенаправления данных к
внешним системам Рис. 25.10. Перенаправление связей с помощью адаптеровПрименение UML. Обратите внимание на обозначение внешнего вспомогатель¬
ного приложения TaxMasterSystem на рис. 25.10. Оно помечено ключевым словом
«исполнитель», обозначающим внешний программный компонент.Класс PersistentStorageВ примере, приведенном при рассмотрении шаблона Pure Fabrication, класс Sale
отделяется от служб взаимодействия с реляционной базой данных посредством введе¬
ния класса PersistentStorage. Этот же пример соответствует реализации шаблона
Indirection. Класс PersistentStorage выступает в роли промежуточного звена меж¬
ду классом Sale и базой данных.Обсуждение. Большинство проблем, связанных с компьютерными науками, можно
решить с помощью нового уровня перенаправления — это старая истина, применимая и к
объектно-ориентированному проектированию3.Точно так же, как многие шаблоны проектирования являются частным случаем
шаблона Pure Fabrication, существует множество специализированных вариантов ша¬
блона Indirection. Примерами таких шаблонов являются Adapter, Facade и Observer
[58]. Кроме того, многие вариации шаблона Pure Fabrication зачастую базируются на3 Это высказывание принадлежит Дэвиду Вилеру (David Wheeler). Заметим, чтЬ известно и
другое высказывание: “Большинство проблем, связанных с производительностью, можно ре¬
шить, удалив новый уровень перенаправления!”
Глава 25. Дополнительные шаблоны GRASP для распределения обязанностей 451основном принципе перенаправления связи по шаблону Indirection. Целью такого
перенаправления обычно является слабое связывание, обеспечиваемое за счет отде¬
ления друг от друга различных компонентов или служб.Преимущества. Слабое связывание между компонентами.Связанные шаблоны и принципы■ Protected Variations.■ Low Coupling.■ Многие шаблоны GoF, в том числе Adapter, Bridge, Observer и Mediator [58].■ Различные частные случаи использования шаблона Pure Fabrication.25.4. Шаблон Protected VariationsПроблема: как спроектировать объекты, подсистемы и систему, чтобы изменение
этих элементов не оказывало нежелательного влияния на другие элементы?Решение: идентифицировать точки возможных вариаций или неустойчивости;
распределить обязанности таким образом, чтобы обеспечить устойчивый интер¬
фейс.Заметим, что термин “интерфейс” в данном случае используется для обозначения
способа обеспечения доступа и не сводится к понятию интерфейса Java.Пример. Вернемся к рассмотренной выше проблеме взаимодействия с различны¬
ми системами вычисления налоговых платежей. Решение этой проблемы на основе
шаблона Polymorphism в то же время иллюстрирует применение шаблона Protected
Variations (см. рис. 25.1). В данном случае точкой вариации или неустойчивости явля¬
ются различные интерфейсы или API внешних систем вычисления налоговых плате¬
жей. POS-система должна обеспечить интеграцию с различными известными (а так¬
же еще не существующими) системами вычисления налоговых платежей.Добавив уровень (или интерфейс) перенаправления на основе принципа полимор¬
физма, можно разработать разные реализации интерфейса ITaxCalculatorAdapter,
защитив систему от возможного изменения внешних интерфейсов. Тогда внутренние
объекты смогут взаимодействовать с устойчивым интерфейсом, а детали взаимодей¬
ствия с внешними системами будут скрыты в конкретных реализациях адаптеров.Обсуждение. Protected Variations — это важный фундаментальный принцип раз¬
работки программных систем. Практически все основные свойства проектных ре¬
шений, описанных в этой книге, — инкапсуляция данных, полиморфизм, проекти¬
рование на основе данных, интерфейсы, виртуальные машины, конфигурационные
файлы, операционные системы и т.п., — являются частным случаем реализации этого
шаблона.Шаблон Protected Variations (PV) впервые был описан Кокбурном в [120], хотя
этот фундаментальный принцип проектирования известен уже несколько десятиле¬
тий под другими названиями, в том числе под именем принципа сокрытия информа¬
ции (information hiding) [102].Механизмы, реализуемые с помощью шаблона PVШаблон PV описывает ключевой принцип, на основе которого реализуются меха¬
низмы и шаблоны программирования и проектирования с целью обеспечения гибко¬
сти и защиты системы от влияния изменений внешних систем.
452 Часть IV. Вторая итерация фазы развития — дополнительные шаблоныВ процессе реализации шаблона PV совершенствуется уровень разработчиков и
архитекторов, поскольку они должны реализовать подходящее решение для этого
шаблона. На начальных стадиях обучения программированию человек знакомится
с инкапсуляцией данных, интерфейсами и принципом полиморфизма — базовыми
механизмами шаблона PV. Затем он осваивает новые приемы и области, такие как
интерпретаторы правил, проектирование на основе метаданных, виртуальные маши¬
ны — средства защиты системы от возможных вариаций.Рассмотрим некоторые примеры.Базовые механизмы защиты от вариацийИнкапсуляция данных, интерфейсы, полиморфизм, перенаправление — все эти
принципы реализуются в рамках шаблона PV. Заметим, что компоненты, в том числе
брокеры и виртуальные машины, — это сложные примеры перенаправления с целью
реализации принципа PV.Проектирование на основе данныхЭто широкий спектр методов, включая чтение кодов, значений, путей к файлам
классов, имен классов из внешнего источника с целью обеспечения возможности
изменения поведения или “параметризации” системы на этапе выполнения. К дру¬
гим вариациям этих методов относятся листы стилей, метаданные для отображения
объектов в реляционное представление, файлы свойств, чтение макетов и т.д. Защита
системы от изменения данных, метаданных или других вариаций обеспечивается за
счет внешнего расположения изменчивой информации и ее чтения на этапе выпол¬
нения программы.Поиск службПоиск служб подразумевает использование служб именования (например, JNDI
для Java) или средств получения доступа к службе (например, Jini для Java или UDDI
для служб Web). Клиенты в этом случае защищены от изменения расположения
служб: они могут использовать стандартный интерфейс поиска служб. Это специаль¬
ный случай проектирования на основе данных.Проектирование на основе интерпретаторовПроектирование на основе интерпретаторов предполагает включение интерпре¬
таторов правил, выполняющих правила и считывающих их из внешнего источника,
интерпретаторов сценариев или языков программирования, считывающих инфор¬
мацию и запускающих программы, виртуальных машин, нейронных сетей, механиз¬
мов реализации логики ограничений и т.д. Такой подход позволяет изменять или
параметризировать поведение системы с помощью внешних логических выражений.
Система защищена от изменения логики за счет внешнего расположения описания
этой логики, считывания его и использования интерпретатора.Рефлексивное проектирование, или
проектирование на метауровнеПримером реализации этого подхода является использование java. bean s.
Introspector для получения объекта Beanlnfo, запрашивающего имя метода, реа¬
лизующего свойство компонента X и вызывающего Метод.invoke. При этом система
остается защищенной от влияния логики и изменения кода внешних компонентов
Глава 25. Дополнительные шаблоны GRASP для распределения обязанностей 453за счет использования служб метаязыка. Это проектное решение является частным
случаем проектирования на основе данных.Унифицированный доступНекоторые языки, такие как Ada, Eiffel и С#, поддерживают синтаксические кон¬
струкции, при которых доступ к полям и методам классов осуществляется одинаково.
Например, запись aCircle.radius может означать и вызов метода radius (): float,
и прямое обращение к открытому полю, в зависимости от определения класса. Тогда
открытые поля можно преобразовывать в метод доступа без изменения кода клиент¬
ских объектов.Стандартные языкиОфициальные стандарты языков, в частности SQL, тоже обеспечивают выполне¬
ние шаблона Protected Variations.Принцип подстановки ЛисковаПринцип подстановки Лискова [88] — это формализация защиты от влияния из¬
менений в различных реализациях интерфейса или расширениях суперкласса.Приведем цитату.“Здесь требуется использовать следующее свойство подстановки: если для каж¬
дого объекта о1 типа S существует объект о2 типа Т, такой что для всех про¬
грамм Р, определенных в терминах Т, поведение Р не изменяется при заменео2 на ol, то S является подтипом Т” [88].Неформально это можно выразить так. Программные элементы (методы, классы
и т.д.), ссылающиеся на тип Т (некоторый интерфейс или суперкласс), должны кор¬
ректно работать при подстановке вместо Т любой его реализации или подкласса S.
Вот пример.public void addTaxes( ITaxCalculatorAdapter calculator, Sale sale ){List taxLineltems = calculator.getTaxes ( sale );//...}He имеет значения, какая из реализаций класса ITaxCalculatorAdapter переда¬
ется в качестве реального параметра метода addTaxes, метод продолжает работать
“как и ожидалось”. Идея принципа подстановки Лискова проста и интуитивно понят¬
на многим разработчикам объектных программ.Сокрытие структурыВ первой редакции этой книги упоминался важный принцип объектного проек¬
тирования, получивший название Don’t Talk to Strangers (He разговаривайте с не¬
знакомцами) или Law of Demeter (Закон Деметры) [87]. Этот принцип был назван
одним из девяти шаблонов GRASP. Вкратце он сводится к необходимости избегать
проектных решений, предполагающих передачу сообщений (или разговоры) с уда¬
ленными непрямыми объектами (или незнакомцами). Непрямыми считаются объек¬
ты, известные другим объектам, но не самому клиенту. Такое проектное решение обе¬
спечивает устойчивость системы к изменению структуры объектов. А это довольно
454 Часть IV. Вторая итерация фазы развития — дополнительные шаблонытипичная точка неустойчивости. Однако во втором издании книги вместо шаблона
Don’t Talk to Strangers рассматривается более общий шаблон PV, для которого Don’t
Talk to Strangers является частным случаем. Таким образом, чтобы обеспечить защиту
от влияния структурных изменений, применяется шаблон Don’t Talk to Strangers.Шаблон Don’t Talk to Strangers налагает ограничения на перечень объектов, кото¬
рым определенный метод должен отправлять сообщения. Этот “закон” гласит, что в
рамках метода сообщения должны отправляться только следующим объектам.1. Объекту this (или self).2. Параметру этого метода.3. Атрибуту объекта this.4. Элементу коллекции, являющемуся атрибутом объекта self.5. Объекту, созданному внутри метода.Основная цель этого шаблона — избежать связывания клиентского объекта с не¬
прямыми объектами.Прямые объекты — это “знакомые” клиента, а непрямые — “незнакомцы”. Клиент
должен общаться только со “знакомыми” и не разговаривать с “незнакомцами”.Для выполнения этих требований прямым объектам могут понадобиться новые
операции, которые выступают в роли дополнительных операций, позволяющих из¬
бежать “разговоров с незнакомцами”.Рассмотрим пример, демонстрирующий нарушение принципа Don’t Talk to
Strangers. После кода приводятся его комментарии и объяснения по поводу наруше¬
ния принципа шаблона.class Register{private Sale sale;public void slightlyFragileMethod (){// sale.getPayment () отправляет сообщение знакомому (вариант 3)// однако в выражении sale.getPayment().getTenderedAmount()// сообщение getTenderedAmount() передается незнакомцу PaymentMoney amount = sale.getPayment().getTenderedAmount();//. . .}//. . .}В этом коде устанавливается соединение объекта Sale с “незнакомцем” Payment,
а затем этому объекту передается сообщение. Это довольно неустойчивое решение,
поскольку для передачи сообщения сначала необходимо установить связь между объ¬
ектами Sale и Payment. Однако на самом деле здесь нет никакой проблемы.Рассмотрим еще один фрагмент.public void moreFragileMethod (){AccountHolder holder =sale.getPayment().getAccount().getAccountHolder();//.}
Глава 25. Дополнительные шаблоны GRASP для распределения обязанностей 455Эту ситуацию можно представить в общем виде.public void doX(){F someF = foo.getA().getB().getC().getD().getE().getF();// ...}Это искусственный пример, однако с его помощью можно проиллюстрировать
передачу сообщения непрямому объекту путем установки цепочки связей. Это про¬
ектное решение зависит от конкретной структуры связей между объектами. Причем
чем дальше по цепочке передается сообщение, тем неустойчивее становится связь
между начальным и конечным объектами.Карл Либерхерр (Karl Lieberherr) со своими коллегами исследовал принципы
хорошего проектирования объектов в ракурсе закона Деметры. Шаблон Don’t Talk
to Strangers (или закон Деметры) был сформулирован потому, что неустойчивость
объектной структуры довольно часто приводит к необходимости модификации кода,
построенного на знании типа связи между объектами.Как будет видно из следующего раздела, этому шаблону нужно следовать не всегда.
Все зависит от самой структуры объектов. В стандартных библиотеках (например, в
библиотеках Java) структурные связи между классами объектов довольно устойчивы.
В почти готовых системах структура объектов тоже довольно устойчива. Однако на
ранних итерациях выполнения проекта объектная структура еще не стабильна.В целом, чем длиннее цепочка передачи сообщения, тем более неустойчивой яв¬
ляется связь между исходным и конечным объектами, поэтому в такой ситуации нуж¬
но следовать шаблону Don’t Talk to Strangers.Строгое следование принципу этого шаблона, призванного защитить систему от
влияния структурных изменений, требует добавления новых открытых операций для
классов-знакомых. Эти операции обеспечивают получение требуемой информации,
оставляя “за кадром” способ ее получения. Например, для реализации принципов ша¬
блона Don’t Talk to Strangers в двух приведенных выше случаях требуется определить
следующие операции.// случай 1Money amount = sale.getTenderedAmountOfPayment();// случай 2AccountHolder holder = sale.getAccountHolderOfPayment();Когда не следует применять шаблон. Следует определить два типа особых точек.■ Точка вариации (variation point) — точка ветвления в существующей на данный
момент системе или в требованиях к ней, например, необходимость поддержки
нескольких интерфейсов для систем вычисления налоговых платежей.■ Точка эволюции (evolution point) — предполагаемая точка ветвления, которая
может возникнуть в будущем, однако не определяемая существующими требова¬
ниями.44 В рамках UP точки эволюции могут быть формально зафиксированы в разделах
“Возможные изменения” (Change cases). В каждом таком разделе описываются соответствую¬
щие аспекты возможных точек эволюции в разрабатываемой архитектуре.
456 Часть IV. Вторая итерация фазы развития — дополнительные шаблоныШаблон PV применяется и к точкам вариации, и к точкам эволюции.Следует сделать оговорку. Иногда для реализации точек эволюции требуется го¬
раздо больше усилий, чем для реализации простого проектного решения без учета
этих точек. В таком случае лучше остановиться на неробастном решении и модифи¬
цировать его по мере необходимости (в случае реальных, а не предполагаемых из¬
менений).Например, автору пришлось участвовать в создании системы обработки “бумаж¬
ных” сообщений, к которой архитектор добавил язык сценариев и интерпретатор
для этого языка с целью повышения гибкости системы и поддержки точек эволюции.
Однако впоследствии от сложного (и неэффективного) языка сценариев пришлось
отказаться, поскольку он был просто не нужен. В начале своей карьеры программиста
объектно-ориентированных систем (в начале 1980-х годов) автор старался создавать
максимально обобщенный код и тратил много времени на создание суперклассов для
действительно нужных ему классов. Он стремился добиться максимальной общности
кода и его гибкости (хотел защитить его от вариаций) в расчете на последующие из¬
менения, которые так никогда и не понадобились. В то время автор не знал, когда
действительно нужно закладывать в систему робастные решения.Эти примеры приведены не с целью пропаганды неробастных решений и последу¬
ющей переработки системы. Если необходимость защиты от влияния возможных ва¬
риаций действительно существует, нужно придерживаться шаблона PV. Однако если
в системе зафиксированы лишь точки эволюции, вероятность реализации которых
очень низка, то, принимая робастное проектное решение, следует хорошо взвесить
все “за” и “против”.Неопытные разработчики зачастую тяготеют к неробастным проектным решени¬
ям, более опытные уделяют слишком большое внимание гибкости системы и стремят¬
ся к обобщениям (даже если они никогда не понадобятся). Самые опытные специали¬
сты выбирают промежуточное решение, тщательно оценивая вероятность возможных
модификаций и усилия, необходимые для обеспечения робастного решения.Преимущества■ Легкость добавления новых расширений и вариаций.■ Возможность добавления новых реализаций, не затрагивая клиента.■ Слабое связывание.■ Минимизация влияния изменений.Связанные шаблоны и принципы■ Большинство принципов и шаблонов проектирования обеспечивает механизмы
для реализации шаблона PV. К их числу относятся принципы полиморфизма,
перенаправления, инкапсуляции данных, шаблоны GoF, Indirection и т.д.■ В [104] точки вариации и эволюции названы “горячими точками”.Также известен под именем. Шаблон PV соответствует принципам сокрытия
информации и ОСР (Open-Closed Principle). Свое официальное название Protected
Variations он получил в 1996 году в [120].
Глава 25. Дополнительные шаблоны GRASP для распределения обязанностей 457Сокрытие информацииИзвестная статья Дэвида Парнаса [102] — это пример классического произведе¬
ния, которое часто цитируют, но редко читают. В этой статье автор вводит концеп¬
цию сокрытия информации. Поскольку этот термин, на первый взгляд, близок поня¬
тию инкапсуляции данных, то его неправильно интерпретировали и в некоторых
книгах определяют как синоним этого понятия. Однако идея Парнаса заключалась в
сокрытии информации о проектном решении, относящемся к точкам ветвления или
возможных изменений, от других модулей. Пропагандируемый автором статьи прин¬
цип проектирования сводится к следующему.Мы предлагаем сначала составить список сложных проектных решений, или
проектных решений, подлежащих возможному изменению. Затем при разра¬
ботке каждого модуля нужно скрыть детали реализации этого решения от дру¬
гих модулей.Таким образом, принцип сокрытия информации Парнаса соответствует шаблону
PV и не сводится к простой инкапсуляции данных. Однако этот термин настолько
часто неправильно интерпретировали как синоним инкапсуляции, что его уже невоз¬
можно использовать в изначальном смысле без дополнительных пояснений.Принцип ОСРПринцип ОСР (Open-Closed Principle), описанный Бертраном Мейером (Bertrand
Meyer) по существу эквивалентен шаблону PV и принципу сокрытия информации.
Приведем его определение.Модули должны быть одновременно и открыты (для расширения или адапта¬
ции) и закрыты (для модификации, затрагивающей клиентов).Принципы ОСР и PV являются, по существу, различными выражениями одной и
той же идеи — защиты точек вариации и эволюции. В контексте ОСР “модуль” вклю¬
чает все отдельные программные элементы, в том числе методы, классы, подсисте¬
мы, приложения и т.д.В контексте ОСР выражение “закрыт в смысле X” означает, что изменения X не
затрагивают клиентов. Например, “класс закрыт в смысле определений полей экзем¬
пляров” означает применение механизма инкапсуляции для определения закрытых
полей и открытых методов доступа. В то же время такой класс открыт для модифика¬
ции определений закрытых данных, поскольку внешние клиенты не взаимодейству¬
ют напрямую с этими полями.Рассмотрим еще один пример. Адаптеры систем вычисления налоговых платежей
“закрыты в смысле их открытого интерфейса”, что обеспечивает устойчивость ин¬
терфейса ITaxCalculatorAdapter. Однако эти адаптеры открыты для расширения,
поскольку их можно модифицировать при изменении внешнего интерфейса систем
вычисления налоговых платежей, не затрагивая клиентов.
Применение шаблонов
проектирования GoFСмещение фокуса внимания (в сторону шаблонов) оказывает глубокое и серьезное воз¬
действие на способ написания программ.Вард Каннингхем (Ward Cunningham), Ральф Джонсон (Ralph Johnson)Основные задачи■ Ознакомиться с некоторыми шаблонами проектирования GoF и при¬
менить их.■ Продемонстрировать принципы GRASP как обобщение других шабло¬
нов проектирования.ВведениеВ этой главе рассматривается процесс проектирования в рамках реализации пре¬
цедентов на второй итерации разработки приложения NextGen. На этой итерации
необходимо реализовать взаимодействие с внешними службами, интерфейсы кото¬
рых могут изменяться, обеспечить выполнение более сложных правил вычисления
стоимости товаров и подключение новых бизнес-правил на этапе функционирования
системы. Основное внимание здесь уделяется применению шаблонов GoF и GRASP.
Мы попытаемся проиллюстрировать тот факт, что объектно-ориентированное проек¬
тирование и распределение обязанностей можно построить на применении шабло¬
нов— “перечня” принципов и идиом, помогающих грамотно проектировать объекты.
460 Часть IV. Вторая итерация фазы развития — дополнительные шаблоныЧто дальше? После ознакомления с оставшимися принципами GRASP в данной главе описаны
шаблоны проектирования GoF, чем и завершается текущая итерация. В следующей
главе определяются требования для итерации 3/\Требования
итерации 2Шаблоны GRASP:
дополнительные
объектыПрименениешаблоновпроектированияGoFТребования
итерации 3ДиаграммывидовдеятельностиUMLВ этой главе рассмотрены лишь некоторые из 23 шаблонов проектирования GoF.
Часть шаблонов из этой группы будут рассмотрены в главах 35 и 38.Шаблоны Gang-of-FourШаблоны проектирования GoF впервые упоминались в главе 17. Их краткое опи¬
сание впервые было приведено в популярной книге [58]. В ней описаны 23 шаблона,
предназначенных для использования на этапе объектно-ориентированного проекти¬
рования.Не все из этих шаблонов являются одинаково популярными. На самом деле широ¬
ко используются примерно 15 из существующих 23 шаблонов.Читателям настоятельно рекомендуется внимательно изучить книгу [58] для бо¬
лее полного изучения принципов объектного проектирования. Правда, авторы книги
предполагают, что читатели уже имеют некоторый опыт проектирования и знакомы
с языками программирования C++ и Smalltalk. Наша книга рассчитана на менее под¬
готовленных читателей.26.1. Шаблон Adapter (GoF)Проблема, возникающая при разработке POS-системы NextGen, описанная в пред¬
ыдущей главе при рассмотрении шаблона Polymorphism, более точно соответствует
шаблону Adapter из набора GoF.Имя AdapterПроблема Как обеспечить взаимодействие несовместимых интерфейсов или как
создать единый устойчивый интерфейс для нескольких компонентов с
разными интерфейсами?Решение Конвертировать исходный интерфейс компонента в другой вид с по-(совет) мощью промежуточного объекта-адаптера.Напомним, что POS-система NextGen должна поддерживать несколько разных
внешних служб, включая систему вычисления налоговых платежей, службы авториза¬
ции платежей по кредитной карточке, системы бухгалтерского и складского учета и
т.д. Каждая из этих систем обладает отдельным интерфейсом приложения, который
нельзя изменить.Решение этой проблемы состоит в добавлении специального объекта с общим
интерфейсом в рамках данного приложения и перенаправлении связей от внешних
объектов к этому объекту-адаптеру. Решение проблемы, обеспечиваемое посредством
шаблона Adapter, показано на рис. 26.1.
Глава 26. Применение шаблонов проектирования GoF 461«interface»ITaxCalculatorAdaptergetTaxes(Sale):List of TaxLineltems
 Адаптеры используют ^
интерфейсы и принципы
полиморфизма
для добавления
уровня перенаправления
для различных программных
интерфейсов других
компонентовTaxMasterAdaptergetTaxes(Sale):List of TaxLineltemsGoodAsGoldTaxProAdaptergetTaxes(Sale):List of TaxLineltems«interface»IAccountingAdapterpostReceivable(CreditPayment)
postSale(Sale)"W«interface»ICreditAuthorizationServiceAdapterrequestApproval(CreditPayment,
TerminallD, MerchantID)SAPAc с ount i ngAdap terGreatNorthernAccount ingAdapterpostReceivable(CreditPayment)
postSale(Sale)postReceivable(CreditPayment)
postSale(Sale)«interface»IInventory AdapterPuc. 26.1. Шаблон AdapterКак видно из рис. 26.2, для каждой внешней службы создается отдельный экзем¬
пляр объекта-адаптера,1 в частности SAP для системы бухгалтерского учета. Этот
объект преобразует запрос postSale с учетом требований внешнего интерфейса, а
именно интерфейса XML протокола SOAP поверх HTTPS для Web-службы в рамках
корпоративной сети.Совет: включайте имя шаблона в имя типаОбратите внимание, что имена типов включают название шаблона Adapter. Это
достаточно распространенный стиль, преимущество которого состоит в облег¬
чении понимания диаграмм или кода посторонними читателями, которые сразу
могут определить, на основе какого шаблона построено то или другое проектное
решение.1 В архитектуре J2EE такие адаптеры для внешних служб более точно называются адаптера¬
ми ресурсов (resource adapter).
462 Часть IV. Вторая итерация фазы развития — дополнительные шаблоны:RegisterТmakePayment:SAPAccountingAdapterpostSale(sale)SOAP поверх
HTTP«исполнитель»:SAPSystem..ОШаблон Adapter применяется
к интерфейсам других
компонентовРис. 26.2. Использование шаблона AdapterСвязанные шаблоны. Адаптер, скрывающий внешнюю систему, можно также
рассматривать как фасадный объект, обеспечивающий единообразный доступ к под¬
системе или системе. (Facade — это еще один шаблон GoF, рассматриваемый в этой
главе.) Однако название “адаптер ресурса” является более предпочтительным, если
речь идет об адаптации к различным внешним интерфейсам.26.2. Некоторые принципы GRASP как
обобщение других шаблоновВ предыдущем примере шаблон Adapter можно рассматривать как частный случай
сразу нескольких шаблонов GRASP.В соответствии с шаблоном Protected Variations обеспечивается защита от вли¬
яния изменений интерфейсов внешних пакетов. Это достигается за счет при¬
менения принципа перенаправления, декларируемого шаблоном Indirection на
основе идеи полиморфизма.В чем проблема? Список шаблонов переполненВ книге [106] приводится порядка 500 шаблонов. С момента выхода в свет этой
книги были описаны еще сотни общих принципов проектирования. Если разработ¬
чик захочет познакомиться с полным перечнем шаблонов, у него не останется време¬
ни на создание программы.Решение: изучайте базовые принципыОпытный разработчик должен досконально знать и держать в памяти более пяти¬
десяти важных шаблонов проектирования. Однако вряд ли найдется человек, способ¬
ный изучить и запомнить 1000 шаблонов.
Глава 26. Применение шаблонов проектирования GoF 463К счастью, большинство шаблонов проектирования можно рассматривать как
частный случай или специализацию базовых принципов GRASP. И хотя эти шаблоны
полезно изучить с целью более быстрого овладения принципами проектирования,
необходимо понимать, что все они базируются на применении основных принципов
(обеспечиваемых шаблонами GRASP Protected Variations, Polymorphism, Indirection и
т.д.). Это поможет абстрагироваться от множества избыточных деталей и овладеть
базовыми принципами объектного проектирования.Пример: шаблон Adapter и принципы GRASPИз рис. 26.1 видно, что детализированные шаблоны проектирования можно ана¬
лизировать в терминах базовых шаблонов семейства GRASP. Для описания концеп¬
туальных связей можно использовать отношение обобщения, имеющее соответству¬
ющее обозначение в UML (рис. 26.3). На первый взгляд, эта идея может показаться
слишком академической и оторванной от жизни. Однако если читатель проведет
несколько лет за детальным изучением огромного количества шаблонов проектиро¬
вания, он поймет, что существуют базовые принципы проектирования, которые не¬
обходимо хорошо знать, а частности, описываемые шаблонами Adapter или Strategy,
имеют менее принципиальное значение.Рис. 26.3. Связь шаблона Adapter с базовыми принципами GRASP26.3. Анализ на этапе проектирования:
модель предметной областиОбратите внимание, что на диаграмме, представленной на рис. 26.1 и демон¬
стрирующей применение шаблона Adapter, операция getTaxes возвращает список
объектов TaxLineltems. Это означает, что в процессе глубокого анализа проблемы
464 Часть IV. Вторая итерация фазы развития — дополнительные шаблонывычисления налоговых платежей разработчик (т.е. автор) обнаружил существование
множества различных типов налогов на продажи, в том числе региональных, госу¬
дарственных и т.д. (причем всегда существует вероятность введения новых налогов!).
Многообразие типов налоговых отчислений привело к необходимости определения
целого списка налогов TaxLineltems.Эти объекты не только относятся к вновь созданному программному классу
TaxLineltems в модели проектирования, но и представляют реальное понятие из
предметной области. Выявление новых понятий предметной области и модификация
соответствующих диаграмм на этапе проектирования и программирования — доволь¬
но распространенное и нормальное явление. Итеративный процесс разработки под¬
держивает такую форму поэтапного исследования.Нужно ли отражать эти изменения в модели предметной области (или в словаре)?
Если в будущем модель предметной области будет использована в качестве базовой
для проектирования новых элементов системы, то такая модификация имеет смысл.
На рис. 26.4 показана модифицированная модель предметной области.SaledateTime1Содержит1..*SalesLineltemquantityСодержит1..*TaxLineltemdescriptionpercentageamountPuc. 26.4. Обновленный фрагмент модели предметной области26.4. Шаблон Factory (GoF)Этот шаблон также называют Simple Factory (Простая фабрика) или Concrete
Factory (Конкретная фабрика). Он не относится к шаблонам проектирования GoF, но
является очень распространенным принципом проектирования. Его можно рассма¬
тривать как некое упрощение шаблона GoF Abstract Factory, который будет описан в
главе 35. Однако поскольку данный шаблон тесно связан с шаблонами GoF, он пред¬
ставлен в этой главе.Использование шаблона Adapter порождает новую проблему в проектировании:
какой класс должен отвечать за создание объектов-адаптеров при использовании ша¬
блона Adapter? Кто при этом определяет тип создаваемого объекта-адаптера, к при¬
меру TaxMasterAdapter или GoodAsGoldTaxProAdapter?
Глава 26. Применение шаблонов проектирования GoF 465Если эти объекты создаются неким объектом уровня предметной области, то обя¬
занности объектов уровня предметной области выходят за рамки обеспечения логи¬
ки приложения (например, вычисления общей стоимости покупки) в плоскость взаи¬
мосвязи с внешними программными компонентами.Это приводит к нарушению еще одного фундаментального принципа проектиро¬
вания — разделения различных аспектов функционирования системы (разделения
обязанностей). Суть этого принципа сводится к разделению системы на модули, в
соответствии с разными аспектами функционирования и задачами системы. По суще¬
ству, в этом состоит принцип GRASP High Cohesion. Например, программные объек¬
ты уровня предметной области должны отвечать только за реализацию логики при¬
ложения, а взаимодействие с внешними службами должны обеспечивать отдельные
группы объектов.Следовательно, выбор объекта уровня предметной области (например, Register)
на роль создателя объектов-адаптеров не соответствует принципу разделения обязан¬
ностей и низкого связывания.Выход из сложившейся ситуации обеспечивает шаблон Factory (или Concrete
Factory), в соответствии с которым для построения объектов создается “чисто синте¬
тический” класс-фабрика.Такой подход имеет несколько преимуществ.■ Позволяет выделить обязанность создания сложных объектов и делегировать
ее отдельному вспомогательному классу.■ Скрывает сложную логику создания объектов.■ Позволяет реализовать стратегии оптимального управления памятью и повы¬
шения производительности, в частности кеширование объектов.Имя FactoryПроблема Кто должен отвечать за создание сложных объектов в особых условиях,
предполагающих сложную логику создания, необходимость выделения
обязанностей создания объектов и т.д.?Решение Создать искусственный объект, соответствующий шаблону Pure(совет) Fabrication, и возложить на него обязанность по созданию других объек¬тов в соответствии с шаблоном Factory.Проектное решение, обеспечиваемое шаблоном Factory, показано на рис. 26.5.Из рис. 26.5 видно, что объект ServicesFactory определяет тип создаваемого
объекта путем получения имени класса из внешнего источника (например, через си¬
стемное свойство при использовании Java), а затем динамически загружает класс. Это
пример проектирования на основе данных (data-driven design). Такой подход соответ¬
ствует шаблону Protected Variations в смысле независимости от изменения реализа¬
ции класса-адаптера. Новые экземпляры новых типов адаптеров можно создавать без
модификации исходного кода класса-фабрики путем изменения значения свойства и
обеспечения видимости нового класса.Связанные шаблоны. Доступ к объектам-фабрикам зачастую осуществляется на
основе шаблона Singleton.
466 Часть IV. Вторая итерация фазы развития — дополнительные шаблоныServicesFactoryaccountingAdapter : IAccountingAdapter
inventoryAdapter : IInventoryAdapter
taxCalculatorAdapter : ITaxCalculatorAdaptergetAccountingAdapter () : IAccountingAdapter O''
getInventoryAdapter() : IInventoryAdapter
getTaxCalculatorAdapter() : ITaxCalculatorAdapter•v o-..., Обратите внимание, что ■
методы класса-фабрики
возвращают объекты с типом
интерфейса, а не класса.Так что класс-фабрика
может возвращать любую
реализацию интерфейсаif (taxCalculatorAdapter == null){// подход к поиску нужного класса, управляемый данными:// нужный класс считывается из внешнего свойстваString className = System.getProperty("taxcalculator.class.name");taxCalculatorAdapter = (ITaxCalculatorAdapter)Class.forName(className).newlnstance();}return taxCalculatorAdapter;}Puc. 26.5. Шаблон Factory26.5. Шаблон Singleton (GoF)Использование объекта-фабрики ServicesFactory порождает новую проблему
проектирования — кто должен создавать саму фабрику и как получить к ней доступ?Отметим, во-первых, что в рамках приложения необходим лишь один экземпляр
объекта-фабрики. Во-вторых, методы объекта могут понадобиться разным объектам и
вызываться из различных частей кода, подобно тому, как для обращения к внешним
службам из разных частей программы может понадобиться доступ к объектам-адапте¬
рам. Таким образом возникает проблема получения доступа к единственному экзем¬
пляру ServicesFactory (проблема видимости).Одно из решений этой проблемы состоит в том, чтобы передать объект
ServicesFactory в качестве параметра для обеспечения видимости или инициализи¬
ровать объекты, требующие такой видимости, с постоянной ссылкой на этот объект.
Такой путь возможен, но достаточно неудобен. Альтернативный способ решения этой
проблемы предоставляет шаблон Singleton.Кстати, для одного экземпляра класса желательно поддерживать глобальную види¬
мость или единственную точку доступа и не использовать другие формы обеспечения
видимости. Это касается и экземпляра объекта ServicesFactory.Имя SingletonПроблема Как корректно использовать только один экземпляр класса, к которому
через одну точку доступа должны обращаться различные объекты?Решение Определить статический метод класса, возвращающий этот единствен-(совет) ный объект (объект-синглетон).
Глава 26. Применение шаблонов проектирования GoF 467На рис. 26.6 показан пример реализации шаблона Singleton.цОбозначение UML: символ “ 1 ” можно использовать для
указания того, что будет создан лишь один экземплярОбозначение
UML: при
изображении
классаподчеркнутый
атрибут или
метод являются
статическими
членами (уровня
класса), а не
членами
экземпляровServicesFactoryinstance : ServicesFactoryaccountingAdapter : IAccountingAdapter
inventoryAdapter : IInventoryAdapter
taxCalculatorAdapter : ITaxCalculatorAdaptergetlnstance() : ServicesFactory n~p ,4etAccountingAdapter() : IAccountingAdapter
getInventoryAdapter() : IInventoryAdapter
getTaxCalculatorAdapter() : ITaxCalculatorAdapterЕдинственныйстатическийатрибутЕдинственныйстатическийметод// статический метод ■public static synchronized ServicesFactory getlnstance()
{if (instance == null)
instance := new ServicesFactory();
return instance;}Puc. 26.6. Использование шаблона Singleton при реализации класса ServicesFactoryПрименение UML. Обратите внимание, что объект-синглетон на диаграмме помеча¬
ется символом 1 в правом верхнем углу (рис. 26.7).Символ"!" позволяет указать, что
видимость данного экземпляра обеспечивается
за счет применения шаблона Singleton"О: Register: ServicesFactory -jinitializeаа = getAccountingAdapterРис. 26.7. Неявная передача сообщения getlnstance, согласно шаблону Singleton, обозначает¬
ся в UML с помощью стереотипов
468 Часть IV. Вторая итерация фазы развития — дополнительные шаблоныОсновная идея состоит в определении статического метода getlnstance класса
X, обеспечивающего создание единственного экземпляра этого класса.При таком подходе разработчик обеспечивает глобальную видимость для един¬
ственного экземпляра с помощью статического метода этого класса getlnstance.public class Register
{public void initialize (){... выполняем необходимые действия ...// доступ к единственному экземпляру объекта-фабрики// осуществляется через вызов метода getlnstanceServicesFactory.getlnstance().getAccountingAdapter();. . . выполняем необходимые действия . . .}// другие методы...} / / конец описания классаПоскольку открытые классы чаще всего относятся к глобальной области видимо¬
сти, то при вызове любого метода любого класса из каждой точки программы можно
обратиться к методу SingletonClass.getlnstance () и получить доступ к единствен¬
ному экземпляру объекта-фабрики. Тогда этому экземпляру можно передать сообще¬
ние SingletonClass. get Instance () .doFoo () и выполнить любые действия. Сложно
переоценить возможность выполнить любые действия из любой точки программы.Вопросы реализации и проектированияМетод getlnstance, используемый при реализации шаблона Singleton, вызыва¬
ется довольно часто. В многопоточных приложениях для создания экземпляров ис¬
пользуется пассивная инициализация (lazy initialization) на основе управления парал¬
лелизмом потоков. Например, при использовании пассивной инициализации в Java
управление параллелизмом осуществляется следующим образом.public static synchronized ServicesFactory getlnstance (){if ( instance == null )// важный раздел для многопоточных приложений
instance = new ServicesFactory();}return instance;}Возникает вопрос, почему не используется активная инициализация (eager initial¬
ization), как в следующем примере?public class ServicesFactory
{11 активная инициализация
Глава 26. Применение шаблонов проектирования GoF 469private static ServicesFactory instance =
new ServicesFactory();public static ServicesFactory getlnstance (){return instance;}// другие методы...}Первый подход на основе пассивной инициализации обычно предпочтительнее
хотя бы по следующим причинам.■ Процесс создания экземпляра (или обращения к “дорогим ресурсам”) не иници¬
ируется, пока реально не потребуется доступ к экземпляру.■ Пассивная инициализация иногда выполняется на основе сложной логики.При реализации шаблона Singleton напрашивается еще один вопрос: почему все
служебные методы не объявить статическими методами самого класса? Зачем исполь¬
зовать экземпляр объекта и методы экземпляра? Например, можно создать статиче¬
ский метод getAccountingAdapter для класса ServicesFactory. Однако создание
экземпляра с его методами обычно предпочтительнее по следующим причинам.■ При использовании методов экземпляра можно использовать механизм насле¬
дования и создавать подклассы. Статические методы в большинстве языков
программирования (за исключением SmallTalk) не полиморфны (не могут быть
виртуальными) и не допускают перекрытия в производных классах.■ Большинство механизмов удаленного взаимодействия на основе объектно-ори¬
ентированного подхода (например, RMI в Java) удаленно поддерживает только
методы экземпляров, а не статические методы. Поэтому к единственному эк¬
земпляру, созданному согласно шаблону Singleton, можно получить удаленный
доступ, хотя это и требуется крайне редко.■ Класс может обеспечивать выполнение шаблона Singleton не во всех приложе¬
ниях. К примеру, в приложении X его объект может выступать в роли един¬
ственного экземпляра, а в приложении Y — нет. Кроме того, нередко возникают
ситуации, когда на начальных стадиях проектирования предполагается исполь¬
зование лишь единственного экземпляра объекта, а впоследствии требуется
несколько его экземпляров. Поэтому решение на основе создания экземпляра
является более гибким.Связанные шаблоны. Шаблон Singleton зачастую используется одновременно с
шаблонами GoF Factory и Facade, которые будут описаны ниже.26.6. Еще несколько слов о внешних
службах с разными интерфейсамиШаблоны Adapter, Factory и Singleton применялись для реализации основного
принципа взаимодействия с внешними системами с различными интерфейсами в со-
470 Часть IV. Вторая итерация фазы развития — дополнительные шаблоныответствии с шаблоном Protected Variations. На рис. 26.8 показана укрупненная схема
применения этих шаблонов при реализации прецедентов.Возможно, это проектное решение не идеально — нет предела совершенству.
Задача этого примера — проиллюстрировать проектное решение, основанное на при¬
менении набора принципов и шаблонов. Главное понять методологию проектирова¬
ния на основе шаблонов. Автор надеется, что проектное решение, представленное на
рис. 26.8, с очевидностью демонстрирует применение шаблонов Controller, Creator,
Protected Variations, Low Coupling, High Cohesion, Indirection, Polymorphism, Adapter,
Factory и Singleton.Обратите внимание, насколько кратко разработчик может сформулировать и опи¬
сать свои идеи с помощью шаблонов. Можно сказать, что проблему различных интер¬
фейсов с внешними службами будем решать на основе шаблона Adapter, а адаптеры
ресурсов будем строить по принципу шаблонов Singleton и Factory. Разработчики про¬
граммного обеспечения действительно общаются между собой подобным образом.
Имена и идеи шаблонов повышают уровень абстракции при обсуждении проектного
решения.:Store:ServicesFactory:RegisteraccountingAdapter
getAc с ount ingAdapt er:SAPAccounting
Adapter:Register—гmakePayment iaccountingAdapter:
SAPAccountingAdaptercreate(cashTendered):PaymentpostSale(sale)SOAP поверх
HTTP«исполнитель»SAPSystemPuc. 26.8. Проектирование на основе шаблонов Adapter; Factory и Singleton
Глава 26. Применение шаблонов проектирования GoF 47126.7. Шаблон Strategy (GoF)Следующая проблема — обеспечение более сложной логики вычисления стоимо¬
сти товаров с учетом сезонных скидок, скидок постоянным клиентам и т.д.Стратегия вычисления стоимости (которую можно назвать правилом, политикой,
или алгоритмом) может изменяться. В один период она может составлять 10% от
стоимости каждой покупки, затем — $10 для каждой покупки, превышающей $200 и
т.п. Как спроектировать эти изменяемые алгоритмы?Имя StrategyПроблема Как спроектировать изменяемые, но надежные алгоритмы или стратегии?Как спроектировать возможность изменения этих алгоритмов или политик?Решение Определить для каждого алгоритма (политики, стратегии) отдельный(совет) класс со стандартным интерфейсом.Поскольку ценовая политика может изменяться по некоторому алгоритму, мож¬
но создать несколько классов SalePricingStrategy, каждый из которых содержит
полиморфный метод getTotal (рис. 26.9). Каждому методу getTotal в качестве па¬
раметра нужно передавать объект Sale, чтобы объект ценовой политики мог най¬
ти и применить соответствующее правило вычисления скидок. Реализация метода
getTotal может быть различной: для объекта PercentDiscountPricingStrategy
скидки можно вычислять в процентном соотношении и т.п.«interface»ISalePricingStrategygetTotal(Sale):MoneyPercentDiscountPricingStrategypercentage:floatgetTotal(s:Sale):MoneyAbsoluteDiscount
OverThreshold
PricingStrategydiscount:Money
threshold:MoneygetTotal(s:Sale):Money
о ???PricingStrategyreturn s.getPreDiscountTotal(
}percentage{pdt:=s.getPreDiscountTotal()
if (pdt < threshold)
return pdt
elsereturn pdt - discount}Puc. 26.9. Классы для описания стратегий вычисления стоимости
472 Часть IV. Вторая итерация фазы развития — дополнительные шаблоныОбъект стратегии связывается с контекстным объектом (context object) — объектом,
к которому применяется алгоритм. В рассматриваемом примере контекстным объек¬
том является Sale. При отправке объекту Sale сообщения getTotal он делегирует
часть своих задач объекту стратегии, как показано на рис. 26.10. Имена сообщений,
передаваемых контекстному объекту и объекту стратегии, могут не совпадать, но
в данном примере (и это довольно типично) выбрано одно и то же имя getTotal.
Обычно контекстный объект передает объекту стратегии ссылку на самого себя
(this) (это даже необходимо) для обеспечения параметрической видимости.s:Salelineitems[i]::PercentDiscountSalesLineltemPricingStrategyloopt=getTotalst=getSubtotalо t=getTotal(s)pdt=getPreDi$countTotalIT{t=pdt *percentage}Обратите внимание, что экземпляр s объекта sale передается в
соответствии с шаблоном Strategy так, чтобы была обеспечена видимость
посредством параметров для дальнейшего взаимодействияРис. 26.10. Применение шаблона StrategyОбратите внимание, что контекстный объект Sale должен обеспечивать для сво-
стратегии видимость посредством атрибутов. Это отражено на диаграмме классов,
^ставленной на рис. 26.11.Создание объекта стратегии на основе шаблона FactoryСуществуют различные алгоритмы ценообразования, и они могут изменяться со
именем. Кто должен разрабатывать стратегию? Наиболее логично использовать
[ решения этой проблемы шаблон Factory. Тогда объект PricingStrategyFactory
будет отвечать за разработку всех стратегий (всех подключаемых или изменяемых ал¬
горитмов или политик) в данном приложении. Как и объект ServicesFactory, он бу¬
дет считывать имя класса реализации для стратегии ценообразования из системного
свойства (или некоторого внешнего источника данных), а затем создавать экземпляр
стратегии. При таком рефлексивном проектном решении политику ценообразования
можно изменять в любое время в процессе работы приложения NextGen. При этом
нужно лишь задавать новое имя класса создаваемой стратегии.Заметим, что для создания объектов стратегий используется новый объект-фабри¬
ка, отличный от ServicesFactory. Такой подход обеспечивает высокую степень заце¬
пления: каждая “фабрика” отвечает за создание семейства взаимосвязанных объектов.
Глава 26. Применение шаблонов проектирования GoF 473Объекту Sale требуется видимость объекта
Strategy посредством атрибутовSale6 1
 ^date«interface»ISalePricingStrategypricingStrategygetTotal(Sale):MoneygetTotal()
... QgetTotal() ^
{returnpricingStrategy.getTotal(this)}PercentDiscountPricingStrategypercentage:float
getTotal(Sale):MoneyiAbsoluteDiscountOverThresholdPricingStrategydiscount:Money
threshold:MoneygetTotal(Sale):MoneyРис. 26.11. Контекстные объекты должны обеспечивать видимость своих стратегийпосредством атрибутовОбозначения UML. Обратите внимание, что на рис. 26.11 ссылка (направленная
ассоциация) указывает на интерфейс ISalePricingStrategy, а не на конкретный
класс. Это означает, что ссылочный атрибут объекта Sale будет объявлен в терминах
интерфейса, а не класса, и этому атрибуту будет соответствовать любая реализация
этого интерфейса.Поскольку политика ценообразования изменяется довольно часто (возможно,
даже ежечасно), то созданный экземпляр стратегии нежелательно кешировать в поле
объекта PricingStrategyFactory. Лучше заново создавать этот объект при каждом
использовании, считывая имя класса из внешнего свойства и инстанцируя объект
стратегии.Как и большинство объектов-фабрик, PricingStrategyFactory должен удовлет¬
ворять шаблону Singleton (иметь единственный экземпляр) (рис. 26.12).При создании экземпляра объекта Sale он может обратиться к объекту-фабрике
для определения стратегии ценообразования, как показано на рис. 26.13.Чтение и инициализация процентного соотношенияДо сих пор не рассматривалась еще одна проблема проектирования, связанная с
определением числовых значений скидок, вычисляемых в процентах или абсолют¬
ных значениях. Например, в понедельник значение скидки в процентах, задаваемое
объектом PersentageDiscountPricingStrategy, должно составлять 10%, а во втор¬
ник-20%.
474Часть IV. Вторая итерация фазы развития — дополнительные шаблоныPricingStrategyFactory 1instance : PricingStrategyFactorygetlnstance() : PricingStrategyFactorygetSalePricingStrategy():ISalePricingStrategyQ
getSeniorPricingStrategy():ISeniorPricingStrategy_ .String className = System.getProperty( "salepricingstrategy.class.name" );
strategy = (ISalePricingStrategy) Class.forName( className ).newlnstance();
return strategy;}Puc. 26.12. “Фабрика” стратегийРис. 26.13. Создание объекта стратегииПроцентное соотношение скидки может зависеть от типа покупателя (например,
для почетных граждан), а не только от времени.Такие значения должны храниться на внешнем носителе, например в реляцион¬
ной базе данных, чтобы их было легко изменить. Какие же объекты должны считы¬
вать эти значения и назначать стратегии? Логично поручить эту обязанность самому
объекту StrategyFactory, поскольку именно он создает экземпляры стратегий це¬
нообразования и может “знать”, какое значение нужно считать (“текущей скидки”,
“скидки для почетных граждан” и т.д.)Способы считывания этих значений из внешнего хранилища могут варьироваться
от самых простых до очень сложных, таких как обычный запрос SQL через JDBC
(при использовании Java-технологий) или взаимодействие с объектами путем пере¬
направления для сокрытия конкретного местоположения, языка запросов и^и типа
хранилища данных. Анализируя точки вариации и эволюции в контексте хранения
данных, следует оценить необходимость применения шаблона Protected Variations.
Глава 26. Применение шаблонов проектирования GoF 475Например, можно задать вопрос о том, насколько долговременным будет хранение
информации в реляционной базе данных, взаимодействие с которой осуществляется
с помощью SQL? Если тип хранилища данных не будет изменяться, то можно ограни¬
читься использованием драйвера JDBG из объекта StrategyFactory.Заключительные замечанияПринципы шаблона Protected Variations при реализации динамически изменяе¬
мой стратегии ценообразования обеспечиваются применением шаблонов Strategy и
Factory. Объекты стратегии строятся на основе принципа полиморфизма и обеспе¬
чивают механизмы подключения через общий интерфейс в рамках объектного про¬
ектного решения.Связанные шаблоны. Шаблон Strategy основан на шаблоне Polymorphism и обе¬
спечивает реализацию шаблона Protected Variations для изменяемых алгоритмов.
Объекты стратегий зачастую создаются с помощью шаблона Factory.26.8. Шаблон Composite (GoF) и другие
принципы проектированияРассмотрим еще одну интересную проблему проектирования и формулировки
требований. Как обрабатывать многочисленные противоречивые политики ценоо¬
бразования? Допустим, к примеру, что на сегодняшний день в магазине действуют
следующие правила.■ 20%-ная скидка для почетных граждан■ Скидка в размере 15% для постоянных клиентов при покупке товаров на сумму
свыше $400■ По понедельникам действует скидка в размере $50 при покупке товаров на сум¬
му свыше $500■ При покупке 1 ящика чая Darjeeling клиент получает скидку на все остальные
товары в размере 15%Предположим, почетный гражданин, который является также постоянным по¬
купателем, приобретает 1 ящик чая Darjeeling и на $600 овощных котлет (поистине
фанатичный вегетарианец и любитель чая!). Какую политику ценообразования при¬
менить в данном случае?Уточним ситуацию. Действующие на данный момент стратегии ценообразования
определяются тремя факторами:■ временем (понедельник);■ типом покупателя (почетный гражданин);■ типом выбранного продукта (чай Darjeeling).Еще одно уточнение: три из четырех примеров политик, по существу, являются
процентными скидками.Для решения этой проблемы нужно определить стратегию разрешения конфликтов
(conflict resolution strategy) для данного магазина. Обычно магазины выбирают луч¬
шую для покупателя (обеспечивающую самую низкую стоимость) стратегию, однако
476 Часть IV. Вторая итерация фазы развития — дополнительные шаблоныэто не обязательное требование. Например, в трудный период магазин может вы¬
брать стратегию “наивысшей стоимости”.Первый важный момент: одновременно существует множество стратегий, причем
некоторые из них могут применяться к одной продаже. Второй: политика ценообра¬
зования может быть связана с типом покупателя (например, постоянный). Отсюда
вывод — тип покупателя должен быть известен объекту StrategyFactory на момент
создания стратегии ценообразования для данного продукта.Существует ли способ изменения проектного решения таким образом, чтобы объект
Sale не обладал информацией о количестве применяемых к нему стратегий, но оста¬
валась возможность разрешения конфликтов? Да, это решение обеспечивается шаб¬
лоном Composite.Имя CompositeПроблема Как обрабатывать группу или композицию структур объектов одновре¬
менно (полиморфно) как некомпозитный (атомарный) объект?Решение Определить классы для композитных и атомарных объектов таким об-
(совет) разом, чтобы они реализовали один и тот же интерфейс.Например, можно создать новый класс CompositeBestForCustomerPricing
Strategy (во всяком случае это имя содержательно), реализующий интерфейс
ISalePricingStrategy и содержащий другие объекты ISalePricingStrategy. Идея
этого решения представлена на рис. 26.14.Обратите внимание, что в этом проектном решении композитный класс Comp о
siteBestForCustomerPricingStrategy наследует атрибут pricingStrategies, со¬
держащий список других объектов ISalePricingStrategy. Это отличительная осо¬
бенность композитных объектов — внешний композитный объект содержит список
внутренних объектов, реализующих тот же интерфейс, что и внешний объект. Таким
образом, композитный класс сам реализует интерфейс ISalePricingStrategy.Теперь с объектом Sale можно связать либо композитный объект Composite
BestForCustomerPricingStrategy (включающий в себя другие стратегии), либо
атомарный объект PercentDiscountPricingStrategy. Причем объект Sale даже
не будет знать о том, какой тип стратегии (композитная или атомарная) с ним
связан, поскольку для объекта Sale это просто объект, реализующий интерфейс
ISalePricingStrategy и “понимающий” сообщение getTotal (рис. 26.15).Для большей ясности рассмотрим реализацию класса CompositePricingStrategy
у одного из его подклассов на языке Java.//суперкласс, от которого все производные классы могут наследовать
список стратегийpublic abstract class CompositePricingStrategy
implements ISalePricingStrategy{protected List strategies = new ArrayList ();
public add(ISalePricingStrategy s){strategies.add(s);}
Глава 26. Применение шаблонов проектирования GoF 477return pricingStrategy.getTotal(this)
}SaledategetTotal () $Все сложные объекты шподдерживают список
имеющихся стратегий. Таким
образом, определите общий
суперклассCompositePricingStratеду,
в котором будет определен этот
список(strategies)pricingStrategy«interface»ISalePricingStrategygetTotal(Sale):Money
 1..*strategiesPercentageDiscountPricingStrategypercentage:floatgetTotal(Sale):MoneyAbsoluteDiscountOverThresholdPricingStrategydiscount:Money
threshold:MoneygetTotal(Sale):MoneyCompositePricingStrategyadd(ISalePricingStrategy
getTotal(Sale):Money
 return sale.getPreDiscountTotal()*
percentage
}CompositeBestForCustomerPricingStrategyCompositeBestForStorePricingStrategygetTotal(Sale):MoneygetTotal(Sale):Moneya...lowestTotal = INTEGER.MAX
for each ISalePricingStrategy strat in
pricingStrategies
{total := strat.getTotal(sale)
lowestTotal = min(total, lowestTotal)
}return lowestTotal
}Puc. 26.14. Применение шаблона Composite
478 Часть IV. Вторая итерация фазы развития — дополнительные шаблоныpublic abstract Money getTotal(Sale sale);}// конец описания класса// композитная стратегия, возвращающая самую низкую стоимость
// среди всех стоимостей, определяемых внутренними стратегиями
public class CompositeBestForCustomerPricingStrategy
extends CompositePricingStrategy
{public Money getTotal(Sale sale){Money lowestTotal = new Money (Integer.MAX_VALUE);// цикл для всех внутренних стратегийfor (Iterator i = strategies.iterator (); i.hasNext ();){ISalePricingStrategy strategy =(ISalePricingStrategy)i.next();Money total = strategy.getTotal(sale);
lowestTotal = total.min(lowestTotal);}return lowestTotal;} // конец описания классаОбозначения UML ISalePricingStrategy - это интерфейс, Ьь
а не класс. В UML 2 таким образом можно представить объект
неизвестного класса, однако который реализует данный интерфейсs:Salelineltems[i]::CompositeBestForCustomer 0 strategies[j]:SalesLineltemPricingStrategyISalePricingStrategyloopt=getTotalst=getSubtotal't=getTotal(s){t=min(set lof
lall x)}loopx=getTotal(s)По шаблону Composite объект Sale рассматривается как
составной, реализующий различные стратегииРис. 26.15. Взаимодействие на основе шаблона Composite
Глава 26. Применение шаблонов проектирования GoF 479На рис. 26.14 введены некоторые новые обозначения UML для иерархии классов
и наследования. Эти обозначения поясняются на рис. 26.16.Обозначение UML: имя абстрактного
класса выделяется курсивом.Абстрактные методы тоже выделяются
курсивомCompositePricingStrategyadd(ISalePricingStrategy)
‘О getTotal (Sale) :MoneyCompositeBestForCustome]PricingStrategyCompositeBestForStorePricingStrategygetTotal(Sale):MoneygetTotal(Sale):MoneyPuc. 26.16. Абстрактные суперклассы, абстрактные методы и наследование в UMLСоздание нескольких стратегий SalePricingStrategyНа основе шаблона Composite была создана группа из нескольких (противоречи¬
вых) стратегий ценообразования, которые с точки зрения объекта Sale выглядели
как одна стратегия. Композитный объект, содержащий эту группу, тоже реализует
интерфейс ISalePricingStrategy. Теперь возникает новая (еще более интересная)
проблема: когда создавать эти стратегии?Сначала нужно создать композитный объект, содержащий действующие на данный
момент политики скидок (если никакие скидки не действуют, то процентная скидка
будет равна 0%), некий PersentageDiscountPricingStrategy. Затем, если в неко¬
торый момент понадобится применить новую стратегию ценообразования (скажем,
для постоянных клиентов), то ее можно легко добавить к композитному объекту с по¬
мощью унаследованного метода CompositePricingStrategy.addO.Вот три возможных стратегии с учетом времени их добавления.1. Текущая скидка для данного магазина, добавляемая при создании экземпляра
Sale.2. Скидка для определенных типов покупателей, добавляемая при вводе типа по¬
купателя в POS-систему.3. Скидка для определенного типа товара (при покупке чая Darjeeling — 15% от
общей стоимости покупки), добавляемая при выборе этого типа товара.Проектное решение для первого случая показано на рис. 26.17. Как и в описанном
выше исходном проектном решении, имя класса стратегии считывается как систем¬
ное свойство, а процентное соотношение скидки поступает от внешнего источника
данных.
480 Часть IV. Вторая итерация фазы развития — дополнительные шаблоны.♦Registermake I
NewSale 1 M-1:PricingStrategyFactorycreate:Saleps=getSalel PricingStrategycreateps:CompositeBestForCustomer
PricingStrategycreate(percent)add(s)s:PercentageDiscount
PricingStrategyPuc. 26.17. Создание композитной стратегииПри рассмотрении второго вида скидок, определяемого типом покупателя, об¬
ратимся к расширению описания прецедента, в котором впервые упоминается это
требование.Прецедент ПР1: Оформление продажиРасширения (альтернативные сценарии)56. Покупатель сообщает о положенной ему скидке (например, для сотрудников данного пред¬
приятия или постоянных покупателей).1. Кассир отправляет запрос на скидку.2. Кассир вводит идентификационные данные покупателя.3. Система предоставляет сумму скидки, вычисленную на основе дисконтных правил.Из этого описания видна необходимость новой системной операции для POS-
приложения. Помимо существующих операций makeNewSale, enterltem, endSale и
makePayment, требуется пятая системная операция enterCustomerForDiscount. Она
может дополнительно выполняться после операции endSale. Для ее выполнения не¬
обходимо иметь идентификаторы покупателей customerlD. Их можно считывать с
карточки или вводить с клавиатуры.Проектное решение для второго случая показано на рис. 26.18 и 26.19. Не удиви¬
тельно, что объект-фабрика отвечает за создание дополнительных стратегий ценообра¬
зования. Он может создать новую стратегию PercentageDiscountPricingStrategy,
предоставляющую, например, скидки постоянным клиентам. Как и в исходном про¬
ектном решении, имя класса считывается в качестве системного свойства, обеспе¬
чивая выполнение шаблона Protected Variations. Благодаря применению шаблона
Глава 26. Применение шаблонов проектирования GoF 481Composite, с объектом Sale можно связать несколько противоречивых стратегий це¬
нообразования, но для самого объекта они будут выглядеть как единая стратегия.По шаблону ControllerПо шаблону Expert
и IDs to ObjectПо шаблону Expert:RegisterenterCustomerForDiscount(custlD):StoreО Ic=getCustomer(custlD)|*□s:SaleenterCustomerForDiscoifnt (c:Customer)refEnter Customer
For Discounti i i
Puc. 26.18. Создание стратегии ценообразования для конкретного типа покупателя (часть I)Обозначения UML. Рис. 26.18 и 26.19 иллюстрируют важную идею UML, относящу¬
юся к диаграммам взаимодействия, — использование фреймов ref и sd для взаимос¬
вязи диаграмм.Шаблоны GRASP и другие принципы проектированияРассуждая в терминах шаблонов GRASP, можно задать вопрос: почему во втором
случае объект Register не отправляет сообщение объекту PricingStrategyFactory
о создании новой стратегии, а затем не передает ее объекту Sale? Одна из причин
состоит в соответствии шаблону Low Coupling. Объект Sale уже связан с фабрикой.
Если с объектом-фабрикой будет взаимодействовать и объект Register, то повы¬
сится уровень связывания объектов приложения. Более того, объект Sale является
информационным экспертом, обладающим информацией о текущей стратегии цено¬
образования (которая может изменяться). Поэтому согласно шаблону Expert, эту обя¬
занность нужно делегировать объекту Sale.Обратите внимание, что в этом проектном решении идентификатор customerlD
трансформируется в объект Customer, когда объект Register отправляет запрос
объекту Store на получение объекта Customer по его идентификатору. Обязанность
по предоставлению типа покупателя getCustomer возлагается на объект Store, со¬
гласно шаблону Expert. Запрос отправляется объектом Register, поскольку для этого
объекта обеспечивается видимость объекта Store посредством атрибутов. Если бы за¬
прос направлял объект Sale, то он должен был бы иметь ссылку на объект Store, что,
в свою очередь, повысило бы уровень связывания в разрез с шаблоном Low Coupling.Преобразование идентификаторов в объектыЗачем преобразовывать идентификатор customerlD (возможно, числовой) в
объект Customer? Это типичная ситуация для объектного проектирования. В рам-16 3ак.3357
482 Часть IV. Вторая итерация фазы развития — дополнительные шаблоныках этого подхода ключи и идентификаторы зачастую преобразуются в реальные
объекты. Такое преобразование обычно выполняется вскоре после передачи иденти¬
фикатора с уровня интерфейса пользователя на уровень логики приложения. Такой
прием не оформлен в виде именованного шаблона, но является хорошим кандидатом
в шаблоны, поскольку встречается довольно часто. Его можно назвать шаблоном ID
to Objects. Даже если на ранних стадиях проектирования разработчики планируют
обойтись числовым идентификатором, впоследствии может возникнуть необходи¬
мость во введении реального объекта Customer, обладающего собственным поведе¬
нием (например, согласно шаблону Expert) и инкапсулирующего всю информацию о
покупателе. Такое решение повышает гибкость разработки. Заметим, что еще одним
примером применения шаблона IDs to Objects является преобразование идентифика¬
тора itemID в объект ProductDescription.sd Enter Customer For DiscountПо шаблону ExpertЪПо шаблонам
Factory и High CohesionenterCustomers:Sale~T:PricingStrategy
Factoryps:CompositeBestForCustomer
PricingStrategyForDiscount(c:Customer) I addCustomer q. 1
PricingStrategy (s )''!••.По шаблону Expertifc=getCustomer()T« ps=getPricing
Strategy()■0Передача I
агрегатного
объекта
в качестве
параметраpct= о*'
getCustomer
Percentage(с)create(pet)
add(s)По шаблону High Cohesionbnjs:PercentageDiscount
PricingStrategyПо шаблонам
Factory и CompositePuc. 26.19: Создание стратегии ценообразования для конкретного типа покупателя (часть П)
Глава 26. Применение шаблонов проектирования GoF 483Передача агрегатного объекта в качестве параметраПри передаче сообщения addCustomerPricingStrategy (s: Sale) объекту-фабри¬
ке в качестве параметра выступает объект Sale, а затем объект-фабрика запрашивает
объекты Customer и PricingStrategy у объекта Sale.Почему не извлечь эти объекты из объекта Sale и не передать их объекту-фабри¬
ке? Ответ на этот вопрос заключается в еще одной идиоме объектного проектирова¬
ния. Дочерние объекты обычно не извлекаются из агрегатных объектов и не пере¬
даются отдельно. Как правило, передается сам агрегатный объект.Этот принцип повышает гибкость проектного решения, поскольку объект-фабри¬
ка может взаимодействовать с объектом Sale, в результате чего повышается произ¬
водительность и устраняется необходимость передачи конкретных объектов, необхо¬
димых объекту-фабрике. Эта идиома тоже не имеет имени, но связана с шаблонами
Low Coupling и Protected Variations. Ее можно было бы назвать Pass Aggregate Object
as Parameter.Заключительные замечанияРассмотренная проблема решена с помощью нескольких шаблонов. Опытный раз¬
работчик хранит в памяти множество шаблонов и принципов проектирования, в том
числе шаблоны семейства GRASP.Несмотря на то, что шаблон Composite введен для объектов, соответствующих
шаблону Strategy, его можно применять не только для стратегий, но и для любых дру¬
гих объектов. Например, зачастую создают макрокоманды — команды, включающие
другие команды. Это тоже делается на основе шаблона Composite. Шаблон Command
будет рассмотрен в последующих главах.Связанные шаблоны. Шаблон Composite зачастую применяется вместе с шабло¬
нами Strategy и Command. Он основан на принципах шаблона Polymorphism и обе¬
спечивает реализацию Protected Variations для клиента, поскольку клиенту не нужно
знать, с чем он связан — с композитным или атомарным объектом.26.9. Шаблон Facade (GoF)Еще одним требованием для этой итерации является реализация подключаемых
бизнес-правил. Это значит, что в некоторых фиксированных точках сценария, напри¬
мер, при выполнении операций makeNewSale или enteritem в рамках прецедента
Оформление продажи, различные пользователи могут слегка модифицировать пове¬
дение системы NextGen.Уточним сказанное. Предположим, требуется определить правила, отменяющие
некоторые действия. Рассмотрим следующие примеры.■ Допустим, при создании нового экземпляра продажи можно учесть наличие по¬
дарочного сертификата. В магазине можно ввести правило, ограничивающее ко¬
личество покупаемых товаров при наличии подарочного сертификата одной еди¬
ницей. И тогда все операции enteritem, кроме первой, должны быть отменены.■ Если покупка оплачивается с помощью подарочного сертификата, необходимо
отменить все типы сдачи, кроме других подарочных сертификатов. Например,
если кассир вводит запрос на вычисление сдачи наличными, то этот запрос не¬
обходимо отменить.
484 Часть IV. Вторая итерация фазы развития — дополнительные шаблоны■ При создании новой продажи можно оформить ее как благотворительную ак¬
цию магазина. Для подобных акций можно использовать товары, стоимость ко¬
торых не превышает $250, при этом в качестве кассира должен зарегистриро¬
ваться менеджер магазина.В терминах анализа требований необходимо идентифицировать конкретные точ¬
ки реализации сценария (операции enterltem, chooseCashChange и т.д.). Далее бу¬
дем рассматривать только операцию enterltem, хотя предложенное решение подхо¬
дит и для других операций.Допустим, архитектор системы хочет использовать программное решение, оказы¬
вающее минимальное влияние на существующие программные компоненты. То есть,
он хочет выработать общее решение для различных ситуаций, детали реализации ко¬
торого для каждой из этих ситуаций различны. Допустим, он не знает, какую реализа¬
цию использовать для данных подключаемых правил, и хочет поэкспериментировать
с разными решениями для представления, загрузки и обработки правил. Например,
правила можно реализовать с помощью шаблона Strategy или с помощью свободно
распространяемых интерпретаторов, считывающих и интерпретирующих набор пра¬
вил if-then, либо на основе коммерческих интерпретаторов правил.Для решения этой проблемы используется шаблон Facade.Имя FacadeПроблема Как обеспечить унифицированный интерфейс с набором разрозненных
реализаций или интерфейсов, например с подсистемой, если нежела¬
тельно высокое связывание с этой подсистемой или реализация подси¬
стемы может измениться?Решение Определить одну точку взаимодействия с подсистемой — фасадный(совет) объект, — обеспечивающий общий интерфейс с подсистемой, и возло¬жить на него обязанность по взаимодействию с ее компонентами.Фасад — это внешний объект, обеспечивающий единственную точку входа для
служб подсистемы.2 Реализация других компонентов подсистемы закрыта и не вид¬
на внешним компонентам. Фасадный объект обеспечивает реализацию шаблона
Protected Variations с точки зрения защиты от изменений в реализации подсистемы.Например, можно определить подсистему “генератора правил”, конкретная реа¬
лизация которой неизвестна. Она может обрабатывать набор правил и сообщать об
отмене операций.Фасадный объект для такой подсистемы можно назвать POSRuleEngineFacade.
Разработчик может обращаться к этому объекту в начале метода, определяющего точ¬
ку подключения правил, как в следующем примере.public class Sale{public void makeLineltem( ProductDescription desc, int quantity){SalesLineltem sli - new SalesLineltem(desc, quantity);2 В данном случае термин “подсистема” используется в неформальном смысле для обозначе¬
ния отдельной группы взаимосвязанных компонентов, а не в традиционном смысле UML.
Глава 26. Применение шаблонов проектирования GoF 485// обращение к фасадному объекту
if (POSRuleEngineFacade.getlnstance().islnvalid(sli, this))
return;lineltems.add(sli);}//...}//конец описания классаОбратите внимание на использование шаблона Singleton. Доступ к фасадным
объектам зачастую обеспечивается посредством этого шаблона.В этом примере детали реализации и ее сложность скрыты в подсистеме “генера¬
тора правил”, доступ к которой осуществляется через объект POSRuleEngineFacade.
Заметим, что подсистема, скрываемая за “фасадом”, может содержать десятки или
сотни объектов, либо даже вообще не содержать объектно-ориентированного реше¬
ния. Внешний пользователь будет видеть только открытую часть этой подсистемы.При этом различные аспекты реализации обеспечиваются разными частями под¬
системы.Заключительные замечанияШаблон Facade достаточно прост, поэтому он широко используется. Он призван
скрывать подсистему за “фасадом” одного объекта.Связанные шаблоны. К фасадным объектам доступ зачастую обеспечивается
посредством шаблона Singleton. Шаблон Facade обеспечивает реализацию шаблона
Protected Variations для реализации подсистем за счет добавления объекта, удовлетво¬
ряющего шаблону Indirection с целью выполнения шаблона Low Coupling. Внешние
объекты “общаются” с подсистемой через фасадный объект.Как было сказано ранее, для доступа к внешним подсистемам с разными интер¬
фейсами можно использовать шаблон Adapter. Это тоже разновидность фасадного
объекта, обеспечивающего взаимодействие с разными интерфейсами.В UML существует обозначение для группы некоторых объектов — так называе¬
мого пакета (package). Оно напоминает пиктограмму папки с корешком. Пакеты ис¬
пользуются для отображения логической группировки объектов и могут соответство¬
вать пакетам в Java, пространствам имен в C++ либо другим логически обоснованным
компонентам или подсистемам. На рис. 26.20 открытой частью пакета является толь¬
ко объект POSRuleEngineFacade.26.10. Шаблон Observer/Publish-Subscribe/
Delegation Event Model (GoF)Еще одним требованием для данной итерации является обеспечение возможности
обновления окна интерфейса пользователя при изменении общей стоимости покупки
(рис. 26.21). Решив эту проблему, на пбследующих итерациях можно воспользоваться
полученным проектным решением для обновления окна интерфейса пользователя
при изменении каких-либо других данных.
486 Часть IV. Вторая итерация фазы развития — дополнительные шаблоныDomain о-+Sale+RegisterИмя пакета можно указать во вкладкеМожно отобразить видимость
элемента пакета (за пределами
пакета), поместив перед его
именем соответствующий символ+POSRuleEngineFacadeinstance:RuleEngineFacadegetlnstance():RuleEngineFacadeisInvalid(SalesLineItem,Sale)
isInvalid(Payment,Sale)«interface»-IRule-Rulel-Rule2Puc. 26.20. Обозначение пакета в языке UMLРис. 26.21. Обновление интерфейса при изменении общей стоимости покупки
Глава 26. Применение шаблонов проектирования GoF 487Почему не воспользоваться следующим решением? При изменении общей стоимо¬
сти покупки объект Sale передает сообщение объекту окна с требованием обновить
его содержимое.Такое решение не согласуется с принципом шаблона Model-View Separation.
Согласно этому принципу, объекты уровня предметной области (в частности, Sale)
не должны знать о представлении объектов в окнах. Это обеспечивает слабое связы¬
вание между уровнями интерфейса и объектов предметной области.Преимуществом такого подхода является возможность замены интерфейса поль¬
зователя, не затрагивая объекты уровня предметной области. Если объекты модели
“не знают” об объектах Java Swing, то можно отключить интерфейс Swing и заменить
его другими объектами.Таким образом, шаблон Model-View Separation поддерживает требования шаблона
Protected Variations при изменении интерфейса пользователя.Для решения этой проблемы проектирования используется шаблон Observer
(Наблюдатель) или Publish-Subscribe (Опубликовать-подписаться).Имя Observer (Publish-Subscribe)Проблема Различные классы объектов-подписчиков должны знать об изменении
состояния или некоторых событиях другого объекта и соответствую¬
щим образом реагировать на эти изменения. Более того, необходимо
поддерживать низкий уровень связывания с объектами-подписчиками.
Что делать?Решение Определить интерфейс “подписки” или “прослушивания”. Объекты-под-
(совет) писчики реализуют этот интерфейс и динамически регистрируются дляполучения информации о некотором событии. Затем при реализации
этого события оповещаются все объекты-подписчики.Пример такого решения показан на рис. 26.22.Основная идея этого решения сводится к следующему.1. Определяется интерфейс. В данном случае это интерфейс PropertyListener с
операцией onPropertyEvent.2. Определяется окно для реализации интерфейса.• Окно SaleFramel будет реализовывать метод onPropertyEvent.3. При инициализации окна SaleFramel ему передается экземпляр Sale для ото¬
бражения общей стоимости покупки.4. Объект окна SaleFramel регистрирует (или подписывается на) экземпляр Sale
для уведомления о данном событии посредством сообщения addPropertyLis-
tener. Тогда при изменении свойства (например, общей стоимости) объект
окна будет получать уведомление.5. Заметим, что объект Sale “не знает” о существовании объекта SaleFramel.
Он лишь “знает” о существовании объектов, реализующих интерфейс
PropertyListener. Это снижает уровень связывания объекта Sale с окном.
Объект Sale связан только с интерфейсом, а не с классом GUI.6. Экземпляр Sale публикует информацию о событиях. При изменении об¬
щей стоимости покупки эта информация передается всем подписчикамPropertyListener.
488 Часть IV. Вторая итерация фазы развития — дополнительные шаблоныfor each PropertyListener pi in propertyListeners
pi.onPropertyEvent( this, name, value );SaleaddPropertyListener(PropertyListener lis)0>
‘ф publishPropertyEvent(name, value)setTotal(Money newTotal)Qj avax.swing.JFramesetTitle()
setVisible()propertyListenerstotal = newTotal;publishPropertyEvent("sale.total",total) ;V«interface»PropertyListeneronPropertyEvent(source,name,value)Z57SaleFramel}onPropertyEvent(source,name,value)°< k.sale.addPropertyListener(this)}initialize(Sale sale) о Puc. 26.22. Шаблон ObserverОбъект SaleFramel в данном случае выступает наблюдателем или подписчи¬
ком. Из рис. 26.23 видно, что он “подписывается” на получение информации о со¬
бытиях объекта Sale. Объект Sale добавляет SaleFramel в свой список подписчи¬
ков PropertyListener. При этом он “не знает” о существовании самого объекта
SaleFramel, а “знает” лишь о существовании нового объекта PropertyListener. Это
снижает уровень связывания между уровнями приложения.Как видно из рис. 26.24, при изменении общей стоимости покупки объекта Sale
эта информация передается всем подписчикам этого события путем передачи сооб¬
щения onPropertyEvent.Обозначения UML. Обратите внимание на отображение полиморфных сообщений
на диаграмме взаимодействия (см. рис. 26.24).Экземпляр SaleFramel, реализующий интерфейс PropertyListener, реализует в
том числе и метод onPropertyEvent. При получении сообщения он отправляет со¬
общение объекту JTextField объекта GUI об обновлении значения общей стоимо¬
сти покупки (рис. 26.25).
Глава 26. Применение шаблонов проектирования GoF 489Рис 26.23. Наблюдатель SaleFramel подписывается на получение информации
об изменении свойств объекта SaleРис 26.24. Объект Sale распространяет информацию об изменении свойств своим подписчикамРис. 26.25. Подписчик SaleFramel получает уведомление о событии
490 Часть IV. Вторая итерация фазы развития — дополнительные шаблоныПри реализации этого шаблона объекты модели (Sale) все же связаны с объекта¬
ми представления (SaleFramel). Однако уровень графического интерфейса отделен
от уровня предметной области интерфейсом PropertyListener. Такое проектное
решение не требует реальной регистрации объектов-подписчиков, т.е. список подпис¬
чиков объекта Sale может быть пустым. При этом связывание с общим интерфейсом
объектов, которые могут динамически добавляться к списку подписчиков (и удаляться
из него), поддерживает принципы шаблона Low Coupling. Следовательно, выполняет¬
ся шаблон Protected Variations в смысле независимости от интерфейса пользователя.Почему этот шаблон называется Observer,
Publish-Subscribe, или Delegation Event ModelИзначально этот шаблон назывался Publish-Subscribe (Опубликовать-подписаться).
Он и до сих пор широко распространен под этим именем. Один объект “публикует”
информацию о событии (Sale). Эти сведения могут никого не интересовать, в этом
случае у объекта Sale не будет зарегистрированных подписчиков. Однако заинтере¬
сованные объекты могут “подписаться” на получение информации, тогда при реали¬
зации некоторого события они будут уведомлены. Это делается с помощью сообще¬
ния Sale.addPropertyListener.Этот шаблон также называют Observer (Наблюдатель), поскольку слушатели или
подписчики “наблюдают” событие. Этот термин был очень распространен в Smalltalk
в начале 1980-х годов.При реализации на Java этот шаблон называют также Delegation Event Model
(Модель делегирования событий), поскольку обработка событий “делегируется” слу¬
шателям (или подписчикам) (рис. 26.26).Шаблон Observer не только связывает интерфейс
пользователя с объектами моделиПредыдущий пример иллюстрирует применение шаблона Observer для связыва¬
ния объектов GUI с объектами предметной области. Однако это не единственный
пример использования шаблона.Чаще всего этот шаблон применяется для обработки событий объектов GUI при
использовании как технологий Java (AWT и Swing), так и Microsoft (.NET). Каждый
элемент интерфейса публикует связанные с ним события, а другие объекты могут
подписаться на получение уведомлений о них. Например, объект Swing JButton опо¬
вещает своих подписчиков о щелчке на кнопке. Объекты-подписчики при получении
такого уведомления могут выполнять некоторые характерные действия.В качестве другого примера на рис. 26.27 показан объект будильника AlarmClock,
уведомляющий о событиях своих подписчиков. Из этого примера видно, что подпис¬
чиками могут быть одновременно несколько объектов, и каждый из них может реаги¬
ровать на уведомление по-своему.
Глава 26. Применение шаблонов проектирования GoF 491Рис. 26.26. Кто является наблюдателем, слушателем или подписчиком?На одно событие могут подписаться
несколько пользователейКак видно из рис. 26.27, на одно событие могут подписаться несколько пользова¬
телей. Например, один экземпляр AlarmClock может иметь три зарегистрированных
объекта AlarmWindow, четыре объекта Beeper и один ReliabilityWatchDog. При
реализации события все восемь подписчиков AlarmListener будут уведомлены по¬
средством сообщения onAlarmEvent.РеализацияСобытияВ обеих реализациях шаблона Observer (на Java или C# .NET) уведомление о со¬
бытии выполняется с помощью обычного сообщения, например onPropertyEvent.
Более того, в обоих случаях событие формально определяется как класс с соответ¬
ствующими данными о событии. Такое событие передается в качестве параметра со¬
общения.
492 Часть IV. Вторая итерация фазы развития — дополнительные шаблоныfor each AlarmListener al in alarmListeners
al.onAlarmEvent(this, time);{alarmListeners.add(lis) ;}AlarmClockaddAlarmListener(AlarmListener lis) O'
‘6 publishAlarmEvent(time)setTime(newTime) Очj avax.swing.JFramesetTitle()
setVisible()~KalarmListenersЖ.«interface»AlarmListeneronAlarmEvent(source,t ime)X{time = newTime;
if (time == alarmTime)
publishAlarmEvent(time) ;}уAlarmWindowBeeper4ReliabilityWatchDogonAlarmEvent(source,time)
Q.onAlarmEvent(source,time)
°чonAlarmEvent(source,t ime)
o4"i Ц// отображение
// диалогового окна
//с уведомлением}{// звуковой сигнал}1 Ц// проверка того, что
// все требуемые процессы
// выполняются нормально}Рис. 26.27. Шаблон Observer при наличии нескольких подписчиковРассмотрим следующий пример.class PropertyEvent extends Event
{private Object sourceOfEvent;
private String propertyName;
private Object oldValue;
private Object newValue;//...}//...
Глава 26. Применение шаблонов проектирования GoF 493class Sale{private void publishPropertyEvent(String name, Object old, Object new ){PropertyEvent evt =new PropertyEvent (this, "sale.total", old, new);for each AlarmListener al in alarmListeners
al.onPropertyEvent( evt )}//...}JavaВ первой версии набора JDK 1.0, увидевшей свет в январе 1996 года, содержа¬
лись некоторые средства реализации этого шаблона в виде класса и интерфейса
Observable и Observer соответственно. Эти средства были, по существу, скопирова¬
ны без всякого улучшения реализации механизма подписки Smalltalk, реализованного
в начале 1980-х годов.В конце 1996 года в версии JDK 1.1 проектное решение Observable-Observer
было эффективно заменено более робастной версией модели делегирования сообще¬
ний DEM (Delegation Event Model) Java, однако прежнее решение было сохранено
для обеспечения совместимости с более ранней версией (но в целом его не рекомен¬
довалось использовать).Решения, описанные в этой главе, ориентированы на модель DEM, но несколько
упрощены с целью более ясного изложения идей.Заключительные замечанияШаблон Observer обеспечивает способ снижения связывания объектов при взаи¬
модействии. О подписчиках известен только их интерфейс. При этом подписчики
могут динамически регистрироваться (или отключаться) на получение информации
о событиях.Связанные шаблоны. Шаблон Observer основан на принципах полиморфизма и
обеспечивает реализацию шаблона Protected Variations в смысле знания конкретных
типов подписчиков и их количества.26.11. ВыводыГлавный вывод, который можно сделать на основе вышеизложенного материала,
заключается в следующем. Распределять обязанности в процессе объектно-ориенти¬
рованного проектирования можно на основе применения шаблонов. Шаблоны пред¬
ставляют собой набор идиом, на базе которых можно разработать удачную объектно-
ориентированную систему.
494 Часть IV. Вторая итерация фазы развития — дополнительные шаблоны26.12. Дополнительная литератураВсем разработчикам в рамках объектного подхода можно порекомендовать книгу
Гамма, Хелма, Джонсона и Влиссидеса [58]. В ней можно найти конструктивную ин¬
формацию о шаблонах проектирования.Ежегодно проходит конференция PLOP (Pattern Languages of Programs), по ре¬
зультатам которой публикуется сборник шаблонов в серии Pattern Languages of Program
Design (том 1, 2 и т.д.). Рекомендую прочитать всю серию.В [17] (том 1 и 2) продолжается обсуждение шаблонов для больших приложений.
В первом томе приводятся принципы систематизации шаблонов.На сегодняшний день описаны сотни шаблонов, большая часть из которых рас¬
смотрена в [106].
ЧастьVТретья итерация
фазы развитияВ этой части...Глава 27. Третья итерация — вспомогательные вопросы
Глава 28. Диаграммы видов деятельности UML
Глава 29. Диаграммы состояний UML и моделирование
Глава 30. Взаимосвязь прецедентовГлава 31. Дополнительные диаграммы последовательностей и описание
операцийГлава 32. Уточнение модели предметной областиГлава 33. Архитектурный анализГлава 34. Уточнение логической архитектурыГлава 35. Новые проектные решения на основе шаблонов GoFГлава 36. Проектирование на основе пакетовГлава 37. Диаграммы развертывания и компонентов UMLГлава 38. Проектирование каркаса взаимодействия с базой данных на
основе шаблоновГлава 39. Документирование архитектуры с помощью N+1 представления
Третья итерация —
вспомогательные вопросыОсновная задача■ Определить требования для реализации на третьей итерации.ВведениеВ течение начальной фазы и первой итерации были исследованы фундаменталь¬
ные аспекты процесса анализа требований и ООА/П. На второй итерации основное
внимание уделялось вопросам проектирования объектов. На третьей итерации мы
снова попытаемся “более широко” взглянуть на вещи, обратившись к анализу и про¬
ектированию в следующих областях.■ Дополнительные шаблоны проектирования GoF и их применение к проектиро¬
ванию каркасов, в частности каркаса взаимодействия с базой данных■ Архитектурный анализ и документирование архитектуры■ Моделирование процессов с помощью диаграмм видов деятельности UML■ Обобщение и специализация■ Проектирование пакетовЧто дальше? После завершения итерации 2 в данной главе приводятся требования
для итерации 3. В следующей главе кратко рассматриваются вопросы
использования для моделирования диаграмм видов деятельности/\Шаблоны GRASP: ПР"“»е»“шаблонов Требованиядополнительные к „объекты проектирования итерации 3GoFДиаграммывидовдеятельностиUMLДиаграммысостоянийUML
498 Часть V. Третья итерация фазы развития27.1. Требования третьей итерации
для POS-системы NextGenНа третьей итерации разработки этого приложения реализуются следующие тре¬
бования.■ Обеспечить возможность использования локальных служб, если удаленные
службы оказались недоступными. Например, если не удается получить доступ к
удаленной базе данных товаров, то нужно воспользоваться ее локальной верси¬
ей с кешированными данными.■ Обеспечить поддержку устройств POS-системы, таких как выдвижной ящик для
хранения наличных и аппарат для приема монет.■ Обеспечить авторизацию кредитных карточек.■ Обеспечить возможность использования объектов, подлежащих постоянному
хранению.27.2. Требования третьей итерации
для игры “Монополия”На третьей итерации разработки этого приложения реализуются следующие тре¬
бования.■ Продолжить реализацию базового сценария прецедента игра “Монополия” —
перемещение игроков по игральной доске. Как и ранее, игра происходит в ре¬
жиме имитационного моделирования, пользователь только задает количество
игроков. Однако на третьей итерации реализуется более полный набор правил
игры, которые описаны в следующих пунктах.■ Добавляются клетки Частные владения (Lot), Железная дорога (Railroad) и
Коммунальные службы (Utility), при попадании на которые выполняются раз¬
личные действия.■ Если эти клетки еще никому не принадлежат, при попадании на них игрок мо¬
жет их купить. При этом стоимость покупки определяется финансовым состоя¬
нием игрока и потенциальной прибылью от их приобретения.• В начале игры цена этих клеток задается произвольным образом, например,
в соответствии с общепринятыми ценами для игры “Монополия”.■ Если на клетки Частные владения (Lot), Железная дорога (Railroad) и Комму¬
нальные службы (Utility) попадает их владелец, ничего не происходит.■ Если на клетки Частные владения (Lot), Железная дорога (Railroad) и Коммуналь¬
ные службы (Utility) попадает игрок, который не является их владельцем, он дол¬
жен заплатить плату за аренду в пользу владельца этой собственности.• Плата за аренду частных владений равна порядковому номеру клетки, напри¬
мер, если клетка находится в позиции 5, плата составляет $5.• Плата за аренду железной дороги равна произведению числа 25 на количе¬
ство железных дорог у их владельца. Например, если владелец данной дороги
является собственником 3 железных дорог, плата за аренду составляет $75.• Плата за аренду коммунальных зданий равна значению кубиков, выпавшему
при попадании игрока на данную клетку, увеличенному в 4 раза (кубики по¬
вторно не вбрасываются).
Диаграммы видов
деятельности UMLЕсли эта информация не была сохранена, значит,> она не существенна.Системный администраторОсновная задача■ Ознакомиться с обозначениями диаграмм видов деятельности языка
UML и примерами таких диаграмм для различных приложений.ВведениеДиаграммы видов деятельности отображают последовательные и параллельные
процессы. Они полезны для моделирования бизнес-процессов, последовательностей
выполнения задач, потоков данных и сложных алгоритмов.Что дальше? После определения требований для итерации 3 в данной главе рассматриваются
вопросы моделирования с использованием диаграмм видов деятельности UML.
В следующей главе иллюстрируются возможности использования
для моделирования диаграмм состояний/Применениешаблонов Требованияпроектирования итерации 3
GoFДиаграммывидовдеятельностиUML\ДиаграммысостоянийUMLВзаимосвязьпрецедентов
500 Часть V. Третья итерация фазы развития28.1. ПримерОсновные обозначения UML для диаграмм видов деятельности (activity diagrams) по¬
казаны на рис. 28.1. На таких диаграммах отображаются действия (action), точки вет¬
вления (fork), разделы (partition), объединения (join) и объекты (object). По существу, на
этих диаграммах изображают последовательности действий, часть из которых может
выполняться параллельно. Большая часть обозначений довольно очевидна, но неко¬
торые требуют пояснения.■ При завершении вида деятельности выполняется автоматический завершаю¬
щий переход.■ На диаграммах могут отображаться как потоки управления, так и потоки данных.Выполнение заказаНачало 1Разделы. Иллюстрируют
различные компоненты,
задействованные в процессеУзел объекта. Создаваемый 1
объект или объект, используемый
при выполнении различных видов
деятельности. Используется при
моделирования потоков данных
или потоков объектовТочка объединения. Несколько W
входных переходов и/или потоков
объектов; один выходной переход.
Выходной переход не инициируется
до тех пор, пока точки объединения
не достигнут всех входных данных
всех потоковXI-Завершение IL
вида деятельности |СлужбаобслуживанияФинансоваяслужбаVПолучениевидеозаказаДействие. Выполнение ■
некоторых операций. После его
завершения выполняется
автоматический переход.
Переходы поддерживают моде¬
лирование потоков управлениятТочка ветвления. Один к
входящий переход и несколько
выходных параллельных пере¬
ходов и/или потоков объектовОтправка
счета ГЛЗакрытиезаказаСчетVПолучениеплатежа7Рис. 28.1. Основные обозначения UML для диаграмм видов деятельности
Глава 28. Диаграммы видов деятельности UML 50128.2. Как применять диаграммы
видов деятельностиВ UML диаграммы видов деятельности (activity diagrams) обеспечивают систему обо¬
значений для последовательности видов деятельности. Эти обозначения можно ис¬
пользовать в различных целях (в том числе для визуализации шагов компьютерного
алгоритма), однако они особенно полезны для построения диаграмм прецедентов и
графиков выполнения проекта.Моделирование бизнес-процессовОдин из моих заказчиков занимается грузоперевозками. Этот процесс являет¬
ся очень нетривиальным, поскольку в нем участвуют множество заинтересованных
лиц (заказчик, водитель и т.д.). Этот процесс можно представить в текстовом виде
(в форме описания прецедента), но диаграмма видов деятельности поможет сэконо¬
мить тысячи слов. Мой заказчик использует диаграммы видов деятельности для улуч¬
шения понимания сложных бизнес-процессов и их визуализации. Разделы позволяют
рассмотреть составные части и параллельные действия процесса, а узлы объектов —
проиллюстрировать основную сущность видов деятельности. Визуальное моделиро¬
вание облегчает процесс внесения изменений и оптимизацию. На рис. 28.1 показан
простой пример применения диаграмм видов деятельности для моделирования биз-
нес-процессов. Модель видов деятельности моего заказчика, связанная с грузопере¬
возками, занимает целую стену.Моделирование потоков данныхНачиная с 1970-х годов диаграммы потоков данных (data flow diagram — DFD) явля¬
ются популярным средством визуализации основных действий над данными в рамках
программной системы. В отличие от моделей бизнес-процессов, диаграммы потоков
данных обычно используются для отображения потоков данных в компьютерных си¬
стемах. Они позволяют построить высокоуровневые проектные решения в терминах
работы с данными. Основные обозначения DFD показаны на рис. 28.2. Обратите вни¬
мание, что на этом рисунке основные шаги пронумерованы.Диаграммы потоков данных полезны для документирования и исследования про¬
цессов. Однако UML не содержит специальных обозначений для их построения. К
счастью, DFD можно строить с помощью обозначений диаграмм видов деятельности
UML. На рис. 28.3 показана та же информация, что и на рис. 28.2, но с использова¬
нием обозначений диаграмм видов деятельности UML. Обратите внимание, что по¬
мимо объектов на диаграмме потоков данных используются узлы хранилищ данных,
помеченные стереотипом «datastore».Параллельное программирование
и моделирование параллельных алгоритмовПараллельные алгоритмы и параллельные программы не относятся к предмету
рассмотрения этой книги, но включают множество разделов, точек ветвления и объе¬
динений. Например, такие алгоритмы используются для 3D-моделирования на основе
конечного числа элементов, анализа сопротивления материалов, моделирования пого¬
502 Часть V. Третья итерация фазы развитияды и т.д. Общее физическое пространство делится на большие блоки, для каждого из
которых используется один из параллельных потоков или процессов. Разделы на диа¬
граммах видов деятельности UML можно использовать для представления различных
потоков или процессов в операционной системе. Узлы объектов используются для мо¬
делирования совместно используемых объектов или данных. Точки ветвления иллю¬
стрируют создание и параллельное выполнение множества потоков и процессов.Диаграмма потоков данных для автоматизированной системыРис. 28.2. Классическая диаграмма потоков данныхРис. 28.3. Применение обозначений диаграмм видов деятельности
для построения модели потоков данных
Глава 28. Диаграммы видов деятельности UML 50328.3. Дополнительные обозначения
диаграмм видов деятельности UMLКак продолжить диаграмму видов деятельности на другой диаграмме? Эта ситуа¬
ция показана на рис. 28.4 и 28.5. При этом используется специальный символ, напо¬
минающий трезубец (rake).Для отображения условных переходов используются символы условных переходов
(decision) и слияния (merge) (рис. 28.5).Символ трезубца
(обозначающий иерархию)
свидетельствует о том, что
данный вид деятельности
будет показан на отдельной
диаграммеЗаполнениезаказа\/rhДоставказаказаРис. 28.4. Диаграмму видов деятельности можно продолжить на другой диаграммеУсловный переход.Возможны оба перехода.
Эти переходы являются
взаимоисключающимиТочка слияния. Любые^Х
входные данные приводят
к продолжению процесса.
Этим точки слияния
отличаются от точек
объединения, в которых
перед продолжением
процесса их должны
достигнуть все входные
данныеРис. 28.5. Ветвление вида деятельностиНа рис. 28.6 показаны сигналы, применяемые для моделирования событий, пере¬
ключаемых по времени.В UML существуют и другие обозначения для диаграмм видов деятельности, но в
этом кратком введении описаны лишь основные элементы.28.4. РекомендацииПриведем несколько рекомендаций, касающихся моделирования видов деятель¬
ности.
504 Часть V. Третья итерация фазы развития■ Эта методология оправданна для визуализации очень сложных процессов, в
которых задействовано множество участников. Простые процессы лучше пред¬
ставлять в виде описания прецедентов.■ При моделировании бизнес-процесса используйте переходы между диаграмма¬
ми. На диаграмме уровня 0 можно показать действия на самом высоком уровне
абстракции. Тогда эта диаграмма останется простой и понятной. Детализацию
можно выполнить на диаграммах уровня 1, уровня 2 и т.д.■ При построении конкретной диаграммы придерживайтесь одного уровня аб¬
стракции. Не следует смешивать на одной диаграмме понятия разного уровня.28.5. Пример: диаграмма видов деятельности
для приложения NextGenНа рис. 28.7 показано применение UML для описания процессов прецедента
Оформление продажи. Этот пример приведен для наглядности. На самом деле он яв¬
ляется относительно простым и его лучше представить в виде описания прецедента.Рис. 28.6. Сигналы
Глава 28. Диаграммы видов деятельности UML 505Покупатель Кассир POS-система NextGen СлужбаРис. 28.7. Моделирование прецедента Оформление продажи с помощью диаграммывидов деятельности28.6. Диаграммы видов деятельности в UPОдной из дисциплин UP является бизнес-моделирование. Ее задача — сформиро¬
вать и отразить “структуру и динамику организации, в которой развертывается систе¬
ма” [112]. Основным артефактом этой дисциплины является модель бизнес-объектов
(прототип модели предметной области UP), в рамках которой с помощью диаграмм
классов, последовательностей и видов деятельности UML обычно отображается эко¬
номическая деятельность предприятия. Таким образом, диаграммы видов деятельно¬
сти чаще всего строятся в процессе дисциплины бизнес-моделирования.
506 Часть V. Третья итерация фазы развития28.7. Другие подходыЯзыки моделирования процессов и потоков данных появились очень давно.
Однако с каждым годом диаграммы видов деятельности UML становятся все более
популярными.Семантика диаграмм видов деятельности базируется на вычислительной теории
сетей Петри (Petri net), представляющих собой графы видов деятельности, по кото¬
рым перемещаются маркеры (token). Если маркер попадает в узел, соответствующий
определенному действию, то это действие выполняется. В результате прохождения
по сети всех маркеров создается выходной маркер.
Диаграммы состояний
UML и моделированиеНет, нет, вы не мыслите, а просто рассуждаете логически.Нильс Бор (Niels Bohr)Основная задача■ Ознакомиться с обозначениями UML для диаграмм состояний и при¬
мерами их построения для различных приложений.ВведениеКак и диаграммы видов деятельности, диаграммы состояний UML отражают ди¬
намическую модель системы. С их помощью иллюстрируются события и состояния
объектов — транзакций, прецедентов, людей и т.д. В этой главе обсуждаются наибо¬
лее важные аспекты использования диаграмм состояний, однако, кроме них, суще¬
ствуют и многие другие особенности.Применение диаграмм состояний, в основном, ориентировано на отображение
системных событий в рамках описания прецедентов, но они могут быть использова¬
ны и в ряде других случаев.Что дальше?После знакомства с диаграммами видов деятельности в данной главе
рассматриваются диаграммы состояний. Следующая глава посвященаисследованию взаимосвязи прецедентов/\ДополнительныеТребованияДиаграммывидовДиаграммысостоянийВзаимосвязьдиаграммыпоследова¬итерации 3деятельностиUMLUMLпрецедентовтельностей
и описание
операций0 —о • о— о
508 Часть V. Третья итерация фазы развития29.1. ПримерНа диаграммах состояний языка UML (рис. 29.1) иллюстрируются интересные со¬
бытия и состояния объекта, а также поведение объекта в ответ на реализацию собы¬
тий. Переходы между состояниями обозначаются стрелками с указанием соответствую¬
щих событий. Сами состояния изображаются в виде прямоугольников со скругленными
углами. Зачастую используется некоторое начальное псевдосостояние, которое автома¬
тически переходит в другое состояние при создании экземпляра класса.ТелефонНачальное, off hook .
Idle ) — >( ActiveСостояние Ion hook о.ПереходСобытиеРис. 29.1. Диаграмма состояний для телефонаДиаграмма состояний отражает жизненный цикл объекта. На ней отображаются
события, в которых участвует данный объект, переходы и состояния объекта между
событиями. Нет необходимости иллюстрировать все возможные события: в случае
реализации события, не отображенного на диаграмме, событие игнорируется, со¬
гласно диаграмме состояний. Следовательно, можно создавать диаграммы состояний,
описывающие жизненный цикл объекта с произвольной степенью детализации или
упрощения, в зависимости от текущих потребностей.29.2. События, состояния и переходыСобытие (event) — это значимое или заслуживающее внимания происшествие.
Например:■ снятие телефонной трубки с рычага.Состояние (state) — это условие, характеризующее объект в некоторый момент
между двумя событиями. Например:■ телефон находится в состоянии “ожидания” с момента опускания трубки на ры¬
чаг и до момента снятия трубки.Переход (transition) — это такое отношение между двумя состояниями, которое ука¬
зывает на переход объекта из одного состояния в другое при выполнении некоторо¬
го события. Например:■ в случае реализации события “снятие трубки” телефон переходит из состояния
ожидания в состояние активности.
Глава 29. Диаграммы состояний UML и моделирование 50929.3. Как применять диаграммы состоянийОбъекты, независимые и зависимые от состоянийЕсли объект всегда одинаково реагирует на событие, то он считается независимым
от состояния (state-independent object) (или безрежимным) по отношению к этому со¬
бытию. Например, если в ответ на получение сообщения всегда вызывается один и
тот же метод объекта, в теле которого не содержится операторов ветвления, этот
объект считается независимым от состояния по отношению к данному событию.
Если на все интересующие нас события некоторый объект реагирует одинаково, то
он называется независимым от состояния объектом (state-independent object). В отличие
от него, зависимые от состояния объекты (state-dependent object) по-разному реагируют
на одно и то же событие в зависимости от своего состояния.СоветДиаграммы состояний создаются для зависимых от состояний типов со сложнымповедением.Например, телефон — это объект, зависимый от состояния. Его реакция на нажа¬
тие конкретной кнопки зависит от текущего режима работы телефона и положения
трубки.Диаграммы состояний, построенные для сложных ситуаций, зачастую позволяют
лучше понять происходящие процессы и задокументировать их.СоветВ целом, в экономических информационных системах содержится очень мало ин¬
тересных классов, зависимых от состояния, а системы управления процессами и
системы телекоммуникаций зачастую содержат множество зависимых от состоя¬
ния объектов.Моделирование зависимых от состояния объектовДиаграммы состояний применяются в двух случаях.1. Для моделирования поведения сложных объектов, реагирующих на внешние
событий.2. Для моделирования допустимых последовательностей операций — специфика¬
ций протоколов или языков.• Эта ситуация является частным случаем п.1, если в качестве объекта высту¬
пает язык, протокол или процесс. Формальную грамматику контекстно-неза¬
висимого языка можно представить в виде диаграммы состояний.Перечислим стандартные объекты, которые обычно являются зависимыми от со¬
стояния и для которых полезно создавать диаграммы состояний.
510 Часть V. Третья итерация фазы развитияСложные объекты, реагирующие на события■ Физические устройства с программным управлением.• Телефон, автомобиль и микроволновая печь по-разному реагируют на кон¬
кретное событие в зависимости от их текущего состояния.■ Транзакции и взаимосвязанные бизнес-объекты.• Как бизнес-объект реагирует на различные события? Например, что проис¬
ходит в случае отмены заказа? Понимание всех событий и состояний помога¬
ет спроектировать систему, оценить полученное решение и модифицировать
его.■ Изменяемые классы (это классы, изменяющие свою роль).• Штатский человек, ставший военным.Протоколы и допустимые последовательности событий■ Коммуникационные протоколы.• TCP и другие протоколы можно легко представить с помощью диаграмм со¬
стояний, иллюстрирующих допустимые операции. Например, запрос close
для протокола TCP необходимо игнорировать, если обработчик уже ранее
был переведен в состояние closed.■ Окна пользовательского интерфейса.• При моделировании интерфейса полезно оценить допустимую последова¬
тельность перехода между окнами. В этом помогут диаграммы состояний.■ Контроллеры или сеансы.• Существуют программные объекты, относящиеся к серверной части приложе¬
ния и представляющие сеанс взаимодействия с клиентом. Еще одним типич¬
ным примером является обработка на сервере данных, поступающих от кли¬
ента Web-приложения, и реализация логики этого приложения. Например,
сервлет Java может выступать в роли контроллера, фиксирующего состояние
сеанса связи с Web-клиентом и управляющего передачей новых Web-страниц
или модификацией текущей страницы на основе состояния сеанса.■ Системные операции прецедентов.• Вспомним системные операции прецедента Оформление продажи: makeNewSale,
enterltem и т.д. Они должны выполняться в определенном порядке. Так,
класс по-разному реагирует на событие endSale в зависимости от состояния
продажи. Обычно порядок следования операций очевиден, но в сложных си¬
туациях помогут разобраться диаграммы состояний, на которых прецеденты
выступают в качестве объектов.■ Обработка событий отдельного окна.• Операция вставки допустима только в том случае, если в буфере обмена со¬
держится некоторый фрагмент.
Глава 29. Диаграммы состояний UML и моделирование 51129.4. Дополнительные обозначения
для диаграмм состоянийДействия и условия, связанные с переходамиПереход из одного состояния в другое может инициировать некоторое действие.
В программной реализации это может быть вызов метода класса, для которого стро¬
ится диаграмма состояний.Переход может осуществляться с учетом некоторых условий (например, логиче¬
ских) (рис. 29.2).Действие переходаIdleIoff hook / play dial tone
[подключен к станции]QГActiveon hookУсловие переходаРис. 29.2. Обозначения для действий и условий, связанных с переходамиВложенные состоянияСостояние объекта может включать в себя некоторые производные состояния
(подсостояния), которые наследуют переходы состояний более высокого уров¬
ня абстракции (суперсостояний). Подсостояния графически изображаются в виде
прямоугольников со скругленными углами, вложенных в блок основного состояния
(рис. 29.3).off hook / play dial tonePuc. 29.3. Вложенные состояния
512 Часть V. Третья итерация фазы развитияНапример, при переходе в состояние активности Active на самом деле осущест¬
вляется переход в подсостояние гудка PlayingDialTone. Независимо от того, в ка¬
ком из подсостояний находится объект, при реализации события опускания трубки
на рычаг on hook, связанного с состоянием активности, выполняется переход в со¬
стояние ожидания Idle.29.5. Моделирование навигации с помощью
диаграммы состоянийВ некоторых приложениях, особенно с Web-интерфейсом, используются сложные
переходы между страницами. Их можно задокументировать и понять с помощью диа¬
грамм состояний, создаваемых в процессе разработки системы.В рамках гибкого моделирования подобные диаграммы можно строить на больших
листах бумаги, прикрепленных к стене. Каждый лист представляет собой отдельную
Web-страницу. На листах можно рисовать элементы, разделяя их по функционально¬
сти различным цветом. Например, желтым цветом можно выделять содержательную
информацию, а розовым — элементы управления, например кнопки. Все листы долж¬
ны быть поименованы, например Страница справки и т.д.Помимо построения моделей самих страниц можно указать переходы между эти¬
ми страницами с помощью диаграмм состояний, на которых состояния представля¬
ют страницы, а переходы — события, приводящие к просмотру следующей страницы.
Пример такой модели навигации (navigation model) представлен на рис. 29.4. Это лишь
простой пример, который вряд ли будет полезен при разработке реальных приложе¬
ний. Однако в сложных приложениях подобные диаграммы играют важную роль.Рис. 29.4. Применение диаграмм состояний для моделирования нави¬
гации по Web-страницам
Глава 29. Диаграммы состояний UML и моделирование 51329.6. Пример: диаграмма состояний для
прецедента системы NextGenДиаграммы состояний зачастую используются для описания допустимой последо¬
вательности внешних системных событий, распознаваемых и обрабатываемых систе¬
мой в контексте одного прецедента. Например, на рис. 29.5 показано применение
таких диаграмм для прецедента Оформление продажи в POS-приложении NextGen.29.7. Диаграммы состояний и UPВ контексте UP не определена отдельная модель состояний. Однако для каждого
элемента любой модели (проектирования, предметной области и т.д.) можно постро¬
ить диаграмму состояний для более глубокого понимания динамического поведения
этого элемента в ответ на события. Например, можно построить диаграмму состоя¬
ний для класса Sale в рамках модели проектирования.29.8. Дополнительная литератураПрименение моделей состояний в процессе ООА/П хорошо описано в книге Кука
и Дэниелса [29]. В работе Дугласса (Douglass) Real Time UML тоже очень хорошо опи¬
сывается моделирование на основе состояний. Основное внимание в книге уделяется
системам реального времени, однако описанные подходы применимы для широкого
класса приложений.17 Зак. 3357
Взаимосвязь прецедентовПочему программисты путают Хэллоувин и Рождество ?Потому что OCT(31)=DEC(25).Народная мудростьОсновная задача■ Связать прецеденты с помощью ассоциаций включает и расширяет.ВведениеПрецеденты могут быть связаны друг с другом. Например, подчиненный прецедент
одного прецедента, такого как Обработка платежа по кредитной карточке (Handle
Credit Payment), может быть частью других прецедентов, например Оформление
продажи (Process Sale) и Обработка арендной платы (Process Rental). Определение
взаимосвязей прецедентов не влияет на поведение системы или требования к ней.
Скорее, такая возможность предоставляет (в идеале) механизм повышения качества
взаимосвязей и ясности прецедентов, снижения вероятности дублирования текста и
улучшения управляемости документами с описаниями.Что дальше? После ознакомления с диаграммами состояний в данной главе анализируютсявзаимосвязи прецедентов. В следующей главе будут рассмотрены дополнительные
диаграммы последовательностей и описания операцийДиаграммывидовдеятельностиUMLо /ДиаграммысостоянийUML—о—Взаимосвязь
прецедентов
—•—\Дополнительные
диаграммы
последова¬
тельностей
и описание
операций о Уточнениемоделипредметнойобласти о
516 Часть V. Третья итерация фазы развитияВзаимосвязи прецедентов: все хорошо в меруВ некоторых организациях в процессе работы над прецедентами много времени
тратится на обсуждение того, как связать прецеденты на диаграмме прецедентов, а
не на непосредственное составление текста описаний. На самом деле проблема го¬
раздо глубже. Зачастую разработчики тратят слишком много времени на анализ и
моделирование. В этом проявляется мышление в стиле каскадного процесса разра¬
ботки, а не итеративного и эволюционного. Если попытаться в самом начале проекта
продумать все детали реализации, то дальше стадии анализа разработка проекта не
продвинется.Несмотря на то, что в данной главе обсуждается взаимосвязь прецедентов, этот
вопрос нужно рассматривать более широко. Вне всякого сомнения, взаимосвязь пре¬
цедентов очень важна, однако не менее важной задачей является написание и самого
текста описаний. Определение требований завершается после разработки соответ¬
ствующих описаний, а не после организации прецедентен, что является не более чем
дополнительным шагом на пути повышения их четкости и снижения дублирования.
Если в течение нескольких часов (или, еще хуже, дней) группа разработчиков моде¬
лирует прецеденты и обсуждает диаграммы прецедентов с их взаимосвязями (какую
ассоциацию лучше использовать, включает или расширяет?; нужно ли прецедент еще
больше специализировать?), а не сосредотачивается на написании наиболее важной
части текста описания, то вполне возможно, что полученный эффект будет гораздо
меньше, чем ожидалось.Более того, определение взаимосвязей прецедентов можно итеративно выполнять
на фазе развития, а не пытаться в самом начале проекта за один раз усовершенство¬
вать и полностью определить диаграмму прецедентов.30.1. Отношение включаетТакая взаимосвязь является наиболее стандартной и важной.Вполне логично описать фрагмент, который будет встречаться в различных пре¬
цедентах. Например, описание оплаты по кредитной карточке может входить в раз¬
личные прецеденты, в том числе Оформление продажи (Process Sale), Обработка
арендной платы (Process Rental), Выполнение плана (Contribute to Lay-away Plan)
и т.д. Вместо того чтобы дублировать этот текст, лучше поместить его в отдельный
раздел описания прецедента и ссылаться на него при необходимости. Такой подход
является простым механизмом управления и связывания текста, который позволяет
избежать дублирования.1Рассмотрим следующий пример.1 Очень хорошо, если такие связи реализуются с использованием гиперссылок.
Глава 30. Взаимосвязь прецедентов 517Прецедент 1: Оформление продажиОсновной успешный сценарий1. Покупатель подходит с выбранными товарами к терминалу POS-системы, чтобы оплатить
покупку.7. Покупатель оплачивает покупку, и система обрабатывает этот платеж.Расширения76. Оплата по кредитной карточке: включает прецедент Обработка платежа по кредитной
карточке.7в. Оплата чеком: включает прецедент Обработка платежа чеком.Прецедент 7: Обработка арендной платыРасширения66. Оплата по кредитной карточке: включает прецедент Обработка платежа по кредитной
карточке.Прецедент 12: Обработка платежа по кредитной карточкеУровень: подчиненный прецедент
Основной успешный сценарий1. Покупатель вводит данные о своей кредитной карточке.2. Система отсылает запрос на авторизацию платежа внешней системе авторизации платежей,
чтобы получить подтверждение о возможности оплаты.3. Система получает подтверждение о возможности оплаты и сообщает об этом кассиру.4. ...Расширения2а. При взаимодействии с внешней системой POS-система получает отказ.1. Система сообщает о возникновении ошибки кассиру.2. Кассир предлагает покупателю другой вид оплаты.В приведенных выше примерах прецеденты связаны отношением включает.
Более сжатая (и, следовательно, более предпочтительная) форма включения пре¬
цедента заключается в подчеркивании его имени или его выделении каким-либо дру¬
гим способом, как показано ниже.Расширения76. Оплата по кредитной карточке: Обработка платежа по кредитной карточке.
7в. Оплата чеком: Обработка платежа чеком.
518 Часть V. Третья итерация фазы развитияОбратите внимание, что подчиненный прецедент Обработка платежа по кре¬
дитной карточке ранее содержался в разделе “Расширения прецедента Оформление
продажи”, однако был вынесен в отдельный раздел, чтобы избежать дублирования.
Кроме того, при описании прецедента разделы “Основной успешный сценарий” и
“Расширения” используются так же, как и в прецеденте Оформление продажи.Практические рекомендации по использованию отношения включает (include)
были предложены Фаулером [55]. Приведем цитату.“Используйте взаимосвязь включает в том случае, если вам приходится повто¬
ряться при описании двух или более прецедентов, а нужно избежать дублиро¬
вания”.Кроме того, взаимосвязь включает позволяет без проблем осуществить декомпо¬
зицию чрезмерно длинных прецедентов на несколько более коротких. Это значи¬
тельно повысит их четкость.Отношение включает и обработка асинхронных событийОтношение включает можно использовать также для описания обработки асин¬
хронного события. Такое событие может наступить, например, в том случае, когда
пользователь в произвольный момент времени активизировал какой-либо режим,
перешел в определенное диалоговое окно, вызвал какую-нибудь функцию, перешел
на Web-страницу или выполнил определенную последовательность действий.Представление такого асинхронного события в описании прецедента было рас¬
смотрено ранее в главе 6. Однако там рассматривались лишь ключевые вопросы, свя¬
занные с обработкой асинхронных сообщений, и не затрагивалась взаимосвязь с под¬
чиненными прецедентами.Стандартным обозначением асинхронных событий являются метки а*, б*, рас¬
полагаемые в разделе “Расширения”. Вспомните, что такие метки свидетельствуют
о расширении или возможности наступления события в любой момент времени.
Можно также указать диапазон меток, такой как 3-9, задающий определенные шаги
(но не все) в описании прецедента, когда может произойти асинхронное событие.Прецедент 1: Обработка служебной информацииОсновной успешный сценарий1....Расширенияа*. В любой момент покупатель может отредактировать информацию о себе:Редактирование личной информации,
б*. В любой момент покупатель может перейти к печати справочной информации: печать
текущей справочной информации.2-11. Покупатель отменил предыдущее действие: Отмена обработки транзакции.
Глава 30. Взаимосвязь прецедентов 519Заключительные замечанияВзаимосвязь включает можно применять для разрешения большинства проблем,
возникающих при организации прецедентов. В качестве заключительных рекоменда¬
ций можно сформулировать следующее.Сценарии прецедента следует выделять в отдельные прецеденты, связанные от¬
ношением включает, при выполнении следующих условий.■ Эти сценарии дублируются в других прецедентах.■ Прецедент является очень сложным и длинным, поэтому выделение сценариев
в отдельный прецедент позволит значительно его упростить.Как вы узнаете чуть позже, существуют и другие отношения: расширяет (extend)
и обобщения (generalization). Однако Кокбурн (Cockburn), эксперт в области моде¬
лирования прецедентов, предпочитает использовать именно взаимосвязь включает.
Приведем цитату.“В качестве первого и основного правила руководствуйтесь следующим: между
прецедентами всегда используйте взаимосвязь включает. Те, кто следуют этому
правилу, сообщают о том, что у них самих и тех, кто читает их описания, воз¬
никает гораздо меньше проблем, чем у тех, кто наряду с отношением включает
применяет также отношения расширяет и обобщает [37]”.30.2. Новые термины: конкретный, абстрактный,
основной и дополнительный прецедентыКонкретный прецедент (concrete use case) инициируется исполнителем и опи¬
сывает общее поведение системы [112]. В таких прецедентах описываются элемен¬
тарные бизнес-процессы. Например, прецедент Оформление продажи является кон¬
кретным. В отличие от этого, абстрактный прецедент (abstract use case) никогда не
инстанцируется, а является сценарием, т.е. частью другого прецедента. Прецедент
Обработка платежа по кредитной карточке является абстрактным. Он сам никог¬
да не инициируется, однако всегда входит в состав другого прецедента, такого как
Оформление продажи.Прецедент, включающий другой прецедент, или расширяемый/обобщаемый
другим прецедентом, называется основным (base use case). Прецедент Оформление
продажи является основным, поскольку он включает прецедент Обработка платежа
по кредитной карточке. Однако прецедент, являющийся включением, расширени¬
ем, или специализацией, называется дополнительным (addition use case). Прецедент
Обработка платежа по кредитной карточке является дополнительным, поскольку с
помощью отношения включает связан с прецедентом Оформление продажи. Обычно
дополнительные прецеденты являются абстрактными, а основные — конкретными.
520 Часть V. Третья итерация фазы развития30.3. Отношение расширяетПредположим, что по некоторым причинам текст прецедента не должен изме¬
няться (как минимум, существенно). Это может понадобиться в том случае, когда вне¬
сение огромного количества изменений сопряжено с множеством проблем или пре¬
цедент рассматривается как уже установившийся артефакт. Как же добавить к этому
прецеденту новый фрагмент, не изменяя исходного текста?Ответ на этот вопрос предоставляет взаимосвязь расширяет (extend). Основная
идея заключается в создании расширяющего или дополнительного прецедента, в
котором описывается, где и при каких условиях он расширяет некоторый основной
прецедент. Рассмотрим пример.Прецедент 1: Оформление продажи (основной прецедент)Точки расширения: особый покупатель, шаг 1. Платеж, шаг 7.Основной успешный сценарий1. Покупатель подходит с выбранными товарами к терминалу POS-системы, чтобы оплатить
покупку.7. Покупатель оплачивает покупку, и система обрабатывает этот платеж.Прецедент 15: Обработка платежа с помощью призового сертификата
(расширяющий прецедент)Переключатель: покупатель хочет оплатить покупку с использованием призового сертификата.Точки расширения: платеж при оформлении продажи.Уровень: подчиненный прецедентОсновной успешный сценарий1. Покупатель передает кассиру призовой сертификат.2. Кассир вводит идентификатор призового сертификата.В этих описаниях содержится пример использования отношения расширяет.
Обратите внимание на использование раздела “Точки расширения”, а также на то,
что расширяющий прецедент инициируется при выполнении некоторого условия.
Точки расширения представляют собой метки в описании основного прецедента, в
которых содержится ссылка на расширяющий прецедент. Поэтому нумерацию шагов
основного прецедента можно без проблем модифицировать, никак при этом не вли¬
яя на расширяющий прецедент.Иногда точка расширения указывается в следующей простой форме: в любой мо¬
мент прецедента X. Это особенно характерно для систем с множеством асинхронных
событий, таких как текстовый процессор (“сейчас будет выполнена проверка орфо¬
графии”, “сейчас будет выполнен поиск в тезаурусе”) или системы управления ядер-
ным реактором. Однако обратите внимание на то, что для описания процесса об-
Глава 30. Взаимосвязь прецедентов 521работки асинхронного события можно использовать также и отношение включает.
Взаимосвязь расширяет предоставляет дополнительную возможность в том случае,
когда основной прецедент нельзя модифицировать.Следует отметить, что отличительной особенностью взаимосвязи расширяет явля¬
ется то, что в основном прецеденте (Оформление продажи) не содержится ссылки на
расширяющий прецедент (Обработка платежа с использованием призового сер¬
тификата). Следовательно, этот прецедент не определяет и не управляет условиями,
при которых инициируется расширяющий прецедент. Прецедент Оформление про¬
дажи может так и завершиться, ничего не узнав о расширяющем прецеденте.Обратите внимание, что на дополнительный прецедент Обработка платежа с ис¬
пользованием призового сертификата можно ссылаться из прецедента Оформление
продажи и с помощью отношения включает. Зачастую это оказывается достаточно
полезно. Однако рассмотренный пример обусловлен тем, что прецедент Оформление
продажи нельзя модифицировать. Именно в этом случае удобнее воспользоваться от¬
ношением расширяет, а не включает.Кроме того, сценарий обработки платежа по призовому сертификату можно так¬
же добавить в качестве расширения в раздел “Расширения” прецедента Оформление
продажи. Этот подход позволяет избежать необходимости использования обеих вза¬
имосвязей, а также создания отдельного подчиненного прецедента.Простое обновление раздела “Расширения” обычно оказывается гораздо лучшим
решением, чем создание сложных отношений между прецедентами.В некоторых руководствах по написанию прецедентов рекомендуется применять
расширяющие прецеденты и отношение расширяет для моделирования в рамках
основного прецедента условных или необязательных процессов. Однако при этом
ничего не говорится о том, что описание таких процессов можно в виде текста прос¬
то поместить в раздел “Расширения” основного прецедента.Использование взаимосвязи расширяет на практике обусловлено невозможностью
модификации основного прецедента по каким-либо причинам.30.4. Отношение обобщаетОбсуждение отношения обобщает (generalize) выходит за рамки этой главы.
Однако следует упомянуть, что эксперты в области моделирования прецедентов пре¬
красно обходятся без этого дополнительного отношения, повышающего уровень
сложности прецедентов. Кроме того, в настоящий момент не существует хорошего
практического руководства по его использованию. Большинство специалистов едино¬
душны в своем мнении: добавление большого количества взаимосвязей прецедентов
приводит к непродуктивному использованию времени и проблемам в достижении
требуемого результата.30.5. Диаграммы прецедентовНа рис. 30.1 показан пример обозначений языка UML, используемых для отноше¬
ния включает. На этом рисунке показано лишь одно отношение, что, по мнению экс¬
пертов, позволяет обойтись без лишних сложностей.
522 Часть V. Третья итерация фазы развития:ает»POS-система NextGenОформление
продажи^ 1 ^/ *<включает»IVОформление
оплаты
наличнымОформление
оплаты по кредитной
карточке✓ «включает»основной прецедент
указывает на
включаемый
прецедентОформлениекредитаУправление
пользователя!«исполнитель»Службаавторизациикредитныхкарточек«исполнитель»Бухгалтерская
системаРис. 30.1. Использование отношения включает на диаграмме прецедентовОбозначения, используемые для взаимосвязи расширяет, представлены на
рис. 30.2.Оформление продажиТочки расширения:Платеж
Особый покупатель«расширяет»Сценарий оплаты покупки,
если покупатель предоставляет
призовой сертификатОформление платежа
с использованием
призового сертификатаОбозначения UML:1. Расширяющий
прецедент указывает на
основной прецедент2. Возле линии связи
можно указать условия и
точки расширенияРис. 30.2. Взаимосвязь расширяет
Глава31Дополнительные диаграммы
последовательностей
и описание операцийДобродетель - не лучшее искушение.
Джордж Бернард Шоу (George Bernard Shaw)Основная задача■ Определить диаграммы последовательностей и описания системных
операций для текущей итерации.ВведениеВ этой главе кратко рассматриваются новые диаграммы последовательностей
и описание системных операций для данной итерации разработки приложения
NextGen. Для игры “Монополия” никакие изменения не требуются.Что дальше?ДиаграммысостоянийUMLНа основе взаимосвязи прецедентов в данной главе анализируются дополнительные
диаграммы последовательностей и вносятся изменения в описание операций.
Следующая глава будет посвящена уточнению модели предметной области/ВзаимосвязьпрецедентовДополнительные
диаграммы
последовательностей
и описание операций
 • \Уточнениемоделипредметнойобласти—о—Архитектурныйанализ
524 Часть V. Третья итерация фазы развития31.1. Приложение NextGenНовые диаграммы последовательностейНа текущей итерации для реализации требований по обработке различных
видов платежей необходимо обеспечить взаимодействие с внешними система¬
ми. Следовательно, на системных диаграммах последовательностей (SSD — System
Sequence Diagram) нужно проиллюстрировать межсистемные взаимодействия, рас¬
сматривая каждую систему как черный ящик. На диаграммах SSD полезно изобразить
новые системные события, проясняющие следующие аспекты функционирования.■ Новые системные операции, которые должна поддерживать POS-система
NextGen.■ Обращения к другим системам и их отклики на запросы.Стандартное начало сценария прецедента Оформление продажиДиаграмма последовательностей для начала базового сценария включает систем¬
ные события makeNewSale, enterltem и endSale. Эти события всегда одинаковы,
независимо от типа оплаты (рис. 31.1).Сценарий прецедентаI I IРис. 31.1. Диаграмма SSD со стандартным началом сценарияОплата с использованием кредитной карточкиНа этой диаграмме последовательностей представлен процесс, происходящий по¬
сле стандартного начала прецедента Оформление продажи, когда для оплаты исполь¬
зуется кредитная карточка (рис. 31.2).
Глава 31. Дополнительные диаграммы последовательностей и описание операций 525| ' IIРис. 31.2. Диаграмма последовательностей для оплати по кредитной карточкеВ обоих случаях (при оплате покупки по кредитной карточке и чеком) на данной
итерации принимаются некоторые упрощения. В частности, предполагается, что сум¬
ма платежа в точности соответствует стоимости покупки, следовательно, параметр
“предлагаемая сумма” не требуется.Обратите внимание, что обращение к внешней службе авторизации CreditAutho-
rizationService моделируется как обычное синхронное сообщение с возвращае¬
мым значением. Это некая абстракция, которую можно будет реализовать с помощью
запроса SOAP на основе защищенного протокола HTTPS или любого другого меха¬
низма удаленного взаимодействия. Детали использования конкретного протокола
скрыты с помощью введенного на предыдущей итерации адаптера ресурса.Для системной операции make Credit Payment (и данного прецедента) предпола¬
гается, что информация о платежеспособности покупателя поступает от кредитной
карточки, поэтому в систему вводится номер кредитного счета и срок его действия
(с помощью устройства считывания информации с карточки). Хотя в будущем могут
появиться другие механизмы получения информации о платежеспособности покупа¬
теля, кредитные карточки с высокой степенью вероятности тоже будут поддержи¬
ваться.Напомним, что в случае подтверждения платежа от службы авторизации платежей
по кредитной карточке, этой службе необходимо знать идентификатор магазина, по¬
этому его нужно указать.Оплата чекомНа этой диаграмме последовательностей представлен процесс оплаты покупки че¬
ком (рис. 31.3).Согласно описанию прецедента, кассир должен ввести номер документа для про¬
верки личности покупателя.
526 Часть V. Третья итерация фазы развития• I IРис. 31.3. Диаграмма последовательностей для оплаты чекомНовые системные операцииНа данной итерации в систему необходимо добавить следующие новые системные
операции.■ makeCreditPayment■ makeCheckPaymentНа первой итерации была реализована только операция для оплаты наличными
под общим названием makePayment. Теперь, после появления различных типов пла¬
тежей, ее нужно переименовать в makeCashPayment.Описания новых системных операцийНапомним, что описания системных операций — это необязательные артефакты
(относящиеся к модели прецедентов). Иногда для получения информации о систем¬
ных операциях достаточно описания прецедентов. Однако описания системных опе¬
раций позволяют точно определить, что происходит в системе в терминах измене¬
ния состояния объектов из модели предметной области.Приведем описания новых системных операций.Описание 0П5: makeCreditPaymentОперация makeCreditPayment(creditAccountNumber, expiryDate)Ссылки Прецедент Оформление продажиПредусловия Текущая продажа существует, и все товары выбраны
Постусловия - Создан экземпляр pmt класса CreditPayment- Объект pmt связан с текущим объектом sale класса Sale- Создан экземпляр сс класса CreditCard; при этомсс.number = creditAccountNumber, сс.expiryDate = expiryDate- Объект с с связан с объектом pmt- Создан экземпляр срг класса CreditPaymentRequest- Объект pmt связан с объектом срг- Создан объект ге класса ReceivableEntry- Объект ге связан с внешним объектом AccountReceivable- Объект sale для завершения продажи связан с объектом store
Глава 31. Дополнительные диаграммы последовательностей и описание операций 527Обратите внимание на постусловие, определяющее создание нового экземпляра
счета ReceivableEntry среди бухгалтерских счетов. Хотя эта обязанность выходит
за рамки системы NextGen, это постусловие было введено для корректности реали¬
зации операции.Например, на этапе тестирования на основе этого постусловия нужно протести¬
ровать бухгалтерскую систему и проверить наличие нового экземпляра счета.Описание 0П6: makeCheckPaymentОперация makeCheckPayment (driversLicenceNumber)Ссылки Прецедент Оформление продажиПредусловия Текущая продажа существует, и все товары выбраны
Постусловия - Создан экземпляр pmt класса checkPayment- Объект pmt связан с текущим объектом Sale
-Создан экземпляр dl класса DriverLicense; при этомdl. number = driversLicenseNumber- Объект dl связан с объектом pmt- Создан экземпляр срг класса CheckPaymentRequest- Объект pmt связан с объектом срг- Объект sale для завершения продажи связан с объектом store
ГлаваУточнение модели
предметной областиНепродуманная классификация и некорректное обобщение—
это проклятие организованной жизни.Обобщение X. Дж. Велса (H.G. Wells)Основные задачи■ Уточнить модель предметной области с учетом обобщений, специа¬
лизации, классов ассоциаций, временных интервалов, композиции и
пакетов.■ Определить условия для отображения подклассов.ВведениеОбобщение и специализация — это базовые концепции процесса моделирования
предметной области, позволяющие сэкономить усилия при разработке такой модели.
Более того, иерархия концептуальных классов зачастую становится основой иерар¬
хии наследования программных классов, позволяющей снизить уровень дублирова¬
ния кода. Классы ассоциаций содержат информацию о связях, а временно интерва¬
лы включают важные сведения о времени ых ограничениях существования некоторых
бизнес-объектов. Пакеты — это способ организации крупномасштабных моделей
предметной области и их представление в виде комбинации небольших сущностей.
Большинство этих понятий рассматривается в контексте приложений NextGen, а
в конце главы кратко рассматривается уточненная модель предметной области для
игры “Монополия”.
530 Часть V. Третья итерация фазы развитияЧто дальше?ВзаимосвязьпрецедентовПосле рассмотрения дополнительных диаграмм последовательностей в данной
главе уточняется модель предметной области. В следующей главе рассматриваются
бопросы архитектурного анализа/Дополнительные
диаграммы
последова¬
тельностей
и описание
операций о Уточнениемоделипредметнойобласти\АрхитектурныйанализУточнениелогическойархитектуры32.1. Новые понятия модели предметной
области системы NextGenКак и на первой итерации, модель предметной области можно последовательно
дорабатывать с учетом требований для данной итерации. Понятия можно идентифи¬
цировать на основе списка категорий, применяя способ выделения существительных
из описания прецедентов. Для разработки робастной и разносторонней модели пред¬
метной области очень полезно ознакомиться с работами других авторов по этому во¬
просу, например [50]. Дело в том, что за пределами рассматриваемых тем этой книги
осталось множество важных особенностей процесса моделирования.Список категорий понятийВ табл. 32.1 приводятся некоторые важные понятия, рассматриваемые на данной
итерации.Таблица 32.1. Список категорий понятий
Категория ПримерыФизические или материальные объекты CreditCard (Кредитная карточка), Check (Чек)Транзакции CashPayment (Оплата наличными),CreditPayment (Оплата по кредитной карточке),
CheckPayment (Оплата чеком)Другие компьютеры или электромехани- CreditAuthorizationService
ческие системы, внешние по отношению (Служба авторизации кредитных карточек)
к данной системе CheckAuthorizationService(Служба авторизации чеков)Абстрактные понятияОрганизации CreditAuthorizationService(Служба авторизации кредитных карточек)
CheckAuthorizationService
(Служба авторизации чеков)Записи финансовой, трудовой, юридиче- AccountsReceivable (Система оплаты кредитов)
ской и другой деятельности
Глава 32. Уточнение модели предметной области 531Определение понятий из текстовых описанийКак уже отмечалось, процесс выделения понятий, включаемых в концептуальную
модель, нельзя назвать механическим. При выборе понятий необходимо использо¬
вать определенные абстракции, поскольку слова естественного языка могут иметь по
несколько значений и не всегда точно отражают смысл понятий. Однако выделение
существительных из текстовых описаний прецедентов — важный практический при¬
ем, применяемый при построении модели предметной области.На данной итерации реализуются сценарии прецедента Оформление продажи,
предусматривающие оплату чеком и по кредитной карточке. Поэтому существитель¬
ные будем выбирать из следующих расширений.Прецедент: Оформление продажиРасширения76. Оплата по кредитной карточке.1. Покупатель вводит информацию о своей кредитной карточке.2. Система отправляет запрос на авторизацию платежа внешней системе службы авто¬
ризации платежей и запрашивает подтверждение платежа.2а. Система определяет сбой при взаимодействии с внешней системой.1. Система сигнализирует об ошибке кассиру.2. Кассир просит покупателя изменить тип платежа.3. Система получает информацию о подтверждении платежа и сообщает об этом кассиру.За. Система получает информацию об отказе в выполнении платежа.1. Система сообщает об отказе кассиру.2. Кассир просит покупателя изменить тип платежа.4. Система регистрирует платеж по кредитной карточке, включая информацию о под¬
тверждении платежа.5. Система предоставляет механизм ввода подписи для платежа по кредитной карточке.6. Кассир просит покупателя предоставить подпись на оплату по кредитной карточке.
Покупатель вводит подпись.7в. Оплата чеком.1. Покупатель выписывает чек и передает его и свое удостоверение личности кассиру.2. Кассир записывает номер удостоверения личности на чеке, вводит его и отправляет
запрос на авторизацию оплаты чеком.3. Система генерирует запрос на оплату чеком и отправляет его внешней службе авто¬
ризации чеков.4. Система получает подтверждение на оплату чеком и сообщает об этом кассиру.5. Система регистрирует оплату чеком и выдает сообщение об успешной авторизации.
532 Часть V. Третья итерация фазы развитияТранзакции со службами авторизацииВ процессе выделения понятий из описаний прецедентов были идентифицирова¬
ны следующие понятия: CreditPaymentRequest (Запрос на оплату по кредитной кар¬
точке) и CreditApprovalReply (Подтверждение на оплату по кредитной карточке).
Их можно рассматривать как некий вид транзакций с внешними службами. Вообще,
такие транзакции полезно идентифицировать, поскольку связанные с ними процессы
и виды деятельности могут изменяться по ходу проектирования системы.Эти транзакции не должны представлять собой записи или последовательности
битов. Они лишь представляют абстрактное понятие транзакции, не зависящее от
способа ее реализации. Например, запрос на авторизацию платежа по кредитной
карточке может выполняться в процессе телефонных переговоров между людьми
или в процессе модемного соединения компьютеров.32.2. ОбобщениеПонятия CashPayment, CreditPayment и CheckPayment очень похожи. В этом
случае можно (и весьма полезно1) организовать их в иерархию обобщения-специализа-
ции классов (generalization-specialization class hierarchy) (рис. 32.1). В этой иерархии
суперкласс (superclass) Payment представляет более общее понятие, а его подклассы
(subclass) — более специализированное.Рис. 32.1. Иерархия “обобщения-специализация”Заметим, что термин “класс” в этой главе относится к концептуальным, а не про¬
граммным классам.Обобщение (generalization) — это процесс, связанный с идентификацией общности
между понятиями и определением суперкласса (основного понятия) и связанных с
ним подклассов (специализированных понятий). Обобщение предоставляет метод
систематизированной классификации понятий и их представления в виде иерархии
классов.Идентификация супер- и подклассов осуществляется с использованием модели
предметной области, поскольку она позволяет проанализировать понятия в более
обобщенных, переопределенных и абстрактных терминах. В результате выражения
становятся более емкими, улучшается понимание и уменьшается объем повторяемой
информации. И хотя в данный момент наше внимание сосредоточено на модели1 Далее в этой главе вы узнаете, для чего необходимо определять иерархии классов.
Глава 32. Уточнение модели предметной области 533предметной области, а не на модели проектирования, последующая реализация су¬
перклассов и подклассов в форме дерева наследования классов позволит значительно
улучшить качество программного кода.Таким образом, нужно придерживаться следующих рекомендаций.СоветИдентифицируйте суперклассы и подклассы предметной области, актуальные на
данном этапе исследования, и иллюстрируйте их в модели предметной области.Обозначения UML. В языке UML обобщающая взаимосвязь между элементами ото¬
бражается в виде большой треугольной стрелки, направленной от более специали¬
зированного элемента к более общему. Для каждого такого элемента можно либо
использовать отдельную стрелку, либо указать общую стрелку для всех специализиро¬
ванных элементов (рис. 32.2).Рис. 32.2. Иерархия классов с отдельными стрелками для каждого подкласса и общейстрелкой для всех подклассов32.3. Определение концептуальных
суперклассов и подклассовПоскольку очень важно идентифицировать концептуальные супер- и подклассы,
нужно четко понимать, что такое “обобщение”, “суперклассы” и “подклассы” в тер¬
минах определения классов и их множеств2. Все эти вопросы рассматриваются в по¬
следующих разделах.Обобщение и определение концептуальных классовЧто же собой представляет связь концептуального суперкласса с подклассом?ОпределениеОпределение концептуального суперкласса является более общим, чем определе¬ние подкласса.2 Расширение и сужение классов. Эти вопросы описаны в [94].
534 Часть V. Третья итерация фазы развитияНапример, рассмотрим суперкласс Payment и его подклассы (С ash Payment,
Credit Payment и т.д.). Предположим, что тип Payment определяет транзакцию, свя¬
занную с передачей денег (необязательно наличными) для приобретения товаров, и
что со всеми платежами связано количество передаваемых денег. Модель, соответ¬
ствующая этому описанию, представлена на рис. 32.3.Рис. 32.3. Иерархия класса PaymentКласс Credit Payment определяет передачу денег с использованием кредитной
карточки, которая должна быть авторизована. Определение класса Payment является
более общим, чем определение класса CreditPayment.Обобщение и множества классовКонцептуальные подклассы и суперклассы связаны в терминах элементов множе¬
ства.ОпределениеВсе элементы множества концептуальных подклассов являются элементами мно¬
жества их суперкласса.Например, в терминах теории множеств все элементы множества CreditPayment
являются также элементами множества Payment. На диаграмме Венна (Venn) это
можно представить так, как показано на рис. 32.4.Рис. 32.4. Диаграмма Венна (отношения множеств)
Глава 32. Уточнение модели предметной области 535Совместимость определений концептуальных подклассовПосле создания иерархии классов определитесь с суперклассами, с которыми бу¬
дут связаны созданные подклассы. Например, на рис. 32.5 показано, что у всех под¬
классов Payment имеется атрибут amount и все они связаны с объектом Sale.Рис. 32.5. Совместимость подклассовВсе подклассы должны содержать атрибут amount и быть связаны с объектом
Sale. Это правило совместимости с определением суперкласса называется правилом
100% (100% Rule).Правило 100%100% определения суперкласса должно быть применено к подклассу. Подкласс
должен на 100% соответствовать своему суперклассу по следующим параметрам.■ Атрибуты■ АссоциацииСовместимость множеств концептуальных подклассовКонцептуальный подкласс должен быть элементом множества суперкласса. Так,
подкласс CreditPayment должен быть элементом множества Payment.Неформально это фраза означает, что подкласс является разновидностью (kind) су¬
перкласса. Подкласс CreditPayment является разновидностью класса Payment. Более
кратко, с учетом английского языка, связь “является” (is-a-kind-oj) названа is-a (это).Этот тип совместимости называется правилом Is-а (Is-а Rule).Правило Is-аВсе элементы множества подкласса должны быть элементами множества его су¬
перкласса.В обычном языке это правило можно проверить с помощью следующего выражения.
Подкласс — это (is-a) Суперкласс.Например, фраза Класс CreditPayment — это класс Payment имеет смысл и выра¬
жает совместимость элементов множеств.
536 Часть V. Третья итерация фазы развитияЧто такое корректный концептуальный подклассКак следует из предыдущих разделов, при построении модели предметной обла¬
сти для определения корректного подкласса применяйте следующие тесты3.СоветПотенциальный подкласс должен удовлетворять следующим правилам.■ Правило 100% (совместимость определения)■ Правило Is-a (совместимость элементов множеств)32.4. Когда нужно определять
концептуальный подклассВыше были рассмотрены правила, с помощью которых можно проверить, что
подкласс является корректным (правила 100% и Is-a). Однако когда нужно приступать
к определению подкласса? Введем сначала следующее определение. Разделение кон¬
цептуального класса (conceptual class partition) — это деление класса на непересека-
ющиеся подклассы или, в терминологии Оделла (Odell), типы [94]. Это определение
можно сформулировать также в виде следующего вопроса: “Когда нужно отображать
разделение класса?”.Например, в предметной области POS-системы понятие Customer можно коррек¬
тно разделить на подклассы MaleCustomer и FemaleCustomer. Однако следует ли ил¬
люстрировать это разделение в разрабатываемой модели (рис. 32.6)?MaleCustomerCustomerFemaleCustomerКорректные ^
подклассыОднако стоит ли
использовать такое
разделение?Рис. 32.6. Допустимое разделение концептуального
класса. Насколько оно полезно в рассматриваемой
предметной области ?Такое разделение является абсолютно бесполезным. Почему это именно так, вы
узнаете из следующего раздела.3 Такие имена правил были выбраны, скорее, из-за их мнемоники, а не для обеспечения
точности.
Глава 32. Уточнение модели предметной области 537В каких случаях класс нужно разделять на подклассыВот случаи, когда класс нужно разделять на подклассы.СоветСоздавайте подкласс суперкласса в следующих случаях.1. Подкласс имеет дополнительные атрибуты, интересующие разработчика.2. Подкласс имеет дополнительные ассоциации, интересующие разработчика.3. Подклассу соответствует понятие, управляемое, обрабатываемое, реагиру¬
ющее или используемое способом, отличным от способа, определенного
суперклассом или другими подклассами.4. Подкласс представляет понятие “живой” сущности (например, животное, ро¬
бот), поведение которой отлично от поведения, определяемого суперклассом
или другими подклассами.С учетом приведенных выше критериев, можно прийти к выводу, что класс
Customer разделять на подклассы MaleCustomer и FemaleCustomer не стоит, по¬
скольку у них отсутствуют дополнительные атрибуты или ассоциации, они не обра¬
батываются различными способами и их поведение в контексте рассматриваемой
системы ничем не отличается4.В табл. 32.2 приводится несколько примеров разделения классов из предметной
области платежей и других областей на основе приведенных выше критериев.Таблица 32.2. Примеры разделения суперкласса
Критерий разделения на подклассы ПримерыПодкласс имеет дополнительные атри¬
буты, интересующие разработчикаПодкласс имеет дополнительные ассо¬
циации, интересующие разработчикаПодклассу соответствует понятие,
управляемое, обрабатываемое, реаги¬
рующее или используемое способом,
отличным от способа, определенного
супертипом или другими подтипамиПодкласс представляет понятие
“живой” сущности (например, жи¬
вотное, робот), поведение которой
отлично от поведения, определяе¬
мого суперклассом или другими под¬
классамиК предметной области платежей неприменим.Библиотека — класс Book (Книга), являясь подклассом клас¬
са LoanableResource (Предоставляемый ресурс), имеет
атрибут isbn (Код)Платежи — класс CreditPayment, являясь подклассом
класса Payment, ассоциирован С объектом CreditCard.
Библиотека — класс video, являясь подклассом классаLoanableResource, ассоциирован С объектом DirectorПлатежи — класс CreditCard, являясь подклассом класса
Payment, обрабатывается иначе, чем другие формы плате¬
жей в рамках собственного алгоритма авторизации.
Библиотека — класс Software, являясь подклассом класса
LoanableResource, перед получением требует внесения задаткаК предметной области платежей неприменим.К предметной области библиотеки неприменим.
Исследование рынка — класс MaleHuman (Мужчина) явля¬
ется подклассом класса Human (Человек). В магазине во
время приобретения покупок его поведение отлично от по¬
ведения класса FemaleHuman (Женщина)4 Мужчины и женщины ведут себя в магазине несколько по-разному. Однако эти отличия в
ракурсе требований для текущего прецедента являются несущественными, а именно этим кри¬
терием определяются рамки исследований.
538 Часть V. Третья итерация фазы развития32.5. Когда нужно определять
концептуальный суперклассОбобщение в рамках суперкласса обычно осуществляется в том случае, если вы¬
явлена общность между потенциальными подклассами. Для обобщения и создания
суперкласса применяйте следующие рекомендации.СоветСоздавайте суперкласс в следующих случаях.■ Потенциальные подклассы представляют собой вариации похожего понятия.■ Подклассы будут удовлетворять правилам 100% и Is-a.■ Все подклассы имеют один и тот же атрибут, который можно отнести к супер¬
классу.■ Все подклассы имеют одну и ту же ассоциацию, которую можно выделить и
связать с суперклассом.Эти критерии рассматриваются в последующих разделах.32.6. Иерархия концептуальных классов
POS-системы NextGenКлассы PaymentС помощью рассмотренных выше критериев полезно разделить класс Payment,
создав иерархию классов, представляющих различные виды платежей. Обоснование
создания такого суперкласса и подклассов представлено на рис. 32.7.Рис. 32.7. Обоснование выбора подклассов Payment
Глава 32. Уточнение модели предметной области 539Классы служб авторизацииСлужбы авторизации кредитных карточек и чеков являются вариантами одного и
того же понятия и имеют общие атрибуты. Соответствующие им классы можно пред¬
ставить в виде иерархии, показанной на рис. 32.8.Рис. 32.8. Обоснование иерархии классов AuthorizationServiceКлассы транзакций авторизацииМоделирование различных видов транзакций служб авторизации (запросов и от¬
кликов) — очень интересная задача. Вообще говоря, транзакции с внешними службами
весьма полезно отображать в модели предметной области, поскольку вокруг них скон¬
центрированы все виды деятельности и процессы. Такие транзакции очень важны.Нужно ли иллюстрировать каждый вид транзакции внешней службы? Ответ на
этот вопрос зависит от конкретной ситуации. Как уже упоминалось, модели пред¬
метной области нельзя рассматривать как корректные или ошибочные; скорее, они
полезны в большей или меньшей степени. Отображение всех видов транзакций, как
правило, оказывается совсем не лишним, поскольку каждый из типов связан с раз¬
личными понятиями, процессами и бизнес-правилами5.Еще одним интересным вопросом является выбор степени обобщения, которую
нужно использовать в модели. С учетом приведенных рассуждений, предположим,
что с каждой транзакцией связаны дата и время. Эти стандартные атрибуты, а также
желание выполнить максимально допустимое обобщение для этого семейства поня¬
тий, приведут к созданию класса PaymentAuthorizationTransaction.Однако насколько удачным будет обобщение типов откликов в рамках классов С
reditPaymentAuthorizationReply и CheckPaymentAuthorizationReply (рис. 32.9)
или достаточно более низкой степени обобщения, как показано на рис. 32.10?5 В моделях предметной области коммуникационных систем также полезно идентифициро¬
вать все типы сообщений.
540 Часть V. Третья итерация фазы развитияРис. 32.9. Одна из возможных иерархий классов транзакций с внешними службамиРис. 32.10. Альтернативная иерархия классов транзакций
Глава 32. Уточнение модели предметной области 541Иерархия классов, показанная на рис. 32.10, оказывается достаточно полезной в
смысле обобщения, поскольку дополнительные классы не приводят к повышению
ясности модели. Иерархия, представленная на рис. 32.9, приводит к излишнему дро¬
блению классов, которое не улучшает трактовку понятий и бизнес-правил, а только
усложняет модель. Повышение сложности нежелательно, если оно не дает каких-
либо других преимуществ.32.7. Абстрактные концептуальные классыВ модели предметной области полезно выделить абстрактные классы, поскольку
с их помощью можно уточнить правила предметной области и определить классы,
которые могут иметь конкретные экземпляры.ОпределениеЕсли каждый член класса С должен быть и членом его подкласса, то класс С назы¬
вается абстрактным концептуальным классом (abstract conceptual class).Предположим, что каждый экземпляр Payment должен быть также экземпляром
подкласса CreditPayment, CashPayment или ChackPayment. Если каждый член
класса Payment является также членом своего подкласса, то, по определению, класс
Payment является абстрактным.И наоборот, если могут существовать экземпляры Payment, не являющиеся экзем¬
плярами подкласса, то класс Payment не является абстрактным (рис. 32.11, а).В предметной области системы розничной торговли каждый экземпляр Payment
является экземпляром своего подкласса. На рис. 32.11, б классы представлены коррек¬
тно, и, таким образом, класс Payment является абстрактным.б)Рис. 32.11. Абстрактные концептуальные классы
542 Часть V. Третья итерация фазы развитияОбозначение абстрактных классов в UMLВ языке UML для отображения абстрактных классов существует собственное обо¬
значение — их имена отображаются курсивом (рис. 32.12).Рис. 32.12. Обозначение абстрактного классаСоветИдентифицируйте абстрактные классы и отображайте их в модели предметной
области, выделяя их имена курсивом.32.8. Моделирование изменения состоянийПредположим, что платеж может быть либо авторизованным, либо неавторизо¬
ванным и что состояние платежа нужно отобразить в модели предметной области
(на самом деле это может быть совсем не так, однако для обсуждения сделаем такое
предположение). Как показано на рис. 32.13, одним из возможных способов решения
этой задачи является определение подклассов класса Payment: UnauthorizedPayment
и Author izedPayment. Однако заметим, что платеж не остается в одном из этих со¬
стояний, а обычно переходит из неавторизованного состояния к авторизованному.
На основании приведенных рассуждений можно сформулировать следующие реко¬
мендации.СоветНе моделируйте состояния понятия X как его подклассы. Лучше выполните одно
из следующих действий.■ Определите иерархию состояний и ассоциируйте их с понятием X.■ Не отображайте состояния понятия в модели предметной области. Лучше про¬
иллюстрируйте их на диаграмме состояний.
Глава 32. Уточнение модели предметной области 543Рис. 32.13. Моделирование изменения состояний32.9. Иерархия классов и наследованиеПриведенные рассуждения об иерархии концептуальных классов не имеют ника¬
кого отношения к наследованию (inheritance), поскольку они относятся к модели пред¬
метной области и сущностям окружающего мира, а не к артефактам программного
обеспечения. В объектно-ориентированном языке программирования подкласс на¬
следует (inherits) атрибуты и определения операций своих суперклассов, создавая
тем самым иерархию программных классов (software class hierarchy). Наследование
(inheritance) — это программный механизм реализации совместимости подклассов с
определениями суперклассов. Таким образом, наследование находится за пределами
обсуждения модели предметной области, хотя при переходе к стадии проектирова¬
ния и реализации его значение возрастает.Иерархии концептуальных классов, созданные в данной главе, могут и не отобра¬
жаться в модели проектирования. Например, иерархия классов транзакций служб
авторизации может быть сужена или расширена в альтернативной иерархии про¬
граммных классов, в зависимости от используемого языка программирования и дру¬
гих факторов. Например, для уменьшения количества классов можно использовать
параметризованные классы языка C++.32.10. Классы ассоциацийНеобходимость задания классов ассоциаций определяется следующими требова¬
ниями предметной области.■ Каждому магазину служба авторизации присваивает торговый идентификатор
(merchant ID), используемый для его идентификации в процессе взаимодей¬
ствия.■ В запрос на авторизацию платежа, передаваемый из магазина службе авториза¬
ции, требуется включить торговый идентификатор магазина.
544 Часть V. Третья итерация фазы развития■ При работе с каждой службой магазин использует отдельный торговый иденти¬
фикатор.Где же в модели предметной области должен располагаться атрибут торгового
идентификатора?Помещать торговый идентификатор merchant ID в объект Store некорректно, по¬
скольку магазин может иметь несколько таких идентификаторов. Такая же ситуация
возникает при добавлении атрибута merchantID к объекту AuthorizationService
(рис. 32.14).StoreОба местоположенияк.AuthorizationServiceaddressmerchantIDпашеатрибута merchantIDнекорректны, поскольку
для каждого объекта он
может приниматьaddressmerchantIDnameнесколько значенийphoneNumberРис. 32.14. Неправильное использование атрибутаПриведенные выше рассуждения приводят к следующему принципу моделирования.СоветЕсли в модели предметной области экземпляр класса С может одновременно
иметь несколько значений для одного и того же атрибута А, то атрибут А не сле¬
дует помещать в класс С. Этот атрибут А следует отнести к другому классу, связан¬
ному с классом С, например, следующим образом.■ Объект Person может иметь несколько номеров телефона. Разместите номер
телефона в другом классе, таком как PhoneNumber или Contactlnformation, а
затем свяжите несколько экземпляров этого класса с объектом Person.Приведенная на рис. 32.15 модель соответствует сформулированному выше прин¬
ципу. Действительно, какое понятие делового мира формально отвечает за инфор¬
мацию, связанную с предоставлением услуг клиентам? Такими понятиями могут быть
Contract (Договор) и Account (Счет).Рис. 32.15. Первая попытка моделирования проблемы использования торгово¬
го идентификатора
Глава 32. Уточнение модели предметной области 545Тот факт, что оба объекта, Store и AuthorizationService, связаны с объектом
ServiceContract, наводит на мысль о существовании связи между этими двумя
объектами. Идентификатор me г chant ID можно рассматривать как атрибут, связан¬
ный с ассоциацией, соединяющей объекты Store и AuthorizationService.Это приводит к необходимости создания класса ассоциации (association class), в ко¬
торый можно добавить описание самой ассоциации. Класс ServiceContract можно
представить как класс ассоциации, связанный с ассоциацией между объектами Store
и AuthorizationService.В языке UML это иллюстрируется с помощью пунктирной линии, направ¬
ленной от ассоциации к классу ассоциации. Из рис. 32.16 видно, что класс
ServiceContract и его атрибуты связаны с ассоциацией между объектами Store и
AuthorizationService, а время его жизни зависит от этой связи.Рис. 32.16. Класс ассоциацииПри добавлении классов ассоциаций руководствуйтесь следующими рекоменда¬
циями.СоветНиже приведены критерии включения класса ассоциации в модель предметной
области.■ Атрибут связан с ассоциацией.■ Время жизни экземпляров класса ассоциации зависит от ассоциации.■ Между двумя понятиями существует ассоциация “многие ко многим”, и имеется
информация, связанная с самой ассоциацией.Существование ассоциации “многие ко многим” является стандартным признаком
того, что где-то в глубине подсознания зарождается полезный класс ассоциации. Если
вы обнаружите такую ассоциацию, то рассматривайте ее как класс ассоциации.На рис. 32.17 показаны несколько примеров классов ассоциаций.18 Зак. 3357
546 Часть V. Третья итерация фазы развитияРис. 32.17. Примеры классов ассоциаций32.11. Агрегация и композицияПервые несколько абзацев данного раздела повторяют материал из раздела 16.13.
Агрегация (aggregation) является слабоопределенным типом ассоциации в UML и ото¬
бражает самую общую зависимость типа “целое-часть” (как и многие другие ассоци¬
ации). Этот тип связи не имеет четко определенной семантики в UML, в отличие
от обычной ассоциации. Несмотря на это, данный термин введен в спецификации
UML. Зачем? В ответ процитируем Румбаха (одного из основоположников и ключе¬
вых разработчиков UML).“Несмотря на слабовыраженную семантику агрегации, все считают, что она не¬
обходима (по различным причинам). Думайте о ней как о плацебо в моделиро¬
вании”. [108]Рекомендация. Таким образом, следуя совету создателей UML, не следует исполь¬
зовать агрегацию при моделировании. Вместо этого по возможности стоит использо¬
вать композицию (composition).Композиция, так же известная как композитная агрегация (composite aggregation),
является строго определенным типом связи “целое-часть” и полезна в некоторых
моделях. Отношение композиции предполагает, что: 1) экземпляр части (например,
Square) в каждый момент времени принадлежит только одному целому (напри¬
мер, Board); 2) часть всегда принадлежит целому (пальцы не существуют отдельно
от руки); 3) целое ответственно за создание и удаление своих частей — либо через
самостоятельное создание/удаление, либо через взаимодействие с другими объекта¬
Глава 32. Уточнение модели предметной области 547ми. Следствием этих ограничений является то, что при уничтожении композитно¬
го объекта его части должны быть либо уничтожены, либо присоединены к другому
композитному объекту. Например, если реальная настольная игра “Монополия” уни¬
чтожается, то также уничтожаются и все ее клетки (с концептуальной точки зрения).
Аналогично, если программный объект Board уничтожается, то уничтожаются и про¬
граммные объекты Square.Как идентифицировать композициюВ некоторых случаях наличие отношения композиции очевидно. Обычно это име¬
ет место при рассмотрении физических устройств. Однако иногда выявить подобные
взаимоотношения гораздо сложнее.СоветЕсли вы не уверены в том, что между понятиями существует отношение компози¬ции, не включайте его в модель.Для принятия решения о необходимости иллюстрации отношения агрегации ру¬
ководствуйтесь следующим рекомендациями.СоветОтображайте отношения композиции в следующих случаях.■ Время жизни компонента ограниченно временем жизни составного объекта,
т.е. между частью и целым существует зависимость создания/удаления.■ В физическом или логическом агрегате очевидно наличие отношений “целое-
часть”.■ Некоторые свойства составного объекта распространяются и на его компонен¬
ты, например место их расположения.■ Операции, применяемые к композитному объекту, осуществляются и над его
частями, например разрушение, перемещение и запись.Преимущества отображения композицииИдентификация и иллюстрация композиции не очень важны. Их вполне можно
исключить из модели предметной области. Большинство (если не все) опытных спе¬
циалистов по моделированию считают отображение таких ассоциаций пустой тратой
времени.Все же стоит изучить и проиллюстрировать отношения композиции, поскольку
это может обеспечить ряд преимуществ, большинство из которых связано со стадией
генерации программного кода, а не со стадией построения модели предметной об¬
ласти. Именно поэтому отношения композиции можно, не опасаясь, пропустить при
моделировании предметной области. Вот эти преимущества.
548Часть V. Третья итерация фазы развития■ Проясняются ограничения предметной области, связанные с возможностью
существования частей независимо от целого. При композитной агрегации от¬
дельный компонент не может существовать вне времени жизни целого.• На стадии проектирования это будет оказывать влияние на зависимости соз¬
дания/удаления между целым и частями программных классов или элементов
базы данных (в терминах целостности ссылок и каскадного удаления).■ Отображение таких ассоциаций помогает идентифицировать создателя (состав¬
ной объект) в соответствии с шаблоном Creator.■ Операции, такие как копирование и удаление, применяемые к целому, зачастую
должны распространяться также на его части.Отношение композиции в модели предметной
области POS-системы NextGenВ предметной области POS-системы объекты SalesLineltem можно рассматри¬
вать как части составного объекта Sale. В целом, транзакции с отдельными товарами
можно рассматривать как части объединенной транзакции (рис. 32.18). Кроме того,
имеется зависимость создания/удаления экземпляров SalesLineltem объекта Sale,
поскольку время их жизни ограничено рамками времени жизни объекта Sale.Можно провести аналогичные рассуждения и сказать, что объект ProductCatalog
агрегирует экземпляры ProductDescription.Рис. 32.18. Отношение агрегации в приложении розничной торговлиДругих отношений, удовлетворяющих семантике “целое-часть” и зависимости созда¬
ния/удаления, нет, так что на помощь приходит принцип “не уверен, не используй”.32.12. Временные интервалы и цены товаров:
устранение ошибки первой итерацииНа первой итерации разработки объекты SalesLineltem были связаны с объекта¬
ми ProductDescription, содержащими информацию о цене товара. Для начальных
итераций разработки это было обусловленное упрощение, однако теперь пришло
время его детализировать. При этом возникает интересный (и актуальный) вопрос
о временных интервалах (time interval), связанных с корректностью информации, дей¬
ствием договоров и т.п.Если объект SalesLineltem всегда получает цену товара от объекта Product¬
Description, значит, при изменении цены товара объекты старых продаж будут свя¬
заны с новой ценой, что некорректно. Значит, необходимо различать цену товара на
момент его покупки и текущую цену.
Глава 32. Уточнение модели предметной области 549В зависимости от конкретных требований существует как минимум два спо¬
соба решения этой проблемы. Один состоит в простом копировании цены то¬
вара в элемент SalesLineltem и поддержке текущей цены с помощью объекта
ProductDescription.Второй, более робастный подход, состоит в связывании коллекции объектов
ProductPrice с объектом ProductDescription. При этом каждый экземпляр
ProductPrice обеспечивает цену товара, действующую на определенном временном
интервале. При таком подходе в организации будут храниться все когда-либо действо¬
вавшие цены (для отслеживания изменения цен на распродажах) и текущие цены то¬
варов (рис. 32.19). Более подробная информация о времениых интервалах содержит¬
ся в [30].Зачастую наряду с самими значениями приходится хранить коллекцию объектов,
представляющих времениые интервалы. Это относится к данным физических, меди¬
цинских и научных измерений, а также ко многим артефактам из области бухгалтер¬
ского учета и юриспруденции.Sale1SalesLineltemdateTime1..*quantityОписываетсяTimelntervalstart:timestamp
end:timeStamp1ProductCatalogProductDescriptionОпределяется
ценой изProductPrice1 1..*descriptionitemID1..*activelnterval:Timelnterval
price:MoneyРис. 32.19. Временные интервалы и цены товаров32.13. Имена ролей ассоциацийКаждый конец линии ассоциации — это роль, с которой связаны различные свой¬
ства, а именно:■ имя;■ кратность.Имя роли идентифицирует одну из сторон ассоциации и в идеале описывает роль,
которую играет данный объект. На рис. 32.20 представлены примеры имен ролей.Явное имя роли обычно не требуется. Оно бывает полезным, когда роль объек¬
та является неочевидной. Обычно имя роли начинается со строчного символа. Если
имя присутствует неявно, то предполагается, что используется имя роли по умолча¬
нию, соответствующее имени класса, первый символ которого заменен строчным эк¬
вивалентом.
550 Часть V. Третья итерация фазы развитияКак уже упоминалось в предыдущих главах, роли, используемые на диаграммах
классов на стадии проектирования, можно рассматривать как основу имени атрибута
на стадии генерации программного кода.Создает ►Рис. 32.20. Имена ролей32.14. Роли в форме понятий и роли,
представленные в ассоциацииВ модели предметной области роль из реального мира, в особенности роль, вы¬
полняемая человеком, может быть смоделирована несколькими способами, например
отдельным понятием или ролью в ассоциации6. Например, роли кассира и управля¬
ющего могут быть представлены как минимум двумя способами, проиллюстрирован¬
ными на рис. 32.21.Первый подход можно назвать представлением ролей в ассоциациях, а второй —
представлением ролей в виде понятий. Оба подхода имеют свои преимущества.Представление ролей в ассоциациях является достаточно привлекательным, по¬
скольку в этом случае можно точно указать, что один и тот же экземпляр может вы¬
полнять (в динамике) несколько ролей в различных ассоциациях. Автор как субъект
одновременно или последовательно может выполнять роль писателя, разработчика
программных систем, родителя и т.д.Однако роли, представленные в виде понятий, обеспечивают простоту и гибкость
при добавлении уникальных атрибутов, ассоциаций и дополнительной семантики.
Более того, реализовать роли в форме отдельных классов гораздо проще, поскольку
это соответствует ограничениям современных популярных объектно-ориентирован¬
ных языков программирования. Эти ограничения заключаются в том, что экземпляр
одного класса не может динамически видоизменяться и становиться экземпляром
другого класса или динамически менять свое поведение и атрибуты в зависимости от
изменения своей роли.6 Для простоты другие возможные способы моделирования (например, описанные в [50])
не рассматриваются.
Глава 32. Уточнение модели предметной области 551Роли в ассоциацияхНанимает на управленческую работу- 3 ^ Управляет ►Использование ролей вкачестве понятийРис. 32.21. Два способа моделирования ролей, которые играют люди32.15. Производные элементыПроизводный элемент может быть определен из других объектов. Чаще всего про¬
изводными элементами являются атрибуты и ассоциации. Когда следует отображать
производные элементы?СоветСтарайтесь не отображать производные элементы на диаграммах, поскольку
после их добавления модель усложняется, а новой информации не поступает.
Однако если отсутствие производных элементов затрудняет понимание, их сле¬
дует отображать.Например, атрибут total объекта Sale можно создать на основе информации, со¬
держащейся в объектах SalesLineltem и ProductDescription (рис. 32.22). В языке
UML этот факт отображается с помощью символа “/”, расположенного перед именем
элемента.Sale/total о Рис. 32.22. Производный атрибут
552 Часть V. Третья итерация фазы развитияВ качестве еще одного примера можно привести атрибут quantity объекта
SalesLineltem, который является производным от нескольких экземпляров Item,
связанных с этим объектом (рис. 32.23).Рис. 32.23. Производный атрибут, связанный со значением кратности32.16. Составные ассоциацииВ ассоциации можно использовать спецификатор (qualifier). С помощью значения
спецификатора различаются объекты множества, помещенного со стороны удален¬
ного конца линии ассоциации. Ассоциация со спецификатором называется составной
ассоциацией (qualified association).Например, в объекте ProductCatalog объекты ProductDescription могут разли¬
чаться идентификатором itemID, как показано на рис. 32.24, а. При использовании
спецификатора уменьшается кратность на втором конце линии ассоциации, которая
становится равной единице (рис. 32.24, б). В модели предметной области специфика¬
тор иллюстрирует, чем сущности предметной области одного класса отличаются друг
от друга. В модели предметной области спецификаторы нельзя использовать для от¬
ражения проектных решений, связанных с ключами поиска, хотя позднее они могут
оказаться полезными на диаграммах проектирования.Рис. 32.24. Составная ассоциацияОбычно спецификаторы не добавляют новой информации. Более того, при их
отображении можно слишком увлечься продумыванием проектного решения. Однако
при правильном использовании они могут способствовать улучшению понимания
предметной области и происходящих в ней процессов. Составная ассоциация между
Глава 32. Уточнение модели предметной области 553экземплярами ProductCatalog и ProductDescription является хорошим примером
использования спецификатора, который способствует лучшему пониманию изучае¬
мых процессов.32.17. Рефлексивные ассоциацииПонятие может быть ассоциировано с самим собой. Такая связь называется рефлек¬
сивной ассоциацией (reflexive association)7 (рис. 32.25).Person2родительребенокСоздает ►Рис. 32.25. Рефлексивная ассоциация32.18. Использование пакетов для организации
элементов модели предметной областиМодель предметной области быстро разрастается, поэтому связанные друг с дру¬
гом понятия желательно объединять в пакеты, обеспечивая тем самым возможность
параллельного анализа отдельных составляющих системы разными специалистами.
В следующих разделах будет проиллюстрирована структура пакетов в модели пред¬
метной области UP.Графически пакет представляется в виде папки с корешком (или вкладкой)
(рис. 32.26). В нем могут быть размещены подчиненные пакеты. Если в пакете име¬
ются элементы, то его имя указывается во вкладке, в противном случае — в центре
самой папки.DomainCoreElementsSalesРис. 32.26. Пакет UML7 В [94] приведено более строгое определение рефлексивной ассоциации.
554 Часть V. Третья итерация фазы развитияПринадлежность и ссылкиЭлемент может принадлежать (owned) пакету, в котором он определен, или на него
можно ссылаться (referenced) из других пакетов. В этом случае имя элемента пред¬
ставляется в формате ИмяПакета:: ИмяЭлемента (рис. 32.27). Класс, используемый в
других пакетах, может быть модифицирован с помощью новых ассоциаций, однако
все остальное должно остаться без изменений.Рис. 32.27. Ссылка на класс в пакетеЗависимости пакетовЕсли один элемент модели некоторым образом зависит от другого элемента, то
эту зависимость можно отобразить с помощью специальной связи, имеющей вид ли¬
нии со стрелкой. Зависимость между пакетами определяет, что элементы зависимого
пакета каким-либо образом “знают” об элементах целевого (target) пакета или связа¬
ны с ними.Например, если один пакет ссылается на элемент, принадлежащий другому пакету,
то между ними существует зависимость. Таким образом, пакет Sales зависит от паке¬
та Core Elements (рис. 32.28).DomainРис. 32.28. Зависимость пакетовКак выполнить декомпозицию модели предметной областиКаким образом классы, изображенные в модели предметной области, можно орга¬
низовать в пакеты? Используйте следующие рекомендации.
Глава 32. Уточнение модели предметной области 555СоветПри декомпозиции модели предметной области в один пакет помещайте элемен¬
ты, которые:■ располагаются в одной той же части предметной области, т.е. тесно взаимосвя¬
заны с каким-либо понятием или целью;■ находятся рядом в иерархии классов;■ участвуют в реализации одного и того же прецедента;■ явно связаны друг с другом.Зачастую бывает полезно все элементы, связанные с моделью предметной обла¬
сти, поместить в пакет Domain (Предметная область), а совместно используемые,
стандартные, базовые понятия определить в пакете Core Elements (Элементы ядра)
или Common Concepts (Базовые понятия).Пакеты модели предметной области POS-системыС учетом приведенных выше критериев пакеты модели предметной области POS-
системы можно организовать следующим образом (рис. 32.29).DomainРис. 32.29. Пакеты понятий предметной областиПакет Core/MiscВ пакет Core/Misc (рис. 32.30) желательно поместить широко используемые по¬
нятия, не относящиеся к другим пакетам. Далее этот пакет будем сокращенно назы¬
вать Core.На данной итерации с этим пакетом не связаны никакие новые понятия или ас¬
социации.Пакет PaymentsКак и на первой итерации, новые ассоциации определяются в соответствии с
критерием знания. Например, необходимо зафиксировать связь между объекта¬
ми CreditPayment и CreditCard. Некоторые ассоциации добавляются просто для
556 Часть V. Третья итерация фазы развитияясности, например, как ассоциация Идентифицирует покупателей для объекта
DriverLicense (рис. 32.31).Заметим, что отклик службы авторизации изображен в виде класса ассоциации
PaymentAuthorizationReply. Этот класс обязан своим существованием ассоциации
между платежом и службой его авторизации.Core/MiscРис. 32.30. Пакет CoreРис. 32.31. Пакет Payments
Глава 32. Уточнение модели предметной области 557Пакет ProductsНа данной итерации не появилось новых понятий и ассоциаций, за исключением
композитной агрегации (рис. 32.32).ProductsРис. 32.32. Пакет ProductsПакет SalesНа данной итерации не появилось новых понятий и ассоциаций, за исключением
композитной агрегации и производных атрибутов (рис. 32.33).Рис. 32.33. Пакет Sales
558 Часть V. Третья итерация фазы развитияПакет Authorization TransactionsНесмотря на общую рекомендацию об использовании осмысленных имен ассоци¬
аций, в некоторых случаях это условие может не выполняться, особенно если тип
ассоциации очевиден читателям. Это относится к ассоциациям между объектом пла¬
тежа и связанными с ним транзакциями. Имена таких ассоциаций можно опустить,
поскольку читатели диаграммы классов, представленной на рис. 32.34, легко опреде¬
лят тип этой ассоциации. Добавление имен только усложнит диаграмму.Возможно, эта диаграмма слишком детализирована? Как сказать. Реальным крите¬
рием является полезность диаграммы. Диаграмма, безусловно, корректна. Но повы¬
шает ли она уровень понимания процессов предметной области? Ответ на этот во¬
прос определяет степень детализации модели предметной области.AuthorizationTransactionsCore::
StoreПолучаетОтправляетPayments::
Authorization
ServiceОтправляетPaymentAuthorizationReplyPayments::
CreditPaymentPaymentAuthorizationTransactiondatetimeПолучаетPayment
Authorization -
RequestCreditPaymentCreditPaymentCheckPaymentCheckPaymentCreditPaymentCheckPaymentApprovalDenialApprovalDenialApprovalApprovalReplyReplyReplyReplyRequestRequestPayments::
CheckPaymentPuc. 32.34. Пакет Authorization Transactions
Глава 32. Уточнение модели предметной области 55932.19. Уточненная модель предметной
области для игры “Монополия”На рис. 32.35 показана уточненная модель предметной области для игры “Моно¬
полия”. В нее включены следующие элементы.■ Различные типы клеток (LotSquare и т.д.), отражающие реальные правила
игры и выполнение разных действий при попадании на различные клетки.■ Абстрактный суперкласс PropertySquare, в который включены атрибут price
и ассоциация Owns с конкретным объектом Player, присущие каждому конкрет¬
ному подклассу.Ъ'**-Y] itr»Ofvd,C*w*t>IPUv^r, Ъшр** хPiec*.— _— ’ ГS«g*rc ДC*s*Vs^ ТЧй.»*^чPuc. 32.35. Модель предметной области для третьей итерации разработки игры“Монополия”
Архитектурный анализОшибка, не связанная с клавиатурой, — нажмите <F1 > для продолжения.(Сообщение ранних версий PC BIOS)Основные задачи■ Создать таблицы архитектурных факторов.■ Создать технические описания архитектурных решений.ВведениеАрхитектурный анализ можно рассматривать как отдельный аспект анализа требо¬
ваний, относящихся к архитектуре системы. Например, на этапе архитектурного ана¬
лиза можно выявить необходимость обеспечения высокой защищенности системы.Задача архитектурного анализа сводится к выявлению факторов, определяющих
архитектуру системы, осознанию их приоритетов и возможности изменения, а также
решению связанных с этим проблем. На этом этапе важно осознать стоящие перед
разработчиками проблемы, взвесить все “за” и “против” различных решений, оце¬
нить степень влияния архитектурно важных факторов, проранжировать их в соот¬
ветствии с приоритетами, выработать проектные решения и оценить продукты сто¬
ронних производителей.Главная задача хорошего архитектора состоит в умении задать необходимые во¬
просы заказчику и выбрать адекватные средства их решения.
562 Часть V. Третья итерация фазы развитияЧто дальше? На основе уточнения моделй предметной области в данной главерассматриваются вопросы архитектурного анализа. Следующая глава посвящена
созданию многоуровневой архитектуры/\ДополнительныеПроектированиедиаграммы
последова¬
тельностей
и описание
операцийУточнениемоделипредметнойобластиАрхитектурныйанализУточнениелогическойархитектурыобъектов
на основе
шаблоновGoFОоооАрхитектурный анализ очень важен для решения следующих проблем.■ Снижение риска отсутствия важных элементов в проектном решении системы■ Снижение трудозатрат на реализацию низкоприоритетных моментов■ Обеспечение конкурентоспособности программного продуктаВ этой главе рассматриваются основные моменты и идеи архитектурного анализа
в контексте UP, т.е. здесь излагается метод, а не приводятся готовые советы и архи¬
тектурные решения, позволяющие повысить профессиональный уровень архитекто¬
ра системы. Это не справочник по архитектурным решениям, здесь рассматриваются
лишь вводные вопросы. Тем не менее, на примере рассматриваемого в данной книге
приложения NextGen приводятся конкретные образцы проектных решений.В UP архитектурный анализ должен начинаться до первой итерации разработки.
Пренебрежение этим принципом повышает риск неудачного завершения проекта.
Например, если не учитывать такие архитектурно важные факторы, как необходи¬
мость поддержки английского, китайского языков и хинди или обеспечение одновре¬
менного выполнения пятисот транзакций со средним временем отклика 1-2 секунды,
то разработка системы может быть сопряжена с большими трудностями или завер¬
шится неудачей.В то же время, поскольку UP является итеративным и эволюционным (а не ка¬
скадным) методом, то программирование и тестирование начинаются на ранних ите¬
рациях до завершения архитектурного анализа. Анализ и раннее программирование
в рамках такого подхода “идут рука об руку”.В данной книге вопросы архитектурного анализа рассматриваются одними из по¬
следних, поскольку сначала были изложены основные принципы объектно-ориенти¬
рованного анализа и проектирования.33.1. Когда нужно приступать
к архитектурному анализу33.2. Точки вариации и эволюцииСначала определим два типа точек изменения программной системы (которые
впервые упоминались при описании шаблона Protected Variations).
Глава 33. Архитектурный анализ 563■ Точка вариации (variation point) — точка ветвления в существующей на данный
момент системе или в требованиях к ней, например необходимость поддержки
нескольких интерфейсов для систем вычисления налоговых платежей.■ Точка эволюции (evolution point) — предполагаемая точка ветвления, которая
может возникнуть в будущем, однако не определяемая существующими требова¬
ниями.Как будет видно из дальнейшего изложения, точки вариации и эволюции являют¬
ся основными элементами архитектурного анализа.33.3. Архитектурный анализАрхитектурный анализ (architectural analysis) связан с определением и удовлетворе¬
нием нефункциональных (например, качественных) требований к системе в контек¬
сте функциональных требований.В контексте UP этот термин охватывает как исследование архитектуры (определе¬
ние), так и архитектурное проектирование (удовлетворение требований). Ниже при¬
ведены вопросы, решаемые на архитектурном уровне системы.■ Как требования надежности и защиты от сбоев влияют на проектное решение
системы?• Предположим, для каких удаленных служб POS-системы NextGen (например,
системы вычисления налоговых платежей) нужно обеспечить дублирование
на локальном компьютере? Почему? Будут ли функции локальной реализации
в точности соответствовать функциям удаленного прототипа или предусма¬
триваются какие-то отличия?■ Как стоимость лицензирования или покупки программных компонентов повли¬
яет на рентабельность всей системы?• Например, производитель прекрасного сервера базы данных Clueless требу¬
ет за свои услуги по 2% от каждой продажи, оформленной через POS-систе-
му NextGen, если их продукт входит в состав системы. Использование этого
продукта ускорит разработку, поскольку он обладает свойством робастности и
поддерживает многие важные службы, однако за отдельную плату. Нужно ли
в этом случае использовать менее робастный бесплатный сервер баз данных
YourSQL? Какой риск связан с таким решением? Насколько оно повлияет на
стоимость всей системы?■ Какое влияние на проектное решение окажут требования адаптируемости и бы¬
строй настройки?• Например, большинство торговых организаций хочет видеть в своих POS-при¬
ложениях различные вариации бизнес-правил. В чем состоят эти различия?
Как их лучше всего разработать? Каковы критерии выбора бизнес-правил,
подлежащих реализации в системе? Нужно ли программно настраивать при¬
ложение NextGen для каждого пользователя в отдельности или пользователи
сами могут сконфигурировать приложение? Нужно ли стремиться заработать
максимум денег за минимальное время?
564 Часть V. Третья итерация фазы развития■ Как отразятся на архитектуре имена брэндов?• Как известно, операционная система Windows ХР изначально имела другое
название, которое было изменено в последний момент по настоянию отдела
маркетинга. Очевидно, что название операционной системы отображается
на многих элементах интерфейса как в виде текста, так и в виде логотипа.
Поскольку архитекторы компании Microsoft не идентифицировали изме¬
нение имени как возможную точку эволюции, в данной ситуации было не¬
возможно применить шаблон Protected Variations (когда имя брэнда указано
лишь в одном месте в конфигурационном файле). Поэтому в последний мо¬
мент команда разработчиков была вынуждена просмотреть миллионы строк
исходного кода и файлов изображений и внести сотни изменений.• Аналогично, необходимо предусмотреть возможные изменения брэнда для
приложения NextGen.33.4. Общие методы архитектурного анализаСуществует несколько методов архитектурного анализа. Тем не менее, большин¬
ство из них предполагает выполнение в той или иной форме следующих шагов.1. Определить и проанализировать нефункциональные требования, оказывающие
влияние на архитектуру. Функциональные требования тоже нужно учитывать
(особенно в терминах возможности изменений), но основное внимание следу¬
ет уделить нефункциональным требованиям. В целом, эти требования можно
назвать архитектурными факторами (или архитектурными предпосылками).• Этот шаг можно рассматривать как элемент обычного анализа требований,
однако поскольку он выполняется в контексте идентификации влияния архи¬
тектуры и принятия высокоуровневых решений, то относится к архитектур¬
ному анализу.• В рамках UP некоторые из этих требований, в целом, определяются и описы¬
ваются в дополнительной спецификации или описании прецедентов на на¬
чальной стадии проекта. В процессе архитектурного анализа, выполняемого
на первых итерациях фазы развития, разработчики исследуют эти требова¬
ния более глубоко.2. Для требований, существенно затрагивающих архитектуру системы, проанали¬
зировать альтернативы и выработать приемлемые решения. Такие решения на¬
зываются архитектурными (architectural decision).• Решения могут варьироваться в широком диапазоне: от “отменить требова¬
ние” до “прекратить проект”, “привлечь экспертов” или “найти решение про¬
блемы”.Рассмотрим выполнение этих действий в контексте POS-системы NextGen. Для
простоты вопросы архитектурного развертывания, конфигурирования аппаратных
средств и операционной системы рассматриваться не будут.
Глава 33. Архитектурный анализ 56533.5. Определение и анализ архитектурных факторовАрхитектурные факторыВсе требования FURPS+ оказывают существенное влияние на архитектуру систе¬
мы. К таким требованиям относятся надежность, график реализации проекта, огра¬
ничения по стоимости или высокий уровень квалификации. Например, в условиях
плотного графика, недостаточного профессионализма и достаточного финансиро¬
вания лучше приобрести готовые компоненты, чем пытаться разрабатывать все эле¬
менты системы кустарным способом.Факторы, оказывающие наибольшее влияние на архитектуру системы, можно
определить в контексте высокоуровневых категорий функциональности, надежно¬
сти, производительности, простоты сопровождения и реализации, а также интер¬
фейса. Интересно, что эти требования являются качественными атрибутами системы
(например, надежность и производительность) и придают конкретной архитектуре
особый “дух”, не связанный с функциональными требованиями. Примерами таких
требований для системы NextGen являются поддержка внешних компонентов с их
специфическими интерфейсами и поддержка подключения различных наборов
бизнес-правил.В UP эти факторы получили название архитектурно значимых требований (architec¬
turally significant requirements). Термин “факторы” используется только для краткости
изложения.Многие технические и организационные факторы можно рассматривать как огра¬
ничения, накладываемые на проектное решение (например, система должна работать
под управлением операционной системы Linux, или необходимо приобрести компо¬
нент X).Сценарии реализации качественных требованийПри определении качественных требований в процессе анализа архитектурных
факторов рекомендуется разработать специальные сценарии1 с реальным выходом.
Недостаточно задекларировать, что “система будет легко расширяемой”, поскольку
за этой фразой не стоит никакого конкретного решения.2Зачастую требования обеспечения производительности системы и бесперебойной
работы в течение некоторого периода времени облекают в числовую форму. Однако
сценарии реализации качественных требований дополняют этот процесс и требуют
записи всех (или большинства) факторов в количественной форме.Сценарии реализации качественных требований — это краткие утверждения вида
<предпосылка><измеряемый результат>.1 Термин “сценарий реализации качественных требований” используется в различных мето¬
дах анализа архитектуры, разработанных Институтом программных технологий SEI (Software
Engineering Institute), например методе проектирования системы на основе архитектуры.2 Создатель первого итеративного и эволюционного процесса разработки Evo Том Гилб
(Tom Gilb) является также сторонником необходимости применения количественных показа¬
телей для оценки нефункциональных требований. Для этой цели он разработал структуриро¬
ванный язык описания требований PLanguage.
566 Часть V. Третья итерация фазы развитияРассмотрим несколько примеров.■ После завершения продажи отклик от внешней системы вычисления налого¬
вых платежей должен поступать в среднем через 2 секунды.■ После получения информации от специалистов по бета-тестированию ответ в виде
телефонного звонка должен быть отправлен в течение одного рабочего дня.Заметим, что термин “в среднем” требует дополнительного исследования архитек¬
тором системы. Сценарии реализации качественных требований не могут считать¬
ся корректными до момента их апробации. Заметим также, что временные оценки
в первом сценарии зависят от среды разработки и работы самого приложения. Этот
сценарий может успешно реализовываться только в среде разработки.Определение узких местИногда написание сценариев реализации качественных требований не приносит
желаемого результата. Написать детальную спецификацию очень легко, а реализо¬
вать ее очень трудно. Можно ли будет проверить выполнение этих требований? Как
и какими силами? К написанию подобных сценариев нужно подходить реалистично.
Не имеет смысла тратить силы на формулировку сложных задач, если ни одна из них
не будет решена или невозможно проверить качество решения.Определение узких мест связано с описанным ранее шаблоном Protected Variations.
Какие факторы играют главную роль при написании сценариев? Для системы резер¬
вирования авиабилетов действительно критичным является быстрое выполнение
транзакций в условиях высокой нагрузки на систему. Это требование обязательно
нужно реализовать и протестировать качество его реализации. Система NextGen
должна быть устойчивой к сбоям в работе внешних систем. Это достигается за счет
локальной репликации важных внешних служб. Выполнение этого свойства необ¬
ходимо проверить. Следовательно, сценарии реализации качественных требований
нужно составлять для критичных элементов системы, причем эти сценарии должны
быть проверяемыми.Описание архитектурных факторовВажной задачей архитектурного анализа является осознание влияния различных
факторов, расстановка их приоритетов и определение степени гибкости системы.
Поэтому в рамках многих методов разработки архитектуры (например, в [70]) предла¬
гается строить деревья или таблицы, формат которых зависит от конкретного метода.
В табл. 33.1 приведены факторы, описываемые в дополнительной спецификации.Обратите внимание на название категории — Надежность/восстанавливаемость.
Оно позаимствовано из модели FURPS+. Такая категоризация не является единствен¬
но возможной, но ее удобно использовать для группировки архитектурных факторов.
Например, некоторые категории, такие как надежность и производительность, в зна¬
чительной мере зависят от планов тестирования, поэтому их стоит сгруппировать в
одну категорию.Шкала измерения приоритетов и рисков (высокий/средний/низкий) является
весьма условной. Возможны и другие числовые и качественные описания. Их мож¬
но позаимствовать из различных архитектурных методов и стандартов, в частности
ISO 9126. Но стоит сделать одно предупреждение: если использование сложной схе¬
мы не приведет к ощутимому результату, то от такой схемы следует отказаться.
Глава 33. Архитектурный анализ 567Таблица 33.1. Пример таблицы факторов (в — высокий, с — средний)Фактор Мера качества ИзменяемостьВлияние фактора наПрио¬Сложностьи сценарии (текущая гибкостьзаинтересованных лиц,ритетили риски возможностьархитектуру или другиеэволюции)факторыНадежность/восстанавливаемостьЗащита отВ случае сбоя вТекущая гибкость —Сильное влияние на в ссбоев внеш¬работе внешнейиспользовать упро¬общее проектное ре¬них службслужбы при
нормальной ра¬щенные службы из
клиентской части при¬шениеботе магазиналожения.Торгующие орга¬нужно восста¬низации не любятновить соедине¬Эволюция: в течениесвязываться с нена¬ние в течение2 лет реалии могутдежными внешними1 минутыизмениться, что потре¬
бует полной локальной
репликации удаленных
служб. Вероятность та¬
кого изменения очень
высокаслужбами, что может
“оттолкнуть” их от си¬
стемы NextGenФакторы и артефакты UPВ UP основные функциональные требования определяются в описании прецеден¬
тов, которое наряду с дополнительной спецификацией и описанием видения систе¬
мы является базисом для построения таблицы факторов. В описании прецедентов
наиболее важны разделы “Специальные требования”, “Технологические вариации” и
“Открытые вопросы”. Архитектурные факторы в явной форме описываются также в
дополнительной спецификации.Некоторые факторы можно описать в процессе описания прецедентов. Однако
лучше разместить все архитектурные факторы в одном месте — в таблице факторов
дополнительной спецификации.Прецедент П1. Оформление продажиОсновной успешный сценарий (или основной процесс)1....Специальные требования- Отклик службы авторизации в 90% случаев приходит в течение 30 секунд.- Каким-то образом нужно обеспечить робастное восстановление информации в случае сбоя
при доступе к удаленным службам, таким как система складского учета.Список технологий и типов данныхЗа. Идентификатор товара считывается со штрихкода (при наличии последнего) лазерным ска¬
нером или вводится с клавиатуры.Открытые вопросы- Изучить законодательство по налогообложению.- Исследовать вопрос восстановления удаленных служб.
568 Часть V. Третья итерация фазы развития33.6. Пример: фрагмент таблицы архитектурных
факторов POS-системы NextGen*В табл. 33.2 приводятся некоторые архитектурные факторы, связанные с рассма¬
триваемым приложением.Таблица 33.2. Фрагмент таблицы факторов для архитектурного анализа приложения NextGenФакторМера качества
и сценарииИзменяемость
(текущая гибкость
и возможность
эволюции)Влияние фактора на
заинтересованных
лиц, архитектуру или
другие факторыПрио¬ритетСложность
или рискФакторМера качества
и сценарииИзменяемость (теку¬
щая гибкость и воз¬
можность эволюции)Влияние фактора на
заинтересованных
лиц, архитектуру или
другие факторыПрио¬ритетСложность
или рискНадежность/восстанавливаемостьЗащита от
сбоев внеш¬
них службВ случае сбоя в
работе внешней
службы при
нормальной ра¬
боте магазина
нужно восста¬
новить соеди¬
нение в течение
1 минутыЗащита от
сбоев уда¬
ленной базы
данныхТо жеТекущая гибкость —
использовать упро¬
щенные службы из
клиентской части при¬
ложения.Эволюция: в течение 2
лет реалии могут из¬
мениться, что потре¬
бует полной локальной
репликации удаленных
служб. Вероятность
такого изменения
очень высокаТекущая гибкость —
кешировать инфор¬
мацию о товарах в
клиентской части при¬
ложения до восстанов¬
ления соединения.Эволюция: в течение
3 лет устройства хра¬
нения информации и
средства репликации
станут дешевле и
эффективнее, что
приведет к полной
локальной репликации
удаленной базы дан¬
ных. Вероятность та¬
кого изменения очень
высокаСильное влияние на
общее проектное
решениеТоргующие орга¬
низации не любят
связываться с нена¬
дежными внешними
службами, что может
“оттолкнуть” их от
системы NextGenТо же
Глава 33. Архитектурный анализ 569Окончание табл. 33.1ФакторМера качестваИзменяемостьВлияние фактора наПрио¬Сложностьи сценарии(текущая гибкость
и возможность
эволюции)заинтересованных
лиц, архитектуру или
другие факторыритетили рискПоддержка/АдаптацияПоддержкаПри необ¬Текущая гибкость —Требуется для обе¬внмногих внеш¬ходимостиопределяется описа¬спечения конку¬них службинтеграция снием фактора.рентоспособности(бухгалтер¬новой внешнейЭволюция отсутствуетпродукта.ской систе¬службой должнаНезначительное вли¬мы, системызанять не болееяние на проектноевычисления10 человеко¬решениеналоговыхднейплатежей искладско¬го учета).Службымогут от¬личатьсяпри каждойустановкесистемыПоддержкаДобавлениеТекущая гибкость — вЗначительное вли¬нвбеспровод¬этой возможно¬настоящее время неяние с учетом воз¬ных терми¬сти не должнотребуется.можного измененияналов дляпотребоватьЭволюция: в течениемногих элементов.клиентовизменениятрех лет с высокой ве¬Например, можетPOS-систе¬проектного ре¬роятностью на рынкеизмениться опера¬мышения уровней
архитектуры,
не связанных с
интерфейсом
пользователяпоявятся беспровод¬
ные терминалы для
клиентов POS-системыционная система и
интерфейс пользо¬
вателяДругие факторы, в том числе правовыеНеобходи¬Правила вы¬Текущая гибкость —Несоблюдение зако¬внмость учетачисления нало¬правила вычислениянов влечет уголовнуютекущихговых платежейналоговых платежейответственность.правилдолжны бытьмогут изменяться дажеСистема зависит отвычисленияполностью со¬еженедельно.служб вычисленияналоговыхгласованы сЭволюция — отсут¬налоговых платежей.платежейаудитором.При изменении
налоговых ста¬
вок их нужно
учесть в систе¬
ме в указанный
правительством
срокствуетСобственную службу
написать очень труд¬
но, поскольку прави¬
ла сложны, постоян¬
но изменяются и их
нужно своевременно
отслеживать.Риск значительно
снижается при покуп¬
ке готового пакета
570 Часть V. Третья итерация фазы развития33.7. Определение архитектурных факторовМожно сказать, что наука архитектурного анализа сводится к выявлению архитек¬
турных факторов и составлению соответствующей таблицы. Профессионализм архитек¬
тора состоит в умении определить эти факторы с учетом затрат, взаимозависимостей
и приоритетов.Опытные архитекторы обладают обширными знаниями в разных областях (на¬
пример, знакомы с архитектурными стилями и шаблонами, технологиями, продукта¬
ми и тенденциями), на основе которых строят свои решения.Альтернативы, решения и мотивировкаНезависимо от принципов принятия архитектурных решений, практически все
методы проектирования архитектуры предполагают запись различных вариантов ар¬
хитектурных решений, факторов влияния и мотивов принятия решений.Такие записи называют техническим описанием (technical memo) [45], тематически¬
ми картами (issue card) [70], или описанием архитектурных подходов (архитектурными
предложениями). Глубина проработки материала в различных методах варьируется.
В некоторых методах такие документы являются лишь введением к следующим видам
деятельности.В UP технические описания помещаются в документ SAD.Важным элементом технического описания является мотивировка. Если разработ¬
чику или архитектору в будущем придется модифицировать систему,3 то на основе
этого раздела он сможет разобраться, почему было принято то или иное архитектур¬
ное решение. Это поможет ему принять решение по изменению системы.Мотивировка принятия решений и описание возможных альтернативных реше¬
ний помогут в будущем при модификации программы. Архитектор может воспользо¬
ваться этими вариантами или хотя бы ознакомиться с ними.Рассмотрим пример технического описания для POS-системы NextGen. Точный
формат описания значения не имеет. Нужно стремиться к простоте и записывать
важную информацию, которая может пригодиться в будущем.Техническое описание
Надежность - восстановление информации при отказе удаленной службы.
Идея решения. Обеспечить прозрачный поиск нужной службы, переход от удаленной
службы к локальной и осуществить частичную репликацию локальной службы.
Факторы• Робастное восстановление при выходе из строя удаленной службы (системы складского
учета, системы вычисления налоговых платежей).• Робастное восстановление информации при выходе из строя удаленной базы данных с
описаниями товаров.3 Или если по прошествии 4 недель архитектор системы забыл свой собственный ход мыслей!
Глава 33. Архитектурный анализ 571РешениеРеализовать шаблон Protected Variations (Защищенные вариации) для защиты от влияния ме¬
стоположения службы с помощью интерфейса адаптера и объекта ServicesFactory. По воз¬
можности обеспечить локальную реализацию удаленных служб с упрощенным и ограниченным
поведением. Например, локальная система вычисления налогов может использовать фиксиро¬
ванные ставки налогов. Локальная база данных товаров может представлять собой небольшой
буфер с информацией о наиболее популярных товарах. Информацию для обновления системы
складского учета можно хранить локально и передавать удаленной системе после восстановле¬
ния соединения.Вопросы конкретной реализации этих решений описаны в разделе технической документации
“Адаптация — службы сторонних производителей”, поскольку реализации удаленных служб мо¬
гут изменяться.Для обеспечения качественного восстановления соединения с удаленными службами ис¬
пользуйте объекты-посредники, проверяющие дееспособность каждой удаленной службы и
перенаправляющие по возможности информацию напрямую удаленным службам.МотивировкаВладельцы магазинов не желают прекращать торговлю. Следовательно, в системе NextGen нуж¬
но предусмотреть высокий уровень надежности и возможность восстановления информации при
сбоях. Тогда она станет очень привлекательным продуктом, поскольку конкурирующие системы
такой возможности не обеспечивают. Небольшой размер буфера объясняется ограниченностью
ресурсов клиентских компьютеров. Системы налоговых платежей не устанавливаются на каждом
клиентском компьютере из-за высокой стоимости лицензии и сложности настройки (настройка
каждого рабочего места занимает почти неделю). Такое проектное решение обеспечивает точку
эволюции системы, и в будущем можно будет поместить службу вычисления налоговых плате¬
жей на каждом клиентском компьютере.Неразрешенные вопросыОтсутствуют.Альтернативные решенияОбеспечение наивысшего уровня качества связи с удаленными службами авторизации платежей
по кредитной карточке для повышения надежности. Это возможно, но очень дорого.Заметим, что это иллюстративный пример. В одном техническом описании мож¬
но рассматривать целую группу факторов, а не только один.ПриоритетыРассмотрим иерархию задач, определяющих архитектурные решения.1. Негибкие ограничения, включая защищенность и соответствие законодатель¬
ству.• В POS-системе нужно корректно реализовать текущие политики вычисления
налоговых платежей.2. Экономические задачи.• Важнейшие элементы системы нужно реализовать к выставке в Гамбурге, ко¬
торая состоится через 18 месяцев.• Обеспечить свойства, необходимые для магазинов Европы (например, на¬
стройку бизнес-правил).
572 Часть V. Третья итерация фазы развития3. Другие задачи.• Это тоже экономические задачи, но сформулированные в неявной форме.
Например, “легкая расширяемость” подразумевает возможность выпуска си¬
стемы каждые 6 месяцев.Многие из этих задач в UP описываются в артефакте “Видение”. Их приоритеты
указываются в соответствующем столбце таблицы факторов.Отличительной особенностью принятия решений на этом высоком уровне (по
сравнению с низкоуровневым объектным проектированием) является рассмотрение
множества важнейших задач в комплексе. Причем в процессе принятия технических
решений главную роль играют экономические задачи. Рассмотрим еще один пример.Техническое описание
Соответствие правил вычисления налоговых платежей законодательным нормам.
Идея решения. Приобрести отдельный компонент для вычисления налоговых платежей.
Факторы• Применение действующих правил вычисления налоговых платежей.РешениеПриобрести систему вычисления налоговых платежей с соответствующей лицензией и регуляр¬
но получать обновления. Заметим, что на разных клиентских компьютерах можно использовать
разные системы вычисления налоговых платежей.МотивировкаТакое решение корректно, требует минимальных затрат на поддержку и облегчает труд разра¬
ботчиков. Готовые продукты стоят дорого, однако альтернативные решения неприемлемы.Неразрешенные вопросыКакие продукты имеются на рынке и какими свойствами они обладают?Альтернативные решенияМожно разработать компонент самостоятельно. Однако это займет много времени, обойдется
дорого и потребует дополнительных усилий разработчиков. При этом в “доморощенной” систе¬
ме возможны ошибки.Приоритеты и точки эволюции: недоработанные
и слишком детализированные проектные решенияЕще одной особенностью принятия архитектурных решений является выявление
точек эволюции (evolution points) — т.е. элементов, которые в будущем могут изменить¬
ся. Например, со временем могут появиться беспроводные терминалы для клиентов
системы NextGen. Это обстоятельство существенно влияет на архитектуру системы,
поскольку с появлением новых аппаратных средств могут измениться операционные
системы, интерфейс пользователя и т.д.На подготовку к будущим изменениям можно затратить очень много денег. Если
когда-нибудь окажется, что эти затраты были напрасны, то архитектурные “упражне¬
ния” станут слишком дорогим удовольствием. Такая ситуация является результатом
слишком детализированной проработки. Заметим, что прогнозирование дает очень
ненадежные результаты, поэтому не стоит закладывать в архитектуру системы слиш¬
Глава 33. Архитектурный анализ 573ком много элементов “на будущее”. Даже если впоследствии прогнозы оправдаются,
систему, возможно, все равно придется дорабатывать.Конечно, в системе нужно предусмотреть решение основных возможных проблем
(в свое время такой проблемой была “Проблема 2000”). На ее решение необходимо
затратить средства, поскольку недоработка обернется слишком большими затратами
в будущем.Профессионализм архитектора состоит в правильной расстановке приоритетов
и выборе наилучшего способа вложения средств для защиты от последующих из¬
менений.Чтобы решить, насколько серьезно нужно готовиться к возможным изменениям
в будущем, необходимо взвесить возможные сценарии развития событий. Насколько
потребуется изменить проектное решение и код? Каких затрат это потребует?
Возможно, при ближайшем рассмотрении сложнейшая проблема окажется легко
устранимой в течение нескольких человеко-недель.Здесь уместно снова привести цитату, приписываемую Нильсу Бору: “Прогнози¬
рование — это очень сложная задача, особенно если оно касается будущего”.Основные принципы проектирования архитектурыОсновные принципы проектирования, рассматриваемые в этой книге, в равной
степени применимы к крупномасштабному архитектурному уровню. К ним относятся
следующие.■ Низкая степень связывания■ Высокое зацепление■ Защита от вариаций (интерфейсы, перенаправления и т.д.)Однако архитектурные элементы рассматриваются в более крупном масштабе.
Здесь обеспечивается низкая степень связывания приложений, подсистем и процес¬
сов, а не отдельных объектов.Более того, на архитектурном уровне существует больше различных механизмов
обеспечения качества разработки. В качестве примера рассмотрим следующее опи¬
сание.Техническое описание
Адаптация - службы сторонних производителей.
Идея решения. Реализовать шаблон Protected Variations с использованием интерфейсов
и адаптеров.
Факторы• Поддержка различных внешних служб, перечень которых может изменяться (систем авто¬
ризации платежей, вычисления налогов и т.д.).
574 Часть V. Третья итерация фазы развитияРешениеОбеспечить защиту от вариаций следующим образом. Проанализировать различные коммер¬
ческие продукты и разработать стандартные интерфейсы. Затем на основе шаблона Adapter
обеспечить перенаправление информации. Например, создать объект-адаптер ресурса, реали¬
зующий этот интерфейс и обеспечивающий взаимодействие с реальной системой вычисления
налоговых платежей. Вопросы обеспечения прозрачности такого решения рассмотрены в техни¬
ческом описании “Надежность — восстановление информации при отказе удаленной службы”.МотивировкаПростота. Это решение дешевле и быстрее, чем использование службы сообщений (см. раздел
“Альтернативные решения”). Службу сообщений нельзя использовать для прямого взаимодей¬
ствия со службой авторизации платежей.Неразрешенные вопросыНе будет ли минимальный общий интерфейс слишком ограниченным?Альтернативные решенияМожно реализовать перенаправление с использованием службы сообщений или подписки (ре¬
ализации JMS) между клиентским компьютером и системой вычисления налоговых платежей.
Однако это решение нельзя применять для авторизации платежей, оно слишком дорого и боль¬
ше подходит для доставки сообщений, а не для практических нужд приложения NextGen.Отсюда видно, что на архитектурном уровне расширяются возможные способы
защиты от вариаций. Зачастую они основаны на применении компонентов сторон¬
них производителей, таких как JMS (Java Messaging Service) или сервер EJB.Разделение функций и снижение влиянияЕще одним принципом архитектурного анализа является разделение функций раз¬
личных объектов. Этот принцип применим и для отдельных объектов, но наиболее
ярко проявляется в процессе анализа архитектуры.Существуют функции, относящиеся к приложению в целом, например, хранение
данных или обеспечение безопасности. Можно, конечно, спроектировать приложе¬
ние NextGen таким образом, чтобы каждый объект сам сохранял себя и взаимодей¬
ствовал с базой данных. Однако в этом случае уровни логики приложения и базы
данных будут слишком связаны между собой. Это же относится и к вопросам безопас¬
ности. Такие решения снижают уровень зацепления и повышают связывание.Разделение функций относится к целым подсистемам. Объекты логики приложе¬
ния должны реализовывать только логику приложения и ничего более. Подсистема
взаимодействия с базой данных должна выполнять только свои функции.Разделение функций подсистем обеспечивает низкое связывание и высокое за¬
цепление на архитектурном уровне. Эти принципы применимы и к отдельным объ¬
ектам и их обязанностям. Однако особо важное значение они имеют при проекти¬
ровании архитектуры приложения, поскольку здесь требуются более глобальные и
важные решения.Для разделения функций крупномасштабных компонентов существует несколько
общих приемов.1. Разделить элемент на отдельные части (например, подсистемы) и использовать
их службы.
Глава 33. Архитектурный анализ 575• Это самый общий подход. Например, в системе NextGen функции взаимо¬
действия с базой данных можно возложить на отдельную подсистему, доступ
к которой для других компонентов осуществляется через фасадный объект.
Многоуровневая архитектура приложения тоже иллюстрирует разделение
функций.2. Использовать объекты-декораторы.• Это еще один очень распространенный подход. Впервые он был использован
компанией Microsoft для службы Microsoft Transaction Service, а затем на сер¬
верах EJB. В рамках этого подхода некая функция (например, обеспечение
безопасности) реализуется через объект-декоратор, инкапсулирующий другие
объекты. В терминологии EJB объект-декоратор называется контейнером (con¬
tainer). Например, функцию обеспечения безопасности в системе NextGen
можно возложить на контейнер EJB.3. Применить аспектно-ориентированные технологии и посткомпиляторы.• Например, взаимодействие с базой данных таких классов, как Sale, мож¬
но обеспечить с помощью компонентов EJB. Характеристики класса Sale,
сохраняемые в базе данных, задаются в файле описания свойств. Затем
посткомпилятор (под которым понимается еще один компилятор, запуска¬
емый после “обычного” компилятора) добавляет необходимую поддержку
взаимодействия с базой данных для класса Sale или его подклассов (моди¬
фицируется только байт-код). Разработчик при этом продолжает работать
с исходным классом как с объектом уровня логики приложения. Можно ис¬
пользовать и аспектно-ориентированную технологию, например AspectJ
(www.aspectj.org), которая также поддерживает посткомпиляцию для обе¬
спечения общих функций приложения. При таких подходах в процессе раз¬
работки поддерживается видимость разделения функций.Архитектурные шаблоныПодробное описание архитектурных шаблонов и их применения к приложению
NextGen выходит за рамки задач этой книги. Остановимся лишь на нескольких мо¬
ментах.Наиболее общим шаблоном, обеспечивающим реализацию принципов низкого
связывания, высокого зацепления и разделения функций, является шаблон Layers,
согласно которому функции системы разбиваются на компоненты или уровни.Известно множество архитектурных шаблонов, и их количество постоянно рас¬
тет. Список полезной литературы по архитектурным решениям приводится в конце
этой главы.33.8. Выводы по архитектурному анализуВопросы выбора архитектуры связаны, в основном, с нефункциональными тре¬
бованиями и включают экономические или рыночные аспекты работы приложе¬
ния. При этом не нужно упускать из виду и функциональные требования (например,
оформление продажи). Именно в их контексте рассматриваются главные функции
приложения. Архитектурно значимым является выявление точек вариации.
576 Часть V. Третья итерация фазы развитияАрхитектурный уровень включает общесистемные крупномасштабные проблемы,
устранение которых требует принятия фундаментальных проектных решений. К та¬
ким проблемам относится, в частности, выбор сервера приложений.В процессе архитектурного анализа нужно учитывать взаимозависимость факто¬
ров. Например, повышение безопасности связано с производительностью и удоб¬
ством использования системы, большинство факторов связано с повышением стои¬
мости.В процессе архитектурного анализа нужно оценивать все возможные решения.
Опытный архитектор может предложить проектные решения, связанные с разра¬
боткой новых программных компонентов и покупкой готовых программ или аппа¬
ратных средств. Например, восстановление информации на удаленном сервере POS-
системы NextGen можно обеспечить за счет репликации и служб защиты от сбоев,
обеспечиваемых некоторыми операционными системами и аппаратными средствами.
Хороший архитектор должен знать о таких продуктах.Таким образом, в процессе архитектурного анализа нужно выявить крупномас¬
штабные проблемы и решить их.Архитектурный анализ связан с идентификацией и реализацией нефункциональ¬
ных (качественных) требований к приложению в контексте функциональных
требований.33.9. Итеративный архитектурный анализ в UPПроцесс UP является итеративным и эволюционным методом разработки, при ис¬
пользовании которого большое внимание уделяется архитектуре системы. В книгах
по архитектурному анализу зачастую рассматривается каскадный метод проектиро¬
вания архитектуры, выполняемый до начала стадии реализации. В контексте UP и
итеративной разработки такой анализ проводится на каждой итерации с учетом об¬
ратной связи и адаптации. Наиболее сложные элементы системы, связанные с самым
высоким риском, реализуются на ранних итерациях.Затем на основе обратной связи по мере углубления понимания проблемы они на¬
страиваются и модифицируются.В контексте UP архитектурные факторы описываются в дополнительной специ¬
фикации, а соответствующие архитектурные решения — в документе SAD (Software
Architecture Document), описывающем программную архитектуру. Поскольку процесс
UP не является каскадным, документ SAD создается не до начала написания про¬
граммного кода, а после стабилизации основных компонентов системы.Архитектурный анализ начинается на ранних стадиях разработки проекта, воз¬
можно, в процессе начальной фазы, а основные усилия нужно сконцентрировать на
стадии развития. Это высокоприоритетный и очень важный вид деятельности в рам¬
ках разработки программных систем.Архитектурная информация в артефактах UP■ Архитектурные факторы описываются в дополнительной спецификации, на¬
пример в виде таблицы.
Глава 33. Архитектурный анализ 577■ Архитектурные решения описываются в документе SAD. Туда заносятся техни¬
ческие описания и описания архитектурных представлений.Фазы разработкиНачало. Если непонятно, насколько технически реально удовлетворить архитек¬
турно значимые требования, можно реализовать проверку архитектурной концепции
(architectural proof-of-concept). В UP эта процедура называется архитектурным син¬
тезом (architectural synthesis). Она отличается от принятых в прежние времена про¬
граммных экспериментов, связанных с реализацией отдельных технических решений.
Архитектурный синтез позволяет проверить выполнимость архитектурно значимых
требований в комплексе.Развитие. Основная задача этой фазы — реализация наиболее сложных архитек¬
турных элементов, поэтому основные усилия прикладываются именно на этой ста¬
дии. К ее завершению должны быть составлены таблица факторов, технические опи¬
сания и документ SAD.Передача. Хотя в идеале все архитектурные решения должны быть реализованы
задолго до этой фазы, следует просмотреть документ SAD, сверить описанную в нем
архитектуру с реальной и удостовериться в корректности описания системы.Последующая эволюция системы. Перед переходом к разработке новых версий
системы следует еще раз оценить архитектурные факторы и решения. Например, ре¬
шение по использованию в версии 1.0 единственного экземпляра системы вычисле¬
ния налоговых платежей, вызванное в свое время соображениями экономии, может
быть пересмотрено, поскольку со временем такие системы могут подешеветь. Тогда
в последующих версиях системы можно использовать локальные службы вычисления
налоговых платежей.33.10. Дополнительная литератураПеречень литературы по архитектурным шаблонам и общим принципам создания
систем постоянно дополняется. Автор советует ознакомиться с работами [10, 17, 27,
28, 54]. Особое внимание стоит уделить книге [69]. Это полезное руководство, на¬
писанное опытным архитектором и менеджером, в котором делается акцент на эко¬
номических аспектах проектирования архитектуры. Автор делится своим опытом ре¬
шения важных проблем, которые редко описываются в книгах по архитектуре. Среди
них вопросы бизнес-моделирования, лицензирования и модификации программной
архитектуры.19 3ак. 3357
Уточнение логической
архитектурыАлкоголь и математика несовместимы.
Не пытайтесь брать производные в нетрезвом состоянии.Автор неизвестенОсновные задачи■ Проработать дополнительные вопросы логической архитектуры си¬
стемы в терминах уровней на основе шаблона Layers.■ Представить логическую архитектуру для данной итерации разработ¬
ки приложений.■ Применить шаблоны Facade, Observer и Controller в контексте архи¬
тектурных уровней.ВведениеВопросы логической архитектуры и принципов шаблона Layers впервые рассма¬
тривались в главе 13. В данной главе эти вопросы будут рассмотрены глубже.Что дальше?На основе архитектурного анализа в данной главе исследуются вопросы уточнения
логической архитектуры приложений. В следующей главе речь пойдето проектированию дополнительных объектов на основе шаблонов GoF/\Уточнениемоделипредметнойобластио АрхитектурныйанализУточнениелогическойархитектурыПроектирование
объектов
на основе
шаблонов GoF о Диаграммыпакетов
580 Часть V. Третья итерация фазы развития34.1. Пример: логическая архитектура
приложения NextGenНа рис. 34.1 показана многоуровневая логическая архитектура приложения
NextGen для данной итерации разработки.UIНе библиотеки ^
Java Swing, а
собственные
классы, основанные
на SwingProcessSaleFrameProcessSaleConsoleИспользуется ^
для быстрой
отладкиDomainTechnical ServicesРис. 34.1. Фрагмент логического представления уровней приложения NextGen
Глава 34. Уточнение логической архитектуры 581Обратите внимание на отсутствие уровня приложения на данной итерации раз¬
работки. Как будет видно дальше, этот уровень нужен не всегда.Поскольку процесс разработки является итеративным, то на первых итерациях
многоуровневая архитектура может быть очень простой, а затем постепенно услож¬
няться на этапе развития. Основной задачей стадии развития является формирова¬
ние базовой архитектуры (разработанной и реализованной), однако это не означает
выполнения фундаментальной работы по проектированию архитектуры перед нача¬
лом программирования системы. Логическая архитектура разрабатывается на началь¬
ных итерациях, а затем совершенствуется на стадии развития.Обратите внимание на наличие лишь нескольких типов данных на диаграмме па¬
кетов. Это объясняется не только соображениями экономии места, но и спецификой
архитектурного представления. В нем отображаются только важные элементы, отра¬
жающие основные идеи и архитектурно значимые аспекты. Документ, описывающий
архитектурное представление, призван “сказать” читателю: этот небольшой набор эле¬
ментов был выбран для реализации великих идей.К этой диаграмме можно добавить следующие комментарии.■ В пакетах есть и другие типы данных. Здесь показаны лишь наиболее важные
из них с точки зрения архитектуры системы.■ Уровень основания не отображен в этом представлении. Архитектор решил,
что он не несет интересной информации, хотя разработчикам придется моди¬
фицировать некоторые классы этого уровня, в частности разработать более со¬
вершенные утилиты работы со строками.■ Пока не используется отдельный уровень приложения. Обязанности по управ¬
лению сеансами выполняет объект Register. Архитектор добавит этот уровень
на более поздних итерациях, когда поведение системы усложнится за счет до¬
бавления альтернативных интерфейсов пользователя (таких как Web-браузер).Связывание уровней и пакетовВ логическое представление можно также включить диаграмму, иллюстрирующую
связывание уровней и пакетов. Фрагмент такой диаграммы показан на рис. 34.2.Применение UML■ Линии зависимостей можно использовать для обозначения связывания пакетов
и типов данных в этих пакетах. Обычные линии зависимостей используются
для отображения взаимосвязей общего вида, без указания типа связи (наследо¬
вания, видимости посредством атрибутов и т.д.).■ Линии связи могут соединять пакеты с другими пакетами или отдельными
классами, например пакет Sales с классом POSRuleEngineFacade или пакет
Domain с пакетом Log4 J. Последнее обозначение используется в том случае,
если конкретный зависимый тип данных не играет роли или пакет связан сразу
с несколькими типами данных из другого пакета.Диаграммы пакетов зачастую используются для сокрытия конкретных типов и кон¬
центрации внимания на взаимосвязи более крупных элементов системы (рис. 34.3).На самом деле на рис 34.3 показан самый типичный вид диаграммы логической
архитектуры в UML. На диаграмме пакетов обычно отображают от 5 до 20 пакетов и
взаимосвязи между ними.
582 Часть V. Третья итерация фазы развитияUISwingProcessSaleFrame/ \~7 Г“/ \/ \I \Рис. 34.2. Фрагмент диаграммы связывания пакетов
Глава 34. Уточнение логической архитектуры 583UISwingText4 1I /\ /
1 г—: /\ Domain ,—\\\| //—1 ^Sales siPricing/ ч
1 \V \
—1 ^\\//ServiceAccessPayments////111 ' V\\\.Inventory\чPOSRuleEngine\ /
У
' \\\Technical Services /
 L )—PersistenceifLog4J i 4 / '
N I ✓У 4IV rJessSOAPPuc. 34.3. Фрагмент диаграммы связывания пакетовСценарии взаимодействия уровней и пакетовНа диаграммах пакетов отображается статическая информация. Чтобы понять
динамику взаимодействия объектов между уровнями и пакетами, используются диа¬
граммы взаимодействия. В стиле “архитектурного представления”, скрывающего
безынтересные детали, на диаграммах взаимодействия между уровнями и пакетами
изображаются архитектурно значимые сценарии (architecturally significant scenarios)
(в смысле иллюстрации основных крупномасштабных идей проектного решения).Например, на рис. 34.4 показан фрагмент сценария Оформление продажи, где
основное внимание уделяется взаимодействию между уровнями и пакетами.
584 Часть V. Третья итерация фазы развитияОбозначение UML: полное имя Iдля указания принадлежности к пакетуОбозначение UML: Обратите внимание, что в UML
подсистему можно моделировать как объект.Это бывает полезным в том случае, когда нежелательно
или не нужно изображать детали функционирования
механизма Jess, а достаточно показать взаимодействие
с ним:Кассир:UI: :
Swing::
Process
SaleJFrame:Domain::
Sales::
Register:Domain:::TechPOSRule-Services::Engine::Persistence:::Domain::s:POSRule-Persistence-Products::Domain::EngineFacadeProductSales::FacadeCatalogSale«подсис¬
тема»
:Tech-
Services::
Jessenterltem
(id,qty)
 ►enterltem
(id,qty)
 © *1IIdesc= |
getProductj
Desc(id) ( ►!i imakeLineltem
\ (desc,qty)-4 1 desc=getObject(.
 1 lIonPropertyEveiat
(s, "sale.total" , total) 1 1—4—islnvalid
(lineltem,
sale) /, id)someJessCalls
(lineltem,sale)
 ...--■Oi Линии со стрелками определяют переходы между уровнями. Такая информация особенно важна
для тех, кому необходимо полное понимание системы. Данная диаграмма связана с логическим
представлением архитектуры (термин UP), поскольку акцентирует внимание на архитектурно
значимой информацииРис. 34.4. Архитектурно важная диаграмма взаимодействия
Применение UMLШ Тип в рамках пакета можно определить с помощью выражения <ИмяПакета>:
:<ИмяТипа>, например Domain::Sales::Register. Такое обозначение можно
использовать для привлечения внимания читателей к взаимосвязи между уров¬
нями в рамках диаграммы взаимодействия.
Глава 34. Уточнение логической архитектуры 585■ Обратите внимание на использование стереотипа «подсистема». В UML под¬
системой называют отдельную сущность, обладающую собственным поведением
и интерфейсом. Подсистему можно рассматривать как специальный вид пакета
или как объект, если нужно отразить взаимодействие между подсистемами (как
в данном случае). В UML вся система тоже считается подсистемой (корневой),
поэтому ее можно изображать в виде объекта на диаграмме взаимодействия (на¬
пример, на диаграмме последовательностей).Заметим, что на этой диаграмме опущены некоторые сообщения, в частности от¬
носящиеся ко взаимодействию с объектом Sale. Это сделано для того, чтобы подчер¬
кнуть архитектурно важные взаимодействия.34.2. Взаимодействия на основе шаблона LayersПри разработке архитектуры нужно принять два важных решения.1. Какие большие части можно выделить в системе?2. Как они взаимосвязаны?Если архитектурный шаблон Layers позволяет выделить большие части системы,
то шаблоны проектирования более низкого уровня, такие как Facade, Controller и
Observer, призваны определить взаимосвязи между пакетами. В следующем разделе рас¬
сматриваются шаблоны, определяющие взаимодействие между уровнями и пакетами.Простые пакеты или подсистемыНекоторые пакеты или уровни представляют собой не просто условные группы
объектов, а реальные подсистемы с собственным поведением и интерфейсом. Это
видно на следующем примере.■ Пакет Pricing не является подсистемой. Это просто набор объектов-фабрик
и стратегий, используемых при ценообразовании. Это же можно сказать и о
базовых пакетах типа java.util.■ Пакеты Persistence, POSRuleEngine и Jess являются подсистемами. Это от¬
дельные сущности с четко выделенными обязанностями.В UML подсистему можно изобразить с помощью стереотипа, как на рис. 34.5.Шаблон FacadeДля доступа к пакетам, представляющим подсистему, чаще всего используется ша¬
блон Facade из группы шаблонов GoF. То есть, для доступа к подсистеме определя¬
ется открытый фасадный объект, с которым взаимодействуют клиентские объекты.
Такими фасадными объектами для доступа к подсистеме правил и базе данных явля¬
ются объекты POSRuleEngineFacade и PersistenceFacade.За “фасадом” обычно скрыто большое количество низкоуровневых операций.
Открытыми являются лишь несколько высокоуровневых операций. Если низкоуров¬
невые операции будут открыты, то фасадный объект не будет обладать высоким за¬
цеплением. Более того, если фасадный объект будет распределенным или удаленным
(как компонент сеанса EJB или серверный объект RMI), то при удаленном взаимодей¬
586 Часть V. Третья итерация фазы развитияствии с его службами возникнут проблемы с производительностью, поскольку боль¬
шое количество удаленных обращений снижает производительность распределенной
системы.«подсистема»POSRuleEngineцНе подсистемаPOSRuleEngineFacade-е-Pricing«подсистема»PersistenceDBFacade«подсистема»
JessРис. 34.5. Стереотипы для подсистемыФасадный объект обычно не выполняет отдельных функций. Он лишь консолиди¬
рует и распределяет запросы к конкретным объектам подсистем, которые и обеспе¬
чивают нужную функциональность.Например, объект POSRuleEngineFacade обеспечивает оболочку и общую точку
входа для подсистемы правил POS-приложения. Реализация этих подсистем скрыта
от других пакетов за “фасадным объектом”. Допустим (это лишь одна из множества
реализаций), подсистема правил реализована на основе механизма Jess. Jess — это
подсистема, реализующая множество мелких операций (это довольно типично для
общих внешних подсистем). Однако интерфейс объекта POSRuleEngineFacade не
отражает низкоуровневые операции Jess. Он обеспечивает выполнение лишь не¬
скольких высокоуровневых операций, таких как islnvalid(lineltem, sale).Если в приложении выполняется лишь небольшое число системных операций, то
с верхним уровнем обычно взаимодействует лишь один объект уровня логики при¬
ложения. В то же время на уровне технических служб, включающем несколько под¬
систем, обычно содержится хотя бы один фасадный объект для связи каждой под¬
системы с более высокими уровнями (или несколько открытых объектов, если не ис¬
пользуется шаблон Facade) (рис. 34.6).Фасадные объекты сеансов и уровень приложенияЕсли приложение включает множество системных операций и поддерживает
большое число прецедентов, в нем обычно существует несколько объектов, обеспе¬
чивающих связь уровней интерфейса и объектов предметной области (в отличие от
ситуации, представленной на рис. 34.6).В текущей версии системы NextGen предусмотрен единственный объект Register,
выполняющий функции фасадного объекта для уровня предметной области (согласно
шаблону GRASP Controller).
Глава 34. Уточнение логической архитектуры 587Рис. 34.6. Интерфейсы связи с более высокими уровнямиОднако с ростом системы, реализацией новых прецедентов и системных опера¬
ций зачастую вводится новый уровень объектов (называемый уровнем приложения),
поддерживающих состояние сеанса для операций прецедентов, в котором каждый
экземпляр сеанса представляет сеанс работы с одним клиентом. Такие объекты на¬
зываются фасадными объектами сеансов. Они строятся в соответствии с шаблоном
Controller. На рис. 34.7 показан пример изменения архитектуры приложения NextGen
в результате создания уровня приложения и фасадных объектов сеанса.Шаблон ControllerШаблон Controller описывает типичное проектное решение (объекты-контролле¬
ры) для обработки в клиентской части приложения запросов системных операций,
поступающих от уровня интерфейса пользователя. Реализация шаблона Controller
представлена на рис 34.8.
588 Часть V. Третья итерация фазы развитияРис. 34.7. Фасадные объекты сеансов и уровень приложенияШаблон GRASP Controller"
предлагает стандартный
способ выбора объектов
для обработки запросов
системных операцийProcessSaleSessionFacademakeNewSaleenteritemРис. 34.8. Шаблон Controller
Глава 34. Уточнение логической архитектуры 589Системные операции и уровниНа диаграммах последовательностей изображают системные операции, а не пред¬
ставления объектов. На рис. 34.9 показаны системные операции, представляющие
собой запросы исполнителей, передаваемые с уровня интерфейса пользователя на
уровень приложения или предметной области.Рис. 34.9. Системные операции на диаграмме последовательностей в терминах уровней системыВзаимодействие с верхними уровнями
на основе шаблона ObserverШаблон Facade зачастую используется для взаимосвязи вышестоящих уровней с
нижними уровнями или для доступа к службам и другим подсистемам того же уровня.
Если же нижестоящим уровням приложения или предметной области необходимо
взаимодействовать с вышестоящим уровнем интерфейса пользователя, то обычно ис¬
пользуют шаблон Observer. При этом объекты уровня представления реализуют ин¬
терфейс, наподобие PropertyListener или AlarmListener. Эти объекты являют¬
ся подписчиками или слушателями для событий, инициируемых объектами нижних
уровней. Объекты нижних уровней напрямую передают сообщения объектам более
высокого уровня интерфейса пользователя, но связываются при этом только с объек¬
тами, реализующими интерфейс (например, PropertyListener), а не с конкретны¬
ми окнами GUI.
590 Часть V. Третья итерация фазы развитияЭта ситуация рассматривалась при описании шаблона Observer. Идея таких взаи¬
моотношений показана на рис. 34.10.Взаимодействие нижестоящих уровней с уровнем представления обычно *реализуется на основе шаблона Observer (Publish-Subscribe). Объект Sale
регистрирует подписчиков, являющихся объектами PropertyListener. Такие
объекты относятся к пользовательскому интерфейсу (например, JFrame Swing),
однако рассматриваются как объекты, реализующие интерфейс PropertyListenerРис. 34.10. Использование шаблона Observer для взаимодействия с уровнем
интерфейса пользователяСвязь уровнейВ большинстве многоуровневых приложений уровни связаны между собой не
столь жестко, как в семиуровневой модели сетевых протоколов OSI. В модели про¬
токолов существует строгое ограничение, предполагающее связь элементов уровня N
лишь со службами нижестоящего уровня N-1.Такой принцип очень редко используется в архитектуре информационных систем.
Здесь чаще применяется “прозрачная многоуровневая” архитектура [17], в которой
элементы каждого уровня связаны с несколькими другими уровнями.Рассмотрим связь уровней более подробно.■ Все вышестоящие уровни зависят от технических служб и базового уровня.• Например, в Java все уровни зависят от элементов пакета java.util.■ Объекты уровня предметной области зависят от уровня экономической инфра¬
структуры.
Глава 34. Уточнение логической архитектуры 591■ Объекты уровня представления обращаются к уровню приложения, который, в
свою очередь, обращается к уровню предметной области. При наличии уровня
приложения объекты уровня интерфейса не взаимодействуют напрямую с уров¬
нем предметной области.■ В однопоточных “настольных” приложениях программные объекты уровня
предметной области “видны” или передаются уровням представления, прило¬
жения и, несколько реже, объектам технических служб.• Допустим, к этому типу относится приложение NextGen. Тогда объекты Sale
и Payment могут быть “видимы” для объектов уровня GUI и передаваться в
подсистему взаимодействия с базой данных уровня технических служб.■ В распределенных системах объекты уровня предметной области обычно ре¬
плицируются (как объекты значений) и передаются на уровень представления.
В этом случае уровень предметной области размещается на сервере, а клиент¬
ские узлы получают копии данных с сервера.Не опасно ли связывание с базовым уровнем
и уровнем технических служб?Как указывалось при описании шаблонов GRASP Protected Variations и Low
Coupling, проблемой является не само связывание как таковое, а излишнее связы¬
вание с неустойчивыми объектами в точках вариации и эволюции. Вряд ли стоит
тратить время и деньги на попытки абстрагироваться от неизменяемых элементов
или элементов, изменение которых не повлечет за собой никаких последствий.
Например, при создании Java-приложения не имеет смысла скрывать доступ к библи¬
отекам Java. Высокая степень связывания с библиотеками Java не составляет пробле¬
мы, поскольку эти библиотеки достаточно устойчивы.34.3. Другие вопросы использования шаблона LayersПомимо описанных выше структурных проблем и вопросов взаимодействия, для
этого шаблона следует учесть еще некоторые моменты.Логическое представление архитектуры
и представление развертыванияАрхитектурные уровни приложения составляют логическое представление архи¬
тектуры. Такое представление не отражает обрабатываемые и обрабатывающие эле¬
менты. В зависимости от платформы, уровни приложения могут взаимодействовать в
рамках одного процесса на одном узле либо распределяться между многими компью¬
терами и процессами для крупномасштабных Web-приложений.Модель развертывания UP, отражающая логическую архитектуру и ее распреде¬
ление по разным процессам и узлам, существенно зависит от выбора программной и
аппаратной платформы, а также используемых каркасов приложений. Например, ар¬
хитектура развертывания зависит от того, будет использован модуль .NET или J2EE.Существует множество способов отражения логической архитектуры в модели
развертывания. Однако аспекты развертывания выходят за рамки рассматриваемых
здесь вопросов, поскольку они являются нетривиальными и зависят от выбора про¬
граммной платформы, в частности J2EE.
592 Часть V. Третья итерация фазы развитияДополнительный уровень приложенияЕсли в системе существует уровень приложения, то он содержит объекты, обеспе¬
чивающие управление состоянием сеанса клиентов, взаимодействие с уровнями пред¬
ставления и предметной области, а также управление потоками.Поток может управлять, например, порядком отображения окон и Web-страниц.В терминах шаблонов GRASP объекты-контроллеры, например фасадный контрол¬
лер прецедента, тоже относятся к этому уровню. В распределенных системах к этому
уровню относятся также компоненты, например EJB (и объекты сеансов в целом).В некоторых приложениях этот уровень не требуется. Он нужен при выполнении
одного или нескольких из следующих условий (этот список не является исчерпыва¬
ющим).■ В системе используется несколько интерфейсов пользователя (например, Web-
страницы и интерфейс Swing). Объекты уровня приложения могут выступать в
роли адаптеров, коллекционирующих и консолидирующих данные для различ¬
ных интерфейсов пользователя, а также в роли фасадных объектов, скрываю¬
щих доступ к уровню предметной области.■ Уровень приложения необходим в распределенных системах, где объекты уров¬
ня предметной области располагаются на одном узле, а интерфейс пользовате¬
ля — на другом. Он обычно необходим для отслеживания состояния сеанса.■ Объекты уровня предметной области не могут или не должны поддерживать
состояние сеанса.■ Существует определенный порядок выполнения приложения, например, задан¬
ный порядок отображения окон или Web-страниц.Нечеткая принадлежность к различным уровнямНекоторые элементы принадлежат строго к одному уровню. Так, класс Math от¬
носится к базовому уровню. Однако некоторые элементы сложно отнести к одному
конкретному уровню (технических служб или базовому, уровню предметной области
или экономической инфраструктуры), поскольку различие между этими уровнями ха¬
рактеризуется качественными показателями, такими как “высокий” — “низкий”, “кон¬
кретный” — “абстрактный”. Эти характеристики относятся к теории нечетких мно¬
жеств. Это нормальная ситуация, и строгое разграничение здесь требуется далеко
не всегда. Разработчики могут рассматривать уровень технических служб и базовый
уровень одновременно, назвав их уровнем инфраструктуры.1Рассмотрим следующие примеры.■ Допустим, Java-приложение разрабатывается на основе открытого каркаса реги¬
страции Log4J (являющегося частью проекта Jakarta). К какому уровню в этом
случае относится подсистема регистрации — к базовому или уровню техниче¬
ских служб? Log4J — это низкоуровневый маленький каркас общего назначения.
Его можно отнести и к техническим службам, и к базовым объектам.1 Заметим, что не существует общепринятой системы имен для разных уровней приложе¬
ния, поэтому имена уровней отражают общепринятые термины.
Глава 34. Уточнение логической архитектуры 593■ Предположим, при разработке Web-приложения используется каркас Struts про¬
екта Jakarta. Это относительно высокоуровневый большой специализирован¬
ный технический каркас. Его с большой долей достоверности можно отнести к
техническим службам и с меньшей — к базовому уровню.Однако то, что в одной системе считается высокоуровневой технической служ¬
бой, в другой может быть базовым элементом.И наконец, библиотеки для конкретных программных платформ не всегда от¬
носятся к низкоуровневым базовым службам. Например, в библиотеках .NET и
J2SE+J2EE содержатся относительно высокоуровневые функции, относящиеся к служ¬
бам имен и каталогов.Ограничения и рекомендации
по применению шаблона Layers■ В некоторых контекстах добавление новых уровней вызывает проблемы с про¬
изводительностью. Например, при добавлении уровней для абстракции и пере¬
направления в ресурсоемкую графическую игру вместо прямого доступа к компо¬
нентам графической платы может снизиться производительность приложения.■ Шаблон Layers является одним из нескольких базовых архитектурных шабло¬
нов. Он применим не ко всем приложениям. Например, вместо него можно ис¬
пользовать шаблоны Pipes (Конвейер) и Filters (Фильтры) [17]. Эти шаблоны
пригодятся в приложениях, выполняющих последовательные преобразования,
например трансформацию изображений в выбранном порядке. При этом, если
на высоком уровне архитектура всего приложения соответствует шаблону Pipes
или Filters, отдельные фильтры или конвейеры могут быть реализованы на базе
шаблона Layers.Применение шаблона Layers: экскурс в историюБольшинство современных объектно-ориентированных систем (от настольных
приложений до распределенных Web-систем на основе J2EE) строится на основе ша¬
блона Layers. Трудно найти систему, не основанную на этом шаблоне. Поэтому обра¬
тимся к истории.Виртуальные машины и операционные системыНачиная с 1960-х годов сформировалась ярко выраженная многоуровневая архи¬
тектура операционных систем, в которой нижние уровни инкапсулируют доступ к
физическим ресурсам и обработку ввода-вывода, а более высокие уровни обращаются
к этим службам. Эти принципы описаны в работах [47] и [48].До этого, в 1950-е годы, была предложена идея виртуальных машин с универсаль¬
ным машинным языком байт-кодов (например, UNCOL [41]). Предполагалось, что
приложения будут разрабатываться на более высоком уровне, чем уровень виртуаль¬
ной машины (и выполняться без перекомпиляции на различных платформах), кото¬
рый, в свою очередь, является надстройкой над операционной системой и машинны¬
ми ресурсами. Многоуровневая архитектура виртуальных машин была использована
Аланом Кеем (Alan Kay) в его персональной объектно-ориентированной компьютер-
594 Часть V. Третья итерация фазы развитияной системе Flex [78], а позднее (в 1972 году) в виртуальной машине Smalltalk [61],
которая стала праобразом более современных виртуальных машин, таких как Java
Virtual Machine.Информационные системы: классическая
трехуровневая архитектураТипичная архитектура информационных систем, включающая интерфейс пользо¬
вателя и хранение данных на постоянном носителе, называется трехуровневой архитек¬
турой (three-tier architecture) (рис. 34.11). Такая архитектура впервые была описана в
1970-х годах в [118]. Однако этот подход приобрел популярность лишь в середине
1990-х годов, возможно, благодаря выходу в свет книги [56], в которой предлагаются
решения проблем, связанных с двухуровневой архитектурой.Поэтому первая публикация, в которой упоминается этот термин, используется
довольно редко.При такой архитектуре приложение делится по вертикали на три уровня.1. Уровень интерфейса (Interface) — окна, отчеты и т.д.2. Уровень логики приложения (Application Logic) — задачи и правила управления
процессом.3. Уровень данных (Storage) — механизм постоянного хранения данных.УровеньпредставленияУровеньлогики Вычисление налогов А шгате^ей"приложенияУровеньданныхМагазинИдентификатор товараКоличествоIОплатитьВвод товараРис. 34.11. Классическая схема трехуровневой архитектуры
Глава 34. Уточнение логической архитектуры 595Неотъемлемой частью трехуровневой архитектуры является вынесение логики
приложения на отдельный уровень. Уровень интерфейса является относительно не¬
зависимым от выполнения основных задач приложения. Его окна или Web-страницы
лишь направляют запросы на средний уровень логики приложения, а средний уро¬
вень, в свою очередь, взаимодействует с самым нижним уровнем хранения данных.Иногда термин “трехуровневая архитектура” неверно трактуется как требование
развертывания системы на трех компьютерах. Однако он подразумевает лишь логи¬
ческое деление приложения. Число компьютеров, на которых размещается система,
при этом варьируется от 1 до 3 (рис. 34.12).Уровень р
представленияУровеньлогикиприложенияВычислениеналоговОбозначение и
UML: узел. Это
вычислительный
ресурс, например
компьютерСистема с классической
трехуровневой архитектурой,
развернутая на двух узлах:
“более толстый клиент”Уровеньпредставленияшяшт1//УровеньВычислениелогикиналоговприложения/Система с классической
трехуровневой архитектурой,
развернутая на трех узлах:
“более тонкий клиент”Рис. 34.12. Размещение трехуровневого приложения в виде двух физических архитектурЭта архитектура существенно отличается от двухуровневой архитектуры (two-tier
architecture), при которой логика приложения включается в определения окон гра¬
фического интерфейса. Объекты графического интерфейса взаимодействуют (счи¬
тывают и записывают информацию) непосредственно с базой данных, и отдельного
среднего уровня логики приложения не существует. Недостатком двухуровневой ар¬
хитектуры является невозможность представления логики приложения посредством
отдельных компонентов, обеспечивающих возможность повторного использования
объектов. Двухуровневая архитектура клиент/сервер приобрела особую популяр¬
ность с появлением таких средств, как Visual Basic и PowerBuilder.Преимуществом двухуровневой архитектуры (в некоторых случаях) становится
быстрота разработки. Однако ее использование вызывает множество проблем. Тем
не менее существуют простые приложения для обработки данных, для которых эта
архитектура достаточно удобна.
596 Часть V. Третья итерация фазы развитияСвязанные шаблоны■ Indirection (Перенаправление) — к двухуровневой архитектуре добавляется но¬
вый уровень перенаправления.■ Protected Variations (Защищенные вариации) — уровни защищены от влияния
конкретной реализации.■ Low Coupling (Слабое связывание) и High Cohesion (Высокое зацепление) —
уровни обеспечивают реализацию этих шаблонов.■ Применение этого шаблона к проектированию объектно-ориентированных ин¬
формационных систем описано в [50].Другое название шаблона LayersШаблон Layers также называют Layered Architecture (Многоуровневая архитекту¬
ра) [57,114].34.4. Принцип Model-View SeparationКак передавать окнам отображаемую информацию? Как правило, объекты интер¬
фейса отправляют сообщения специальным объектам с запросами на получение ин¬
формации, которую необходимо отобразить. Такая модель отображения изменений
называется моделью с использованием опросов (polling) или опрашиванием сверху (pull-
from-above).Однако иногда модели опросов оказывается недостаточно. Например, неэффек¬
тивно опрашивать тысячи объектов каждые несколько секунд в надежде выявить
одно или два изменения, которые необходимо отразить в интерфейсе. В такой си¬
туации предпочтительнее, чтобы изменившиеся объекты предметной области сами
взаимодействовали с окнами и инициировали отображение изменений. Типичные
ситуации такого вида встречаются в следующих случаях.■ В приложениях мониторинга, например в системах управления телекоммуника¬
ционными сетями.■ В приложениях моделирования с визуализацией результатов, например в систе¬
мах аэродинамического моделирования.В таких ситуациях требуется модель предоставления информации снизу (push-from-
below). Из-за ограничений шаблона Model-View Separation это приводит к непрямому
взаимодействию объектов с окнами, т.е. непрямому уведомлению об обновлении ин¬
формации нижнего уровня.Вот два возможных решения этой проблемы.1. Использование шаблона Observer, при котором на уровне представления создаем
ся объект, реализующий функции интерфейса (например, PropertyListener).2. Использование фасадного объекта для уровня представления. В этом слу¬
чае к уровню представления добавляется фасадный объект, получающий за¬
просы с нижних уровней приложения. В этом примере используется шаблон
Indirection (Перенаправление) для обеспечения принципа Protected Variations
(Защищенные вариации) от изменений GUI (рис. 34.13).
Глава 34. Уточнение логической архитектуры 597UIProcessSaleFrameFTUIFacadeO"QHe является классом Swing “
или пользовательского интерфейса.
Представляет собой простой объект,
реализующий дополнительный
уровень перенаправления
к объектам интерфейсаDomainRegisterSaleОбъекты UIFacade иногда I
используются при реализации
модели предоставления
информации снизуРис. 34.13. Использование объекта UIFacade уровня интерфейса пользователя для опрашива¬
ния сверху34.5. Дополнительная литератураМногоуровневой архитектуре приложений посвящено множество публикаций,
как печатных, так и электронных. Шаблоны для проектирования такой архитектуры
впервые предложены в книге [44], однако сама архитектура описана во многих рабо¬
тах начиная с 1960-х годов. Во втором томе приводятся новые шаблоны, относящиеся
к многоуровневой архитектуре. Шаблон Layers хорошо описан в книге [17] (том 1).
Новые проектные решения
на основе шаблонов GoFЧлены парламента меня дважды спрашивали: “Мистер Бэббидж, выдаст ли ваша
машина правильные ответы, если ввести в нее неверные данные?”Я не могу предста¬
вить, какая цепочка мыслей привела их к такому вопросу.Чарльз Бэббидж (Charles Babbage)Основная задача■ Применить шаблоны GoF и GRASP для проектирования и реализации
прецедентов.ВведениеВ этой главе рассматриваются проектные решения на основе шаблонов GoF и
GRASP для текущей итерации разработки обеих рассматриваемых в книге програм¬
мных систем. Для приложения NextGen реализуются требования обработки отказа
удаленных служб с помощью локальных служб, обслуживания аппарата с POS-систе¬
мой и авторизации платежей на основе шаблонов GoF. Для игры “Монополия” на
основе шаблонов GRASP проектируются сценарии приобретения собственности и
оплаты аренды.Что дальше?После уточнения логической архитектуры в данной главе рассматриваются вопросы
применения шаблонов GoF для создания дополнительных объектов. В следующей
главе речь пойдет о диаграммах пакетов/\АрхитектурныйанализУточнениелогическойархитектурыПроектирование
объектов
на основе
шаблонов GoF
 • ДиаграммыпакетовДиаграммы
развертывания
и компонентов
600 Часть V. Третья итерация фазы развития35.1. Пример: POS-система NextGenВ следующих разделах описывается применение шаблонов и базовых принципов
проектирования для реализации следующих требований третьей итерации разработ¬
ки системы NextGen.■ Обработки отказа удаленных служб с помощью локальных■ Локальное кеширование■ Поддержка дополнительных устройств для POS-системы, например различных
типов сканеров■ Обработка платежей по кредитной или дебетной карточке, а также оплата чеком35.2. Переход к локальным службам
и обеспечение локальной буферизацииТребования к приложению NextGen предусматривают защиту от отказов удален¬
ных служб, например временной недоступности базы данных.Сначала рассмотрим проектное решение, обеспечивающее обработку отказа и
восстановление информации о товарах. Затем исследуем доступ к бухгалтерской си¬
стеме, для обеспечения работоспособности которой предлагается несколько другая
стратегия.Напомним фрагмент технического описания.Техническое описание
Надежность - восстановление информации при отказе удаленной службы.
Идея решения. Обеспечить прозрачный поиск нужной службы, переход от удаленной
службы к локальной и осуществить частичную репликацию локальной службы.
Факторы• Робастное восстановление при выходе из строя удаленной службы (системы складского
учета, системы вычисления налоговых платежей).• Робастное восстановление информации при выходе из строя удаленной базы данных с
описаниями товаров.РешениеРеализовать шаблон Protected Variations (Защищенные вариации) для защиты от влияния ме¬
стоположения службы с помощью интерфейса адаптера и объекта ServicesFactory. По воз¬
можности обеспечить локальную реализацию удаленных служб с упрощенным и ограниченным
поведением. Например, локальная система вычисления налогов может использовать фиксиро¬
ванные ставки налогов. Локальная база данных товаров может представлять собой небольшой
буфер с информацией о наиболее популярных товарах. Информацию для обновления системы
складского учета можно хранить локально и передавать удаленной системе после восстановле¬
ния соединения.Вопросы конкретной реализации этих решений описаны в разделе технической документации
“Адаптация — службы сторонних производителей”, поскольку реализации удаленных служб мо¬
гут изменяться.
Глава 35. Новые проектные решения на основе шаблонов GoF 601Для обеспечения качественного восстановления соединения с удаленными службами ис¬
пользуйте объекты-посредники, проверяющие дееспособность каждой удаленной службы и
перенаправляющие по возможности информацию напрямую удаленным службам.МотивировкаВладельцы магазинов не желают прекращать торговлю. Следовательно, в системе NextGen нуж¬
но предусмотреть высокий уровень надежности и возможность восстановления информации при
сбоях. Тогда она станет очень привлекательным продуктом, поскольку конкурирующие системы
такой возможности не обеспечивают.Прежде чем приступать к реализации защиты от сбоев, заметим, что архитектор
(в данном случае автор) рекомендует использовать локальный буфер (базу данных на
локальном жестком диске в виде простого файла) объектов ProductDescription.
Это позволяет повысить производительность и надежность системы. Следовательно,
прежде чем обращаться к удаленной базе данных, нужно всегда выполнять поиск то¬
вара в этом буфере.Это можно легко реализовать на основе шаблонов Adapter и Factory.1. Объект-фабрика ServicesFactory всегда возвращает адаптер для локальной
службы информации о товарах.2. Локальный “адаптер” для товаров на самом деле не является адаптером для дру¬
гих компонентов, а сам выполняет обязанности локальной службы.3. Локальная служба инициализируется ссылкой на другой адаптер для реальной
удаленной службы.4. Если данные о товаре содержатся в локальном буфере, то они и возвращаются.
В противном случае запрос перенаправляется адаптеру внешней службы.Обратите внимание на двухуровневый буфер в клиентской части приложения.1. Расположенный в оперативной памяти объект ProductCatalog будет поддер¬
живать коллекцию (например, объект HashMap для Java) нескольких (например,
1000) объектов ProductDescription, содержащих информацию о товарах.
Размер коллекции можно настраивать в зависимости от объема оперативной
памяти компьютера.2. Локальные службы информации о товарах будут поддерживать более мощный
(расположенный на жестком диске) буфер с данными о большем количестве то¬
варов (занимающий от 1 до 100 Мбайт дискового пространства). Размер этого
буфера тоже можно настраивать в зависимости от конфигурации локального
компьютера. Этот буфер играет важную роль для защиты от сбоев, поскольку
не выходит из строя даже при сбоях в самом приложении NextGen.Такое проектное решение не приводит к необходимости переделки существую¬
щего кода — новый локальный объект службы можно добавить, не затрагивая объект
ProductCatalog (взаимодействующий со службой информации о товарах).Здесь не применялись новые шаблоны. Решение основано на шаблонах Adapter и
Factory.На рис. 35.1 показано описанное проектное решение, а на рис. 35.2 проиллюстри¬
рован процесс инициализации.
602 Часть V. Третья итерация фазы развития1«интерфейс»IProduc t sAdapt егgetDescription(itemID):ProductDescription Ж Рис. 35.1. Адаптеры для информации о товарахРис. 35.2. Инициализация службы информации о товарахНа рис. 35.3 показано исходное взаимодействие объекта-каталога со службой ин¬
формации о товарах.ProductCatalog
productsService:IProductAdapteraetDescriotion()->1
Глава 35. Новые проектные решения на основе шаблонов GoF 603Рис. 35.3. Начало взаимодействия объекта-каталога со службой информации о товарахЕсли в буфере локальной службы информация о товаре отсутствует, происходит
обращение к адаптеру внешней службы (рис. 35.4). Обратите внимание, что локаль¬
ная служба товаров кеширует объекты ProductDescription как обычную последова¬
тельность объектов.2[нет в файле]:Рис. 35.4. Продолжение взаимодействия со службой информации о товарахПри изменении архитектуры внешней службы (переходе от обычной базы данных
к новой Web-службе) потребуется изменить только конфигурацию объекта-фабрики
удаленных служб (рис. 35.5).2[нет в файле]:ps=getDescription(id):LocalProductsps=getDescription(id)remoteService—►—►BigWebServiceProductsAdapterРис. 35.5. Новые внешние службы не влияют на существующее проектное решениеДалее объект DBProductsAdapter будет взаимодействовать с подсистемой объек¬
тно-реляционного преобразования (рис. 35.6).
604 Часть V. Третья итерация фазы развитияПри взаимодействии с подсистемой объектно-реляционного преобразования нужно указывать ^
тип требуемого объекта и его идентификатор. Эта подсистема в определенной степени стандартна;
она не разрабатывалась специально для POS-приложения NextGen''Оps=getDescription(id):DBProducts1:ps=getObject(ProductDescription.class,id)rDBFacade—►Adapter ►Рис. 35.6. Взаимодействие с подсистемой базы данныхСтратегии кешированияРассмотрим возможные варианты загрузки оперативного буфера ProductCatalog
и файлового буфера LocalProducts. Для этого можно использовать пассивную ини¬
циализацию, при которой буферы заполняются постепенно по мере поступления
информации от внешних служб. Другой подход подразумевает активную инициали¬
зацию, при которой оба буфера заполняются в рамках прецедента Запуск системы.
Если разработчик еще не определился с выбором подхода и хочет поэксперименти¬
ровать с обоими, то для решения этой проблемы можно воспользоваться семейством
различных объектов CacheStrategy и шаблоном Strategy.Устаревший буферПоскольку цены на товары изменяются довольно часто, причем иногда просто
по прихоти менеджера магазина, значение цены в буфере может устареть. Это об¬
щая проблема репликации данных. Решение этой проблемы — добавление операции
удаленной службы, отслеживающей ежедневные изменения. Объект LocalProducts
каждые п минут может отправлять запрос и обновлять буфер.Потоки в UMLЕсли объект LocalProducts должен решать проблему поддержания актуального
состояния данных, то его можно сделать активным объектом (active object) — владель¬
цем процесса управления. Этот процесс может засыпать на п минут, просыпаться,
обеспечивать получение данных и снова засыпать. Для отображения процессов и
асинхронных вызовов в UML имеется специальное обозначение (рис. 35.7 и 35.8).35.3. Обработка отказовВ предыдущем разделе описан способ кэширования объектов ProductDescription
в отдельном файле клиентской части приложения. Это повышает производитель¬
ность системы и обеспечивает частичное решение проблемы защиты от сбоев внеш¬
ней службы информации о товарах. Поскольку в файле локального компьютера
можно хранить данные о 10000 товаров, то такой объем информации может удовлет¬
ворить большую часть запросов в случае отказа внешней службы.Но что делать, если внешняя служба не работает, а в локальном файле нужная
информация отсутствует? Допустим, в этом случае необходимо уведомить кассира о
необходимости ввести цену товара и его описание вручную либо отменить ввод ин¬
формации об этом товаре вообще.
Глава 35. Новые проектные решения на основе шаблонов GoF 605Обратите внимание, что активный объект Ъ
со своим собственным потоком выделяется
жирной линией. Свойство {активный} является
необязательным, однако его рекомендуется
использовать.рс:ProductCataloginitializeНапример, в Java активные объекты реализуют
интерфейс Runnable. Кроме того, для каждого
интерфейса используется отдельное условное
обозначение.Низкоуровневые детали взаимодействия
с объектом Thread на диаграмме
не отображаютсяpsa=getProductsAdaptjer ()createexternalServicp
DBProductsAdapter ( create(externalService)
 1 {active}
psa:LocalProducts-re¬run o
—I loop[всегда]I A:products=I getProductUpdates/..-OВ Java вызов метода м
run класса Thread или
интерфейса Runnable
рассматривается
как асинхронное
сообщение.В UML такие сообщения
изображаются с помощью
стрелки специального
вида. Обратите внимание,
что это изменение
появилось в UML
версии 1.4Если методы запускаются
в другом потоке, соответствующее
выражение на диаграмме
последовательностей UML может
начинаться с имени
или символьного обозначения
потока. Зтот символ применяется
для указания потока и является
необязательным, но позволяет
добиться дополнительного
визуального эффекта.Например, все сообщения,
обрабатываемые в потокеLocalProducts будут
помечаться символом а//это сообщение обрабатывается
//в своем собственном потоке
{всегда выполняется циклически:- "засыпает" на п минут- обновляет буфер}Рис. 35.7. Потоки и асинхронные сообщения в UML
606 Часть V. Третья итерация фазы развитияРис. 35.8. Обозначение активного классаЭто пример условия ошибки или сбоя, который можно использовать для описа¬
ния некоторых общих шаблонов обработки сбоев и исключений. Обработка ошибок
или исключений — отдельный вопрос, поэтому здесь мы сконцентрируемся лишь на
некоторых шаблонах, относящихся к данной проблеме. Сначала введем несколько
терминов.■ Повреждение (fault) — первопричина неправильного поведения.• Программист перепутал имя базы данных.■ Ошибка (error) — выявление сбоя в работающей системе. Ошибки определяют¬
ся (или нет).• При обращении к службе имен для получения ссылки на базу данных (с не¬
правильным именем) она сигнализирует об ошибке.■ Отказ (failure) — отказ в обслуживании, вызванный ошибкой.• Подсистема информации о товарах не отвечает.Генерирование исключенийСамый распространенный способ сигнализировать об отказе — генерирование ис¬
ключений.СоветИсключения чаще всего применяются для обработки отказов ресурсов (диска, па¬
мяти, отсутствия доступа к сети, базе данных или другим внешним службам).Исключение генерируется в подсистеме взаимодействия с базой данных (на са¬
мом деле в реализации JDBC для Java), когда впервые обнаруживается невозможность
использования внешней базы данных. При генерации исключения вызывается его
обработчик.1Допустим, сгенерировано исключение java.sql.SQLException (для Java). Нужно
ли передавать это исключение верхним уровням системы, вплоть до уровня представ¬
ления? Нет. Для обработки исключений используют следующий шаблон.1 Вопросы проверки исключений здесь не обсуждаются, поскольку она поддерживается не
во всех популярных объектно-ориентированных языках, например в C++, C# и Smalltalk про¬
верка отсутствует.
Глава 35. Новые проектные решения на основе шаблонов GoF 607Шаблон Convert Exceptions (Конвертирование исключений) [26]В рамках подсистемы избегайте дальнейшей передачи исключений, поступающих
от подсистем или служб более низкого уровня. Преобразуйте исключения низ¬
кого уровня в форму, соответствующую уровню данной подсистемы. Исключения
более высокого уровня обычно включают исключения более низких уровней и
добавляют информацию, делающую исключение контекстно-значимым для более
высокого уровня.Это рекомендация, а не жесткое правило.Термин “исключение” используется здесь в смысле генерируемой информации.
Этот шаблон известен также под названием Exception Abstraction (Абстрагиро¬
вание исключений) [105].Например, подсистема взаимодействия с базой данных перехватывает некоторое
исключение SQLException и (в предположении, что сама его не обрабатывает2) ге¬
нерирует новое исключение DBUnavailableException, содержащее SQLException.
Заметим, что интерфейс DBProductAdapter выступает в роли фасадного объекта для
логической подсистемы обеспечения информации о товарах. Поэтому на более высо¬
ком уровне DBProductAdapter перехватывает исключение DBUnavailableException
более низкого уровня и (в предположении, что сам его не обрабатывает) генери¬
рует новое исключение Product Inf oUnavailableExcept ion, включающее в себя
DBUnavailableException.Обратите внимание на имена исключений. Почему исключение названо
DBUnavailableException, а не, скажем, PersistenceSubsystemException? Это
объясняется следующим шаблоном.Шаблон Name The Problem Not The Thrower
(Использование имени проблемы, а не ее генератора) [64]Как именовать исключения? Нужно выбирать имена, описывающие саму пробле¬
му, а не ее генератор. Тогда программистам легче понять проблему и единообраз¬
но отразить ее суть во многих классах исключений (что невозможно при исполь¬
зовании имен генераторов исключений).Исключения в UMLСамое время перейти к обозначениям UML для генераторов3 и обработчиков ис¬
ключений.При обсуждении обозначений UML возникает два вопроса.1. Как отобразить классы, генерирующие и перехватывающие исключения, на
диаграмме классов?2. Как отобразить генерацию исключений на диаграмме взаимодействия?2 Желательно разрешать исключения на уровне, близком к уровню его генерации, однако
это достаточно трудная задача, поскольку способ обработки исключений обычно определяется
спецификой приложения.3 Официально в UML исключения “передаются”, однако термин “генерируются” является
более стандартным.
608 Часть V. Третья итерация фазы развитияОбозначения для диаграммы классов показаны на рис. 35.9.Обозначения UML. Для представления исключений можно воспользоваться несколькими
способами.1. Язык UML позволяет использовать для операций синтаксис любого другого языка, такогокак Java. Кроме того, некоторые CASE-средства с поддержкой UML позволяют явно представлять
операции с применением синтаксиса Java.Например,Object get(Key, Class) throws DBUnavailableException, Fatal Exception2. Предлагаемый по умолчанию синтаксис допускает применение “строки свойств” в качестве
последнего элементаput(Object, id) {throws = (DBUnavailableException, FatalException)}3. Некоторые CASE-средства с поддержкой UML позволяют задавать (в специальном диалоговом
окне) исключения, генерируемые операциямиPersistenceFacade..*usageStatistics : МарObject get(Key, Class) throws DBUnavailableException, FatalException
put(Key, Object) {throws = (DBUnavailableException, FatalException)}FatalException
DBUnava i1ableExcept i onИсключенияСгенерированные ■
исключения можно
перечислить
в отдельном разделе
с меткой “исключения”Рис. 35.9. Перехват и генерация исключений некоторым классомВ UML исключение является частным случаем сигналов, описывающих асинхрон¬
ное взаимодействие между объектами. Это означает, что на диаграмме взаимодей¬
ствия исключения изображаются как асинхронные сообщения.4На рис. 35.10 показано обозначение для исключений на примере преобразования
исключения SQLException в DBUnavailableException.В целом, для отображения исключений в UML существует специальное обозначе¬
ние, но оно используется очень редко.Это не значит, что следует забыть о приведенной выше информации об обработ¬
ке исключений. Совсем наоборот. На архитектурном уровне с самого начала следует
предусмотреть основные шаблоны, политики и способы взаимодействия объектов по
обработке исключений, поскольку на поздних стадиях разработки сделать это очень
сложно. Однако низкоуровневую обработку исключений многие разработчики остав¬
ляют на потом, до стадии программирования, а не построения диаграмм UML.4 Обратите внимание, что начиная с версии UML 1.4 изменилось обозначение для асин¬
хронного сообщения.
Глава 35. Новые проектные решения на основе шаблонов GoF 609Вспомните, что в UML 2 линия жизни может быть I
связана с интерфейсом. Это означает, что объект
относится к некоторому анонимному классу,
который реализует данный интерфейсОбозначения UML. яВсе асинхронные сообщения, включая исключения, отображаются
с помощью специальной стрелки.Исключения изображаются как сообщения с именем класса
Exception. Допускается указывать необязательный стереотип
«exception» или «signal» (поскольку исключение
представляет собой разновидность сигнала), если это улучшает
визуальное восприятие диаграммыОкончание линии ш
сообщения в данной точке
означает, что объектPersistenceFacade
перехватывает это
исключениеРис. 35.10. Исключения на диаграмме взаимодействияОбработка ошибокДо сих пор мы рассматривали одну сторону вопроса — генерацию исключений с
точки зрения преобразования исключений, их именования и отображения. Теперь
перейдем к задаче обработки исключений.Для этого чаще всего применяются два шаблона.Шаблон Centralized Error Logging (Централизованная регистрация ошибок) [105]Для централизованной регистрации ошибок используется единственный экзем¬
пляр, которому сообщается обо всех исключениях в системе. В распределенных
системах локальные объекты, соответствующие шаблону Singleton, взаимодей¬
ствуют с центральным журналом регистрации ошибок. Это дает следующие пре¬
имущества.■ Преемственность сообщений■ Гибкость в определении выходного потока и формата данныхЭтот шаблон известен также под именем Diagnostic Logger (Журнал диагностики)
[66].20 Зак. 3357
610 Часть V. Третья итерация фазы развитияЭто достаточно простой шаблон. Существует еще один.Шаблон Error Dialog (Диалоговое окно ошибок) [105]Для уведомления пользователя об ошибках используется стандартный независи¬
мый от приложения неграфический объект, соответствующий шаблону Singleton.
Он включает несколько объектов-окон графического интерфейса (модальное
диалоговое окно, текстовый консольный объект, звуковой сигнал или генератор
речи) и делегирует обязанность уведомления об ошибках объектам пользователь¬
ского интерфейса. Тогда выходное сообщение может передаваться и диалоговому
окну, и генератору голосового сообщения. Этот же объект уведомляет об ошибке
централизованный журнал регистрации ошибок. Соответствующие объекты ин¬
терфейса пользователя может генерировать объект-фабрика на основе систем¬
ных параметров. Такой подход дает следующие преимущества.■ Реализуется шаблон Protected Variations в смысле защиты от влияния измене¬
ний в механизме вывода.■ Поддерживается общий стиль отчета об ошибках. Например, этот объект мо¬
жет вызывать окна графического интерфейса для отображения сообщений об
ошибках.■ Обеспечивается централизованное управление общей стратегией уведомления
об ошибках.■ Минимальные потери производительности. При использовании “дорогостоя¬
щих” ресурсов, в частности диалогового окна, его можно скрыть и хранить в
буфере для последующего использования, а не создавать диалоговое окно при
возникновении каждой ошибки.Должны ли объекты интерфейса пользователя (например, ProcessSaleFrame)
обрабатывать ошибку путем перехвата исключения и уведомления пользователя? Для
приложений с небольшим количеством окон и простым способом навигации между
ними такой подход применим. Это относится и к приложению NextGen.Однако следует помнить, что при такой обработке ошибок часть “логики прило¬
жения” переносится на уровень пользовательского интерфейса. Об обработке оши¬
бок нужно уведомлять пользователей, это вполне логично, но этот процесс нужно
отслеживать. Это не проблема для приложений с простым графическим интерфей¬
сом и низкой вероятностью его изменения, однако это может вызвать проблемы в
дальнейшем. Допустим, решено заменить интерфейс Java Swing на каркас пользова¬
тельского интерфейса IBM Java MicroView. Тогда придется определить, где в интер¬
фейсе Swing задействована логика приложения, и перенести ее в версию MicroView.
По сравнению с заменой интерфейса пользователя эта задача может показаться не¬
значительной, однако при усложнении логики приложения она может превратиться
в проблему. Вообще, чем больше логики приложения передается на уровень пользо¬
вательского интерфейса, тем сложнее поддерживать систему.Для систем с множеством окон и сложными (возможно, даже изменяемыми) пе¬
реходами между ними существуют другие решения. Например, между уровнем пред¬
ставления и предметной областью можно добавить уровень приложения с одним или
несколькими контроллерами.
Глава 35. Новые проектные решения на основе шаблонов GoF 611Более того, можно добавить объект управления представлением [17, 58], содержа¬
щий ссылки на все открытые окна и обладающий информацией о переходах между
ними при реализации некоторого события (например, ошибки).Этот объект, по существу, представляет собой конечный автомат, инкапсулиру¬
ющий состояния (открытые окна) и переходы между ними на основе событий. Он
может считывать модель перехода состояний из внешнего файла, осуществляя нави¬
гацию на основе данных (не требующую изменения исходного кода). Он также может
закрывать окна приложения, сворачивать или упорядочивать их.При таком проектном решении контроллер уровня приложения может иметь
ссылку на этот объект управления представлением (тогда он будет связан с вышестоя¬
щим уровнем представления). Контроллер приложения может перехватывать исклю¬
чение и взаимодействовать с менеджером представления для уведомления пользова¬
теля (на основе шаблона Error Dialog). В этом случае обработка ошибок выносится за
пределы графического интерфейса.Детальное рассмотрение вопросов управления интерфейсом пользователя не
входит в задачи данной книги. Общее проектное решение на основе шаблона Error
Dialog показано на рис. 35.11.35.4. Взаимодействие с локальными службами
на основе шаблона Proxy (GoF)Взаимодействие с локальной службой информации о товарах было реализовано
за счет обращения к этой локальной службе перед обращением к внешней службе.
Однако такое решение применимо не всегда. Иногда сначала следует попытаться об¬
ратиться к внешней службе, а уже затем к ее локальной версии. Например, рассмо¬
трим вопрос передачи информации о продаже в бухгалтерскую систему. Эти сведения
нужно передать как можно скорее, чтобы в реальном времени отслеживать деятель¬
ность магазина.Для решения этой проблемы существует еще один шаблон GoF — Proxy (Объект-
посредник). Это простой шаблон, чаще всего используемый в виде Remote Proxy
(Удаленный объект-посредник). Например, в пакете RMI и спецификации CORBA
для доступа к удаленным объектам служб используется локальный клиентский объект
(называемый “опорным”). Этот опорный объект является локальным объектом-по¬
средником или представителем удаленного объекта.В приложении NextGen используется другой, отличный от Remote Proxy вариант
шаблона Proxy — Redirection Proxy (Посредник для перенаправления), известный так¬
же под именем Failover Proxy (Посредник для устранения проблем).Независимо от варианта, идея шаблона остается одинаковой. Отличия проявля¬
ются после вызова объекта-посредника.Объект-посредник — это объект, реализующий тот же интерфейс, что и основной
объект, содержащий ссылку на этот объект и применяемый для управления доступом
к нему. Общая структура объектов показана на рис. 35.12.
612 Часть V. Третья итерация фазы развитияРис. 35.11. Обработка исключения
Глава 35. Новые проектные решения на основе шаблонов GoF 613Client1 1
 >«interface»
ISubj ectlnterfacesubj ect:ISubj ectlnt^rfасеfoo ()doBar()p \ >1■к... любые действия
subject.foo()... любые действия
}Атрибут Ьsubjectреальноссылается наэкземпляробъекта-посредника,а не наэкземплярRealSubjectProxyrealSubj ect:ISubj ec£Interfacefoo() ОRealSubjectfoo ()1 Ц... предварителная обработка
realSubj ect.foo()... заключительная обработка
}Атрибут realSubj ect на самом деле будет
ссылаться на экземпляр RealSubjectЬРис. 35.12. Общая структура объектов шаблона ProxyШаблон ProxyКонтекст/ПроблемаПрямой доступ к объекту нежелателен или невозможен. Что делать?РешениеДобавить новый уровень перенаправления с искусственным объектом-посредни¬
ком, реализующим тот же интерфейс, что и основной объект, и делегировать ему
обязанность по управлению доступом к основному объекту.В соответствии с рассматриваемым примером приложения NextGen для обеспече¬
ния доступа к внешней бухгалтерской системе объект-посредник для перенаправле¬
ния используется следующим образом (рис. 35.13).1. Сообщение postSale передается объекту-посреднику, обрабатывающему его
как реальная внешняя бухгалтерская система.2. Если объекту-посреднику не удается установить соединение с внешней систе¬
мой (через адаптер), он перенаправляет сообщение postSale локальной служ¬
бе, хранящей информацию о продажах для последующей ее передачи внешней
системе (после восстановления связи).
614 Часть V. Третья итерация фазы развитияАтрибут accounting на самом
деле ссылается на экземплярAccount ingRedirect ionProxy... обработка платежа
if ( payment completed )
completeSaleHandling()}Registeraccounting:IAccountingAdapter+ makePayment(P - completeSaleHandling.fc)1-t—>|«interface»IAccountingAdapterpostReceivable(ReceivableEntry)
postSale( Sale )AccountingRedirectionProxyexternalAccounting:IAccountingAdapter
localAccounting:IAccountingAdapterpostReceivable(ReceivableEntry)
postSale(Sale) qSAPAccountingAdapterpostReceivable(ReceivableEntry)
postSale( Sale )LocalAccountingaccounting.postSale(currentSale)pbstReceivable(ReceivableEntry)
poVtSale(Sale) qexternalAccounting.postSale(sale)if ( externalAccounting fails )
localAccounting.postSale(sale)}{Сохранение данных о продаже
в локальном буфере (чтобы
впоследствии передать их
внешней службе)}ОРис. 35.13. Использование объекта-посредника для перенаправления информациив системе NextGenПрименение UML■ Обратите внимание, как на этой статической диаграмме показана последова¬
тельность взаимодействия (что позволяет избежать построения диаграммы вза¬
имодействия для отображения динамического поведения). Обычно лучше все
же использовать диаграммы взаимодействия, однако здесь показаны альтерна¬
тивные обозначения.■ Обратите внимание на маркеры открытой и закрытой областей видимости
(+, -) рядом с методами объекта Register. Если эти маркеры не указаны, зна¬
чит, область видимости не определена (а не задается по умолчанию). Тем не
Глава 35. Новые проектные решения на основе шаблонов GoF 615мёнее по общепринятому соглашению большинство читателей (и генераторы
кода CASE-средств) интерпретируют отсутствие маркера области видимости
как принадлежность атрибута или метода к закрытой области. На приведенной
диаграмме специально показано, что метод makePayment является открытым,
а метод completeSaleHandling— закрытым. Лишняя информация перегружа¬
ет диаграмму, поэтому желательно использовать на диаграммах общепринятые
обозначения.В заключение отметим, что объект-посредник — это внешний объект, выступаю¬
щий в качестве оболочки для внутреннего объекта и реализующий тот же интерфейс.
Клиентский объект (например, Register) не знает, что общается с посредником. Для
него взаимодействие ничем не отличается от работы с реальным объектом (к приме¬
ру, SAPAccountingAdapter). Объект-посредник перехватывает вызовы для улучшения
доступа к реальному объекту, в данной ситуации за счет перенаправления обращения
к локальной службе (LocalAccounting) в случае отказа внешней службы.35.5. Реализация нефункциональных
или качественных требованийПрежде чем перейти к следующему разделу, отметим, что рассматриваемые до сих
пор в этой главе проектные решения не были связаны с бизнес-логикой, а относи¬
лись лишь к реализации нефункциональных или качественных требований надежно¬
сти и восстановления данных.Интересно, что большинство сложных вопросов, шаблонов и типов программной
архитектуры связано как раз с реализацией нефункциональных качественных требо¬
ваний, а не с реализацией бизнес-логики.35.6. Доступ к внешним физическим устройствам
с помощью шаблона AdapterЕще одно требование этой итерации связано со взаимодействием с физическими
устройствами, сопряженными с терминалом POS-системы, в частности, открытием
кассового аппарата, извлечением сдачи или считыванием подписи с помощью циф¬
рового устройства.POS-система NextGen должна взаимодействовать с различным оборудованием, в
том числе разработанным компаниями IBM, Epson, Fujitsu и т.д.К счастью, в настоящее время существует промышленный стандарт UnifiedPOS
(www.nrf-arts.org), определяющий общепринятый объектно-ориентированный ин¬
терфейс (в смысле UML) для всех типичных POS-устройств. Более того, существует
реализация этого стандарта для Java — JavaPOS (www.javapos.com).Поэтому в описание программной архитектуры нужно добавить раздел о взаимо¬
действии с другими устройствами.
616 Часть V. Третья итерация фазы развитияТехническое описание
Управление аппаратными средствами POS-системы.
Идея решения. Использовать специальное программное обеспечение для Java от
производителей аппаратных средств, удовлетворяющее стандарту интерфейса
JavaPOS.
Факторы• Корректное управление устройствами• Проще купить, чем разработать и поддерживать
РешениеСтандарт UnifiedPOS (www.nrf-arts.org) определяет промышленный стандарт для моделиро¬
вания на UML интерфейсов для POS-устройств. JavaPOS (www.javapos.com) — это промышлен¬
ная версия стандарта UnifiedPOS для Java. Производители оборудования для POS-систем (IBM,
NCR) продают реализации этих интерфейсов, управляющие произведенными ими устройствами.Лучше купить эти программы, чем разрабатывать самим.Для загрузки набора классов IBM или NCR можно использовать шаблон Factory и возвращать
экземпляры, основанные на этих интерфейсах.МотивировкаПо неофициальным данным, эти интерфейсы работают хорошо, производители оборудования
регулярно обновляют их версии в соответствии с модификацией аппаратных средств. Написать
их самостоятельно гораздо сложнее.Альтернативные решенияНаписать интерфейсы самостоятельно — это сложно и рискованно.На рис. 35.14 показаны некоторые интерфейсы, объединенные в новый пакет
уровня предметной области модели проектирования.Рис. 35.14. Стандартные интерфейсы JavaPOS
Глава 35. Новые проектные решения на основе шаблонов GoF 617Допустим, основные производители оборудования для POS-систем поставляют на
рынок также свои реализации стандарта JavaPOS. Например, при покупке терминала
с кассовым аппаратом от компании IBM можно также приобрести классы Java, реали¬
зующие интерфейсы JavaPOS и управляющие физическими устройствами.Следовательно, эта часть архитектуры строится на базе стандартных програм¬
мных компонентов, а не их самостоятельной разработки. Один из советов UP —
приобретение стандартных компонентов.Как работают эти компоненты? На низком уровне существуют драйверы физиче¬
ских устройств, взаимодействующие с их операционной системой. Класс Java (напри¬
мер, одна из реализаций jpos.CashDrawer) использует интерфейс JNI (Java Native
Interface) для обращения к драйверам этих устройств.Эти классы Java адаптируют низкоуровневые драйверы устройств к интерфейсам
JavaPOS, поэтому их можно рассматривать как объекты-адаптеры в смысле шабло¬
на GoF. Их можно также назвать объектами-посредниками, управляющими досту¬
пом к физическим устройствам.Зачастую одно проектное решение соответствует сразу нескольким шаблонам.35.7. Шаблон Abstract Factory (GoF) для
семейства взаимосвязанных объектовРеализации интерфейсов JavaPOS можно приобрести у производителей оборудо¬
вания. Вот несколько примеров.5// Драйверы компании IBMcom.ibm.pos.jpos.CashDrawer (implements jpos.CashDrawer)com.ibm.pos.jpos.CoinDispenser (implements jpos.CoinDispenser)// Драйверы компании NCRcom.ncr.posdrivers.CashDrawer (implements jpos.CashDrawer)com.ncr.posdrivers.CoinDispenser (implements jpos.CoinDispenser)Как же спроектировать работу приложения NextGen с драйверами компании IBM
или NCR?Требуется создать семейства классов (CashDrawer, CoinDispenser и т.д.), каждое
из которых реализует свой интерфейс.Для этого существует шаблон GoF Abstract Factory (Абстрактная фабрика).5 Это фиктивные имена пакетов.
618 Часть V. Третья итерация фазы развитияШаблон Abstract FactoryКонтекст/проблемаКак создать семейства взаимосвязанных классов, реализующих общий интер¬
фейс?РешениеОпределить интерфейс объекта-фабрики (абстрактную фабрику). Определить
конкретный класс-фабрику для каждого создаваемого семейства. Кроме того,
определить реальный абстрактный класс, реализующий интерфейс фабрики и
обеспечивающий однотипную работу с конкретными объектами-фабриками, рас¬
ширяющими его.Основная идея этого шаблона проиллюстрирована на рис. 35.15.Абстрактный Ьь
класс-фабрика,) «interface»интерфейс дляIJavaPOSDevicesFactoryсозданиясемействавзаимосвязанныхобъектговgetNewCashDrawer():jpos.CashDrawergetNewCoinDispenser():jpos.CoinDispenser5^?IBMJavaPOSDevicesFactorygetNewCashDrawer():jpos.CashDrawer
getNewCoinDispenser():jpos.CoinDispenserreturn new com.ibm.pos.jpos.CashDrawer()
}NCRJavaPOSDevicesFactorygetNewCashDrawer():jpos.CashDrawer
getNewCoinDispenser():jpos.CoinDispenser< kreturn new com.ncr.posdevices.CashDrawer()}«interface» (
jpos.CashDrawerisDrawerOpened()com.ibm.pos.j pos.CashDrawercom.ncr.posdevices.CashDrawerisDrawerOpened()isDrawerOpened()Puc. 35.15. Базовая абстрактная фабрика
Глава 35. Новые проектные решения на основе шаблонов GoF 619Абстрактный класс абстрактной фабрикиТипичная реализация шаблона Abstract Factory подразумевает создание абстракт¬
ного класса-фабрики, доступ к которому осуществляется по шаблону Singleton
(Единственный экземпляр), определение на основе системного свойства конкретных
типов создаваемых подклассов-фабрик и получение соответствующего экземпляра
подкласса. Этот принцип реализуется, например, в библиотеках Java с помощью клас¬
са java.awt.Toolkit — абстрактного класса абстрактной фабрики, предназначенной
для создания семейства элементов графического пользовательского интерфейса для
различных операционных систем.Преимуществом такого подхода является решение следующей проблемы: какую
абстрактную фабрику использовать — IBMJavaPOSDevicesFactory или NCRJava-
POSDevicesFactory?Решение этой проблемы показано на рис. 35.16.При наличии абстрактного класса-фабрики и метода getlnstance шаблона
Singleton объекты могут взаимодействовать с абстрактным подклассом, получая ссыл¬
ку на один из экземпляров подкласса. Например, рассмотрим следующий оператор.CashDrawer = JavaPOSDevicesfactory.getlnstance().getNewCashDrawer();Вызов JavaPOSDevicesfactory.getlnstance () возвращает экземпляр класса
IBMJavaPOSDevicesFactory или NCRJavaPOSDevicesFactory, в зависимости от
считанного значения системного свойства. Заметим, что при изменении внешнего
системного свойства jposfactory.classname (представляющего имя класса в виде
строки) в файле конфигурации система NextGen будет использовать другое семей¬
ство драйверов JavaPOS. При этом соблюдается принцип шаблона Protected Variations
в смысле защиты от влияния изменения типа фабрики за счет считывания данных из
файла конфигурации и рефлексивного проектного решения с использованием выра¬
жения c.newlnstance.Взаимодействие с объектом-фабрикой осуществляет объект Register. С целью со¬
кращения разрыва между содержанием и представлением целесообразно поместить в
этот объект ссылки на устройства, в частности CashDrawer. Например:class Register{private jpos.CashDrawer cashDrawer;private jpos.CoinDispenser coinDispenser;public Register(){cashDrawer = JavaPOSDevicesFactory.getlnstance().getNewCashDrawer();
//...}//...}
620 Часть V. Третья итерация фазы развития{// ЭТОТ МЕТОД РЕАЛИЗУЕТ ПОЛЕЗНЫЙ ПРИЕМ
public static synchronized
IJavaPOSDevicesFactory getlnstance(){if (instance == null){String factoryClassName =System.getProperty("jposfactory.classname");Class с =Class.forName(factoryClassName);instance =(IJavaPOSDevicesFactory)с.newlnstance();}return instance;Курсивом выделя¬
ются абстрактные
методы и классык.Деление абстракт¬
ного суперкласса
на подклассык.«interface»IJavaPOSDevicesFactory1getNewCashDrawer():jpos.CashDrawer
getNewCoinDispenser():jpos.CoinDispenser< AJavaPOSDevicesFactoryinstance : IJavaPOSDevicesFactoryb getlnstance():IJavaPOSDevicesFactorygetNewCashDrawer():jpos.CashDrawer
getNewCoinDispenser():jpos.CoinDispenser1'""'"OsIBMJavaPOSDevicesFactory ^NCRJavaPOSDevicesFactory ^getNewCashDrawer():jpos.CashDrawer
getNewCoinDispenser():jpos.CoinDispenser.....ogetNewCashDrawer()...
getNewCoinDispenser()...
pk.return new com.ibm.pos.jpos.CoinDispenser()
}< кreturn new com.ncr.posdevices.CoinDispenser()}Puc. 35.16. Абстрактный класс абстрактной фабрики
Глава 35. Новые проектные решения на основе шаблонов GoF 62135.8. Обработка платежей на основе шаблонов
Polymorphism и Do It MyselfОдним из распространенных способов применения принципа полиморфизма
(и шаблона Information Expert) является стратегия “Сделай сам”, оформленная в виде
отдельного шаблона [34]. Она сводится к следующему.Шаблон Do It Myself
“Программный объект выполняет обязанности реальных объектов, абстракцию
которых он представляет.” [34]В этом проявляется классический стиль объектно-ориентированного проектиро¬
вания: объекты Circle и Square отвечают за отображение самих себя, объект Text
проверяет орфографию и т.д.Заметим, что проверка орфографии с помощью объекта Text — классический
пример реализации шаблона Information Expert, согласно которому функциональная
обязанность присваивается тому объекту, который обладает для ее выполнения до¬
статочной информацией.Шаблоны Do It Myself и Information Expert “провозглашают” схожие принципы.Отображение объектов Circle и Square — это в то же время пример реализации
шаблона Polymorphism, согласно которому обязанности для типов с различным по¬
ведением распределяются на основе полиморфных операций.Шаблоны Do It Myself и Polymorphism обычно приводят к одинаковому распреде¬
лению обязанностей.В соответствии с шаблоном Pure Fabrication, перегрузка класса функциональны¬
ми обязанностями часто противопоказана, поскольку это приводит к проблемам со
связыванием и зацеплением, поэтому разработчики зачастую прибегают к созданию
чисто синтетических классов стратегий, фабрик и т.д.Тем не менее, шаблон Do It Myself очень привлекателен, поскольку позволяет со¬
кратить разрыв между реализацией и ее представлением. Поэтому обработку плате¬
жей будем выполнять на основе шаблонов Do It Myself и Polymorphism.Одним из требований для данной итерации является обработка различных типов
платежей, требующих авторизации и взаимодействия с внешними системами. Разные
типы платежей авторизируются по-разному.■ Платежи по кредитной и дебитной карточке подлежат авторизации через внеш¬
нюю службу.■ Платежи наличными авторизируются в некоторых магазинах с помощью спе¬
циального устройства проверки подлинности банкнот, подключенного к POS-
терминалу. В других магазинах авторизация не проводится.■ Платежи чеком авторизируются в некоторых магазинах с помощью компьюте¬
ризированной службы авторизации, в других — авторизация отсутствует.Таким образом, объекты CreditPayment подлежат авторизации одним способом,
а объекты CheckPayment — другим. Это классическая ситуация для применения ша¬
блона Polymorphism.
622 Насть V. Третья итерация фазы развитияКак видно из рис. 35.17, каждый подкласс класса Payment имеет свой методauthorize.Рис. 35.17. Классический пример использования принципа полиморфизма
для различных методов authorizеНапример, как видно из рис. 35.18 и 35.19, объект Sale инстанцирует объекты
CreditPayment и CheckPayment и передает им запрос на авторизацию соответству¬
ющего типа платежа.По шаблону ^CreatorРис. 35.18. Создание экземпляра CreditPayment
Глава 35. Новые проектные решения на основе шаблонов GoF623Рис. 35.19. Создание экземпляра CheckPayment“Мелкие” классыРассмотрим программные объекты CreditCard, DriversLicense и Check. Сразу
же приходит мысль записать данные этих классов в соответствующие классы плате¬
жей и не связываться со столь “мелкими классами”. Однако зачастую более разумно
эти классы оставить, поскольку они полезны и их можно будет использовать повтор¬
но. Например, класс CreditCard является естественным экспертом для определения
типа кредитной карточки (Visa, MasterCard и т.п.). А это очень нужная для приложе¬
ния информация.Авторизация платежей по кредитной карточкеДля выполнения этой операции система должна взаимодействовать с внешней
службой авторизации кредитов. Для поддержки такого взаимодействия уже создано
проектное решение на основе объектов-адаптеров.
624 Часть V. Третья итерация фазы развитияИнформация из предметной области
о платежах по кредитной карточкеРассмотрим некоторые моменты, в контексте которых строится проектное реше¬
ние.■ POS-системы могут быть физически связаны с внешними службами авториза¬
ции несколькими способами, в том числе через телефонные линии (удаленное
соединение) или выделенный канал Интернет.■ Для авторизации используются различные протоколы уровня приложения
и соответствующие им форматы данных, в частности SET (Secure Electronic
Transaction). Со временем могут появиться новые протоколы, например
XMLPay.■ Авторизацию платежей можно рассматривать как обычную синхронную опера¬
цию: поток POS-системы блокируется и ожидает ответа от удаленной службы
(в течение ограниченного интервала времени).■ Все протоколы авторизации предполагают передачу идентификаторов магазина
(ID магазина) и терминала POS-системы (ID терминала). В ответе содержится
код подтверждения или отказа и уникальный идентификатор транзакции.■ В магазине для разных типов кредитных карточек могут использоваться раз¬
личные внешние службы авторизации (одна для карточек Visa, другая — для
MasterCard). Для каждой такой службы используется свой идентификатор мага¬
зина.■ Тип кредитной карточки можно определить по ее номеру. Например, номера,
начинающиеся с цифры 5, относятся к системе MasterCard, а номера, начинаю¬
щиеся с цифры 4, — к системе Visa.■ Реализации адаптеров защищают вышестоящие уровни системы от изменения
типов авторизации платежей. Каждый адаптер отвечает за выполнение транзак¬
ции авторизации в соответствующем формате и за взаимодействие с внешними
службами. Как было описано при рассмотрении предыдущей итерации, объект
ServicesFactory отвечает за доставку соответствующей реализации интерфей¬
са ICreditAuthorizationServiceAdapter.Сценарий разработкиНа рис. 35.20 показана первая часть проектного решения, удовлетворяющего опи¬
санным требованиям. Приведенные комментарии наглядно иллюстрируют логику
рассуждения.После нахождения соответствующей реализации ICreditAuthorizationService-
Adapter на этот объект возлагается обязанность по выполнению авторизации
(рис. 35.21).После получения положительного ответа объект Credit Payment в соответствии с
шаблоном Polymorphism и Do It Myself завершает свою работу (рис. 35.22).Применение UML. Обратите внимание, что на этой диаграмме последовательно¬
стей некоторые объекты изображены в несколько ярусов. Это допускается синтак¬
сисом UML, однако такую форму записи поддерживают не все CASE-средства. Тем не
менее она достаточно удобна, если ширина листа ограниченна.
Глава 35. Новые проектные решения на основе шаблонов GoF 625Объекту Register Я(абстракции торгового
терминала) известен
идентификатор терминала,
поскольку обеспечены
незначительные различия
между уровнями
представленияПо шаблону
ExpertОбъекту Store Iизвестенидентификатормагазина, посколькуобеспеченынезначительныеразличия междууровнямипредставленияИдентификаторы ^
магазинапроиндексированы
по коду кредитных
карточек, например,
Visa, Master Cardpmt:Credit ^1 ":Credit 1Payment:RegisterCard:Storeauthorize 1 и1tID=getTermin$lID() *0ct=getType:CreditTypemID=getMerchantID(ct)D-mID=find(ct)Требования шаблона Protected Variations
обеспечиваются за счет применения
шаблонов Factory и Adaptercas=getCreditAuthorizationService(ct)reply=requestApproval(pmt,tID,mID)ref/1 credit^ApprovalPuc. 35.20. Обработка платежей no кредитной карточке
Часть V. Третья итерация фазы развитияРис. 35.21. Завершение авторизацииcas:1as:pmt:CreditCreditAuthorization:ServicesIaccountingPayment
 1 ServiceAdapteriFactory
I 4ServiceAdapter
 ©—г authorizeПо шаблону
Do It Myself
и Polymorphismreply=requestApproval(pmt,tID,mID) i[reply.isApproved()] 1
handleApproval(reply) |as=getAccountingService()По шаблонам
Protected
Variations,
Factory
и AdapterpostSale(pmt.getSale())LipostReceivable(pmt)
 e "*0В атрибуте объекта pmt будут храниться
полученные данные.Адаптер будет извлекать объекты pmt
и форматировать содержащиеся в нем данные
в соответствии с требованиями определенной
службыРис. 35.22. Завершение обработки платежа по кредитной карточке после полу¬
чения подтверждения от службы авторизации
Глава 35. Новые проектные решения на основе шаблонов GoF 62735.9. Пример: игра “Монополия”Сначала кратко рассмотрим новые правила игры и требования, реализуемые на
третьей итерации разработки системы. Если игрок попадает на клетку недвижимо¬
сти, железной дороги или коммунальной собственности, не принадлежащую другому
игроку, при наличии нужной суммы денег он может приобрести эти объекты в соб¬
ственность. Если они уже принадлежат другому игроку, он должен платить арендную
плату.Основные проектные решения, реализующие эти правила, приведены на рис. 35.23
и 35.24. Они основаны на принципе полиморфизма. Для клеток с различным пове¬
дением реализован полиморфный метод landedOn. При попадании программного
объекта Player на клетку Square, он передает ей сообщение landedOn.РЦегUt*£<4!4 ^
1ism*<wnV 1и<\А^Ол
 — d£т— L_JРис. 35.23. Диаграмма классов с учетом полиморфной операции landedOn *!f*L:So«r4 Uc-Syct 1Puc. 35.24. Динамика взаимодействия объектов с учетом полиморфной операции landedOn
628 Часть V. Третья итерация фазы развитияЭти проектные решения демонстрируют преимущества полиморфизма для обра¬
ботки новых вариантов поведения объектов. На данной итерации просто добавлены
новые типы клеток (LotSquare, RailRoadSquare, UtilitySquare) и полиморфный
метод landedOn.Из рис. 35.25 видно, что все объекты PropertySquare содержат метод landedOn,
поэтому он может быть реализован в суперклассе и унаследован его подклассами. На
рис. 35.26 показано проектное решение для попытки приобретения недвижимости,
а на рис. 35.27 — для оплаты аренды. Способ вычисления аренной платы отличается
для каждого класса, поэтому согласно принципу полиморфизма операция get Rent
должна быть реализована в каждом подклассе (рис. 35.28).Диаграмма классов для третьей итерации разработки игры “Монополия” показана
на рис. 35.29.[EEEr[ом/Ыг !=Рис. 35.25. Попадание на клетку PropertySquareIp PWy.<- | U'Ptop«i>^v{<»«ni *к.BetUMmi oowhr-tbtSmiy btiftsXРис. 35.26. Попытка приобрести недвижимость
Глава 35. Новые проектные решения на основе шаблонов GoF 629, гсЫл¥Х&Н& Lfl£Л*У •#r«W«v C. * X%[ :U+t1i^S^w. | \ -G1—L——pi. jC<W<\. * 4Рис. 35.28. Полиморфный метод get Rent
630 Часть V. Третья итерация фазы развитияjw<~ 1С,t3E*fw*ivл^МГsVt*«w*\KiHlkiti.| ял A«AO*t•H«a4«AQiv
.$£&**Kt^WS^Jev*.Uttj. Л~ Т '"i Go$^>*reIPuc. 35.29. Диаграмма классов для третьей итерации разработки игры “Монополия ”35.10. ЗаключениеВ рассмотренных примерах не ставилась задача показать корректное решение.
Единственного правильного решения просто не существует. Автор уверен, что чита¬
тели смогут усовершенствовать предложенное проектное решение. Основной зада¬
чей было объектное проектирование на основе базовых принципов, таких как связы¬
вание и применение шаблонов.Предупреждение: не “злоупотребляйте” шаблонамиВ рассмотренном примере довольно часто применялись шаблоны GoF, что соот¬
ветствовало задачам обучения читателей. Однако иногда разработчики “злоупотре¬
бляют” шаблонами и пытаются использовать их где надо и где не надо. Для умелого
использования шаблонов необходимо изучить их. Для изучения шаблонов на прак¬
тике в некоторых организациях (в обеденный перерыв или после работы) проводят
деловые игры, в рамках которых участники группы разработчиков упражняются в
применении шаблонов на тестовых приложениях.
Проектирование
на основе пакетовЕсли бы вам пришлось вспахать поле, что бы вы предпочли:
две сильных лошади или 1024 цыпленка ?Сеймур Крей (Seymour Cray)Основные задачи■ Реализовать пакетную структуру для снижения степени влияния из¬
менений.■ Ознакомиться с альтернативной системой обозначений UML для па¬
кетов.ВведениеЕсли некоторый пакет X в значительной мере зависит от конкретной группы раз¬
работчиков, то его нужно сделать максимально устойчивым (не подлежащим изме¬
нению в новых версиях системы), поскольку в противном случае повышается зави¬
симость от этих разработчиков. Именно их придется привлекать для модернизации
пакета в случае необходимости.Это достаточно очевидно, но иногда данному вопросу не уделяется должного вни¬
мания, что приводит к неоправданно высоким трудозатратам.Что дальше? После проектирования объектов на основе шаблонов GoF в данной главерассматриваются диаграммы пакетов. В следующей главе будут исследованы
диаграммы развертывания и компонентов/ \
632 Насть V. Третья итерация фазы развитияМатериал этой главы базируется на рассмотренных в предыдущей главе вопросах
организации уровней и пакетов, но здесь предлагаются более “тонкие” эвристиче¬
ские советы по организации пакетов, позволяющие снизить зависимость от возмож¬
ных изменений внутри пакетов. Основная задача — создать робастную физическую
структуру пакетов.Зависимость от правильной пакетной организации более остро чувствуют разра¬
ботчики на языке C++, чем на Java, поскольку C++ более чувствителен к реализации
компилятора и компоновщика. Изменение одного класса может отразиться на мно¬
жестве других классов и потребовать перекомпоновки системы.1 Поэтому предлага¬
емые здесь рекомендации особенно полезны при разработке систем на C++ и менее
важны для реализации проектов на Java, Smalltalk или С#.Некоторые из приведенных ниже советов навеяны рассуждениями Роберта Мар¬
тина [91] о проектировании физической структуры приложения на C++ и его пакет¬
ной организации.Исходный код физической архитектуры
в модели реализацииЭтот вопрос относится к физическому проектированию (physical design) системы, ко¬
торое выполняется в рамках модели реализации путем разбиения исходного кода на
пакеты.В процессе построения диаграмм на бумаге или с помощью CASE-средств разра¬
ботчик может разместить типы данных и пакеты достаточно произвольно. Однако в
процессе проектирования физической архитектуры, подразумевающей организацию
типов данных в физические пакеты на C++ или Java, способ разбиения системы на
пакеты определяется взаимным влиянием элементов системы.36.1. Рекомендации по организации пакетовВертикальное и горизонтальное зацепление
функциональности пакетовОсновной интуитивный подход к разбиению системы на модули подразумевает
группировку элементов по принципу высокого зацепления — тесной взаимосвязи ча¬
стей пакета в рамках реализации общих задач, служб, политик и функций. Например,
все типы данных пакета Pricing системы NextGen связаны с определением стоимо¬
сти товаров. Уровни и пакеты системы NextGen разбиты на группы по функциональ¬
ному назначению.Менее очевидным критерием группировки является высокая степень внутреннего
связывания, определяющая принадлежность типов некоторому кластеру. Например,
класс Register тесно связан с классом Sale, который, в свою очередь, связан с объ¬
ектами SalesLineltem.1 В C++ пакеты можно реализовать через пространства имен, однако лучше разделить фай¬
лы исходного кода на несколько каталогов, по одному на каждый пакет.
Глава 36. Проектирование на основе пакетов 633Степень внутреннего связывания пакетов или его относительное зацепление можно
выразить в числовом представлении, хотя эта характеристика используется достаточ¬
но редко. Для общего сведения приведем формулу ее вычисления.КС=ЧислоВнутреннихСвязей/КоличествоТиповЗдесь ЧислоВнутреннихСвязей включает связи между параметрами и атрибутами,
отношения наследования, реализацию интерфейсов среди типов данных пакета.Для пакета с 6 типами данных и 12 связями коэффициент связывания RC состав¬
ляет 2. Для пакета с б типами и 3 внутренними связями RC=0.5. Более высокие значе¬
ния коэффициента означают более высокую степень зацепления элементов данного
пакета.Заметим, что эта характеристика не очень информативна для пакетов, содержа¬
щих в основном интерфейсы. Она гораздо показательнее для пакетов, включающих
реализации классов.Слишком маленькое значение RC означает выполнение одного из следующих усло¬
вий.■ Пакет содержит не связанные между собой элементы и плохо нормализован.■ Пакет содержит не связанные между собой элементы, но это не должно бес¬
покоить разработчиков. Это случается с пакетами утилит или разрозненных
служб (например, java.util). В этом случае значение RC не играет роли.■ Пакет содержит один или несколько внутренних кластеров с высоким коэффи¬
циентом RC, но в целом степень связывания элементов пакета невысока.Пакет, представляющий собой семейство интерфейсовСемейство функционально связанных интерфейсов можно поместить в отдель¬
ный пакет, не содержащий реализации классов. Речь идет не о паре связанных друг
с другом интерфейсов, а о семействе, включающем не менее трех интерфейсов.
Примером такого пакета для Java-технологий является пакет javax.ejb, содержащий
порядка 12 интерфейсов, реализации которых содержатся в других пакетах.Формирование пакетов на базе групп неустойчивых классовОсновная мысль данного обсуждения сводится к следующему. Пакет — это базовая
структурная единица разработки и программного продукта. Отдельные классы разра¬
батываются гораздо реже и совсем редко становятся приложениями.Допустим, существует большой пакет Р1, содержащий порядка тридцати классов,
некоторое подмножество которого (порядка 10 классов: С1...С10) постоянно модифи¬
цируется.В этом случае стоит разделить пакет Р1 на два отдельных пакета Р1-а и Pl-Ь, вклю¬
чив в Pl-Ь десять неустойчивых классов.Таким образом пакет делится на устойчивую и неустойчивую части либо на груп¬
пы классов, работа над которыми ведется одновременно. Следовательно, приходим к
выводу: если работа над классами пакета ведется одновременно, значит, пакет сгруп¬
пирован правильно.В идеале пакеты нужно сформировать таким образом, чтобы от классов пакета
Pl-Ь зависела работа меньшего числа разработчиков, чем от пакета Р1-а. Тогда оче¬
634 Часть V. Третья итерация фазы развитияредная версия пакета Pl-Ь скажется на дальнейшей работе ограниченного круга раз¬
работчиков.Заметим, что такая перегруппировка является следствием учета трудоемкости соз¬
дания пакета. На ранних итерациях очень сложно сформировать хорошую структуру
пакетов приложения. Она постепенно изменяется на стадии развития, и по оконча¬
нии этой стадии разработки должна быть сформирована устойчивая структура боль¬
шинства пакетов.Данный совет сводится к следующей основной стратегии: снижение зависимости
от неустойчивых пакетов.Базовые пакеты должны быть более устойчивымиЕсли структура базовых пакетов (от которых зависит большинство других) не¬
устойчива, то повышается вероятность ошибок в приложении. Например, если ши¬
роко используемый пакет утилит, такой как com.foo.util, часто изменяется, то это
может повлечь за собой неработоспособность многих других элементов системы. На
рис. 36.1 показана рекомендуемая структура пакетов с точки зрения их взаимозависи¬
мости.com.foo.nextgen.
ui.swingIcom.foo.nextgen.domain.sale
 ^ Менее устойчивый:-более зависимый;- конкретный, детализированныйcom.foo.nextgen.
domain.payments
 com.foo.util
 Or: com. foo. nextgen.
domain.posruleengine _Q Более устойчивый:- менее зависимый4- конкретный, детализированный
код становится устойчивым
после доработки;- абстрактные классы, интерфейсыПакеты, от которых зависит большое количество
других элементов, должны быть более устойчивыми,
поскольку их изменение может оказать большое
влияние на другие пакетыРис. 36.1. Базовые пакеты должны быть более устойчивымиЧем ниже расположены пакеты на этой диаграмме, тем устойчивее они должны
быть. Существует несколько способов повышения устойчивости пакета.■ Включение в пакет преимущественно интерфейсов и абстрактных классов.• Например, пакет java.sql содержит восемь интерфейсов и шесть классов,
преимущественно простых и устойчивых, как Time и Date.
Глава 36. Проектирование на основе пакетов 635■ Отсутствие зависимости от других пакетов или зависимость только от очень
устойчивых пакетов, либо инкапсуляция зависимости внутри пакета.• Например, в пакете com.foo.nextgen.domain.posruleengine можно скрыть
реализацию правил за “фасадным” объектом. Тогда даже при изменении реа¬
лизации правил зависимые пакеты не будут оказывать влияния друг на друга.■ Включение в пакет относительно устойчивого кода, апробированного и испы¬
танного ранее.• Например, java.util.■ Утверждение стабильного графика разработки, предполагающего нечастое вне¬
сение изменений.• Например, основной пакет библиотеки Java java.lang просто не может из¬
меняться довольно часто.Факторизация независимых типовКлассы, используемые независимо друг от друга или в различном контексте, следует
помещать в разные пакеты. Без внимательного изучения группировка на основе сход¬
ной функциональности может не обеспечить нужного уровня детализации пакетов.Допустим, что подсистема служб взаимодействия с базой данных содержится в
одном пакете com.foo.service.persistence. Предположим, в этом пакете имеют¬
ся два общих класса утилит JDBCUtilities и SQLCommand. Раз эти общие утилиты
предназначены для взаимодействия с реляционной базой данных, значит, их можно
использовать независимо от остальной части подсистемы для доступа к базе данных
через JDBC. Следовательно, эти типы лучше выделить в отдельный пакет, например
com.foo.util.jdbc (рис. 36.2).ПлохоЛучшея.foo.service.persistence]DBFacadeSchemaMappingJDBCUtilities SQLCommanda.foo.service.persistence]DBFacadeSchemaMappingcom.foo.util.jdbc | ^JDBCUtilities SQLCommandPuc. 36.2. Факторизация независимых типов
636 Часть V. Третья итерация фазы развитияФакторизация для снижения зависимости
от конкретных пакетовОдним из способов повышения устойчивости пакетов является снижение зави¬
симости от конкретных классов других пакетов. Проблемная ситуация показана на
рис. 36.3.SalesRegister
— 1 -Q PaymentsCreditPaymentPersistencePaymentMapper// в некоторых методах объектов Register и PaymentMapper I
CreditPayment pmt = new CreditPayment();Puc. 36.3. Непосредственное связывание с конкретным пакетомПредположим, классы Register и PaymentMapper (класс, осуществляющий преоб¬
разование объектов платежа в формат реляционной базы данных и обратно) создают
экземпляры объектов CreditPayment из пакета Payments. Одним из способов повы¬
шения устойчивости пакетов Sales и Persistence является предотвращение созда¬
ния экземпляров классов, определенных в других пакетах (объектов CreditPayment
из пакета Payments).Такое связывание можно уменьшить за счет ислользования объекта-фабрики, от¬
вечающего за создание экземпляров. Методы этого объекта-фабрики должны возвра¬
щать объекты, объявленные в терминах интерфейсов, а не классов (рис. 36.4).Шаблон Domain Object FactoryИспользование объектов-фабрик для создания всех экземпляров классов уровня
предметной области — это стандартная идиома проектирования. В литературе по
проектированию ее можно встретить под именем шаблона Domain Object Factory
(Фабрика объектов предметной области), однако формально она не описана в виде
шаблона.Не используйте циклы в пакетахЕсли группа пакетов связана циклической зависимостью, их можно объединить в
один пакет. Такая ситуация нежелательна, поскольку увеличение размера пакета по¬
вышает вероятность возникновения ошибок в системе.
Глава 36. Проектирование на основе пакетов 637//в некоторых методах объектов Register и PaymentMapper
ICreditPayment pmt = DomainObjectFactory.getlnstance().getNewCreditPayment();SalesRegisteriPersistencePaymentMapperDomainObj ectCreationDomainObj ectFactory«interface»ICreditPayment«interface»IProductCataloggetNewCreditPayment():ICreditPayment
getNewProductCatalog():IProductCatalogsetCreditAccount(...)getProductDescription(...)PaymentsCreditPaymentProductsProductCatalogPuc. 36.4. Снижение связывания с конкретным пакетом за счет использованияобъекта-фабрикиСуществует два решения подобной проблемы.1. Выделение типов, связанных циклической зависимостью, в отдельный пакет
меньшего размера.2. Прерывание цикла с помощью интерфейса.Для этого можно предпринять следующие действия.1. Переопределить зависимые классы в одном из пакетов таким образом, чтобы
они реализовывали новые интерфейсы.2. Определить новые интерфейсы в новом пакете.3. Переопределить зависимые типы таким образом, чтобы они зависели от интер¬
фейсов в новом пакете, а не от исходных классов.Эта стратегия показана на рис. 36.5.36.2. Дополнительная литератураНе удивительно, что большинство публикаций по улучшению структуры пакетов и
снижению зависимостей принадлежит перу авторов, разрабатывающих приложения
на C++. Однако изложенные в этих книгах принципы применимы и к другим языкам
программирования. Эти вопросы хорошо проработаны в книгах [83] и [91]. Данной
тематике посвящена также книга [62].
Часть V. Третья итерация фазы развитияПлохоЛучше 1Рис. 36.5. Предотвращение циклической зависимости
Диаграммы развертывания
и компонентов UMLВы можете назвать меня параноиком, но символы '/*' внутри комментариявызывают у меня подозрения.Возможное предупреждение компилятора СОсновная задача■ Ознакомиться с обозначениями языка UML для диаграмм развертыва¬
ния и компонентов.Что дальше?После построения диаграммы пакетов в данной главе рассматриваются диаграммы
развертывания и компонентов. Следующая глава будет посвящена разработке
каркаса взаимодействия с базой данныхПроектирование
объектов Диаграммына основе пакетовшаблонов GoFо о Диаграммы
развертывания
и компонентов\Разработка
каркаса
взаимодействия
с базой данных о-—Документи¬рованиеархитектуры37.1. Диаграммы развертыванияДиаграммы развертывания отражают соответствие конкретных программных ар¬
тефактов (например, выполняемых файлов) вычислительным узлам (выполняющим
обработку). Они показывают размещение программных элементов в физической ар¬
хитектуре системы и взаимодействие (обычно сетевое) между физическими элемен-
640 Часть V. Третья итерация фазы развитиятами. Показанная на рис. 37.1 диаграмма развертывания позволяет лучше понять фи¬
зическую архитектуру (или архитектуру развертывания).«client workstation»
:GenericPC«artifact»
MyRichGUIClient.exe«server»:DellPowerEdge 3600
{OS=Red Hat Enterprise Linux 4}«client workstation»
:GenericPC«servlet container»
:Tomcat6
{JVM=Sun Hotspot 2.0}«web server cluster»
:Aoache 2.1
{clusterCount=4}Ajpvl3HTTP«browser»
:WebBrowserРядом с линией
взаимодействия может
быть указан протокол«server»Ре11PowerEdge 3600Альтернативноеобозначениеартефакта«OS»Red Hat Enterprise Linux 4Узел устройстваИсполняющий
узел окруженияРис. 37.1. Диаграмма развертыванияОсновным элементом диаграммы развертывания является узел (node), относящий¬
ся к одному из двух типов.■ Узел устройства (device node) (или просто ycTpoftcTBo(device)). Это физический (на¬
пример, цифровой или электронный) вычислительный ресурс с памятью и про¬
цессорным элементом, на котором работает программное обеспечение. В роли
устройства может выступать обычный компьютер или мобильный телефон.■ Исполняющий узел окружения (execution environment node — EEN) — это програм¬
мный вычислительный ресурс, работающий в рамках другого узла (например,
компьютера) и обеспечивающий выполнение других выполняемых программ¬
ных элементов. К EEN относятся:• операционная система (operating system — OS) — это программное обеспечение,
выполняющее другие прикладные программы;• виртуальная машина (virtual machine), например Java или .NET, отвечающая за
выполнение программ;
Глава 37. Диаграммы развертывания и компонентов UML 641• система управления базами данных (database engine), например PostgreSQL. Она
получает и выполняет SQL-запросы, а также хранимые процедуры;• Web-браузер, отвечающий за выполнение сценариев JavaScript, аплетов Java и
других активных элементов;• механизм управления процессом выполнения задач;• сервлет-контейнер или EJB-контейнер.Согласно спецификации UML многие типы узлов отображаются с помощью стере¬
отипов, таких как «server», «OS», «database» и «browser».Узел устройства или EEN могут содержать другие узлы EEN. Например, виртуаль¬
ная машина может работать на компьютере в рамках операционной системы.Конкретный элемент EEN может не отображаться или неформально изображать¬
ся с помощью строки свойств UML, например {OS=Linux}. На рис. 37.1 показан аль¬
тернативный способ обозначений, когда элемент EEN изображается не в виде явного
узла.Соединение между узлами называется коммуникационным путем (communication
path), который зачастую помечается именем протокола, реализующего сетевое со¬
единение.Узел может содержать артефакт — конкретный физический элемент, обычно вы¬
полняемый файл типа .jar, .ехе или файл сценария. К артефактам могут относиться
и файлы данных, например .xml, .html и т.д.На диаграммах развертывания обычно изображают экземпляры, а не классы.
Например, на конкретном сервере работает конкретный экземпляр OS Linux. В UML
имена конкретных экземпляров подчеркиваются, а отсутствие подчеркивания свиде¬
тельствует об использовании класса, а не экземпляра. Исключение из данного пра¬
вила составляют диаграммы взаимодействия, на которых имена экземпляров не под¬
черкиваются.В любом случае на диаграммах развертывания обычно отображаются конкретные
экземпляры объектов с подчеркнутыми именами. Однако согласно спецификации
UML на диаграммах развертывания подчеркивание можно не использовать. Поэтому
в разных книгах можно встретить оба примера обозначений.37.2. Диаграммы компонентовКомпонент — это несколько размытое понятие в UML, поскольку их можно ис¬
пользовать для моделирования тех же сущностей, что и классы. Можно привести ци¬
тату Румбаха (Rumbaugh), одного из создателей UML.Различие между структурированным классом и компонентом является весьма
относительным и определяется, скорее, предпочтениями, чем строгой семан¬
тикой. [108]Можно также процитировать спецификацию UML [100].“Компонент (component) представляет собой отдельно размещаемую и заменяе¬
мую часть системы, инкапсулирующую свое содержимое. Поведение компонен¬
та определяется в терминах реализации интерфейсов. Таким образом, компо¬
нент служит типом, определяемым с помощью реализуемых интерфейсов.”21 Зак. 3357
642 Часть V. Третья итерация фазы развитияЭту идею можно проиллюстрировать с помощью обычного класса UML и реализу¬
емых им интерфейсов. Напомним, что классы UML можно использовать для модели¬
рования программного элемента любого уровня, от целой системы или подсистемы
до небольшого вспомогательного объекта.При использовании компонентов на диаграммах UML акцент делается на интер¬
фейсах, модульности и заменяемости. Это означает, что компонент практически не
зависит от других внешних элементов (за исключением, возможно, стандартных би¬
блиотек) и является относительно самостоятельным модулем.Компоненты UML рассматриваются на уровне проектирования и не существуют в
конкретной программной реализации. Однако они соответствуют конкретным арте¬
фактам, например наборам файлов.Хорошей аналогией для моделирования программных компонентов служат домаш¬
ние кинотеатры, в которых легко можно заменить DVD-плейер или колонки. Такой
кинотеатр состоит из отдельных заменяемых модулей, взаимодействующих друг с
другом через стандартный интерфейс. Например, на высоком уровне абстракции в
качестве компонента можно рассматривать СУБД SQL, поскольку одну и ту же вер¬
сию SQL могут поддерживать различные базы данных. В более мелком масштабе в
качестве компонента можно рассматривать стандартный программный интерфейс
Java Message Service.Поскольку при моделировании компонентов основное внимание уделяется заме¬
няемости частей (например, с целью повышения производительности), диаграммы
компонентов обычно строят для крупномасштабных элементов. Основные обозначе¬
ния диаграммы компонентов показаны на рис. 37.2.Рис. 37.2. Обозначения диаграммы компонентов UMLВопрос построения моделей компонентов выходит за пределы основных понятий
объектно-ориентированного анализа и проектирования.
Проектирование каркаса
взаимодействия с базой
данных на основе шаблоновПо мнению большинства экспертов, наиболее вероятный способ разрушения
мира — это случайность. К такому же выводу приходим мы — профессионалы вкомпьютерной области. Мы порождаем случайности.Натаниэль Боренштейн (Nathaniel Borenstein)Основные задачи■ Спроектировать часть каркаса на основе шаблонов Template Method,
State и Command.■ Ознакомиться с принципами преобразования информации из объект¬
ного представления в формат реляционной базы данных.■ Реализовать пассивную материализацию на основе шаблона Virtual
Proxy.ВведениеВ данной главе не ставится задача проектирования коммерческого каркаса взаи¬
модействия с базой данных. Здесь рассматриваются принципы объектно-ориентиро-
ванного проектирования каркасов вообще на основе интересного примера каркаса
взаимодействия с базой данных.
644 Часть V. Третья итерация фазы развитияЧто дальше?После изучения диаграмма развертывания и компонентов в данной главе
рассматривается каркас взаимодействия с базой данных. В следующей главе
речь пойдет о документировании архитектуры/\ДиаграммыпакетовДиаграммы
развертывания
и компонентовРазработка
каркаса
взаимодействия
с базой данных
 • Документи¬рованиеархитектурыУправление
итеративной
и гибкой
разработкой оВ приложении NextGen, как и в большинстве приложений, возникает необхо¬
димость хранить информацию на постоянных носителях, например в реляционной
базе данных. В этой главе рассматриваются вопросы объектно-ориентированного
проектирования каркаса объектов, связанные с хранением информации на постоян¬
ных носителях.СоветКак правило, лучше приобрести готовую службу преобразования информации из
объектного представления в формат реляционной базы данных или O-R-службу
(object-relational service), чем самому приниматься за ее разработку. Например,
для Java-приложений широко применяется каркас Hibernate (www.hibernate.org).
Он позволяет решить множество проблем объектно-реляционного преобразова¬
ния (O-R-преобразования), обработки транзакций, обеспечения необходимой
производительности и т.д.Приводимый в книге пример каркаса является лишь типичной реализацией для
многих предметных областей. Автор не рекомендует этот каркас для коммерче¬
ского использования. Для приложений на Java нет необходимости создавать по¬
добные каркасы вручную.38.1. Проблема: объекты, подлежащие
постоянному хранениюПредположим, что в приложении NextGen экземпляры объекта ProductDescription
хранятся в реляционной базе данных и загружаются в оперативную память в про¬
цессе работы приложения. Постоянно хранимыми объектами (persistent objects) назо¬
вем объекты, требующие хранения на постоянном носителе, например экземплярыProductDescription.Механизмы хранения и постоянно хранимые объектыОбъектные базы данных. При хранении информации в объектной базе данных
не требуется никаких дополнительных служб обеспечения взаимодействия с базой
данных. В этом состоит одно из преимуществ такого подхода.Реляционные базы данных. Для хранения информации чаще всего применяют¬
ся реляционные базы данных. При этом возникает множество проблем, связанных с
Глава 38. Проектирование каркаса взаимодействия с базой данных на основе шаблонов 645несоответствием объектно-ориентированного представления данных в системе и их
представления в виде записей в базе данных. Эти проблемы будут рассмотрены не¬
сколько позже. Для работы с реляционными базами данных требуются специальные
средства преобразования форм представления информации (O-R-преобразования).Другие базы данных. Иногда желательно хранить информацию в другом виде, на¬
пример в текстовых файлах, в формате XML, в файлах Palm OS PDB, иерархических
базах данных и т.п. В этом случае возникают те же проблемы преобразования форм
представления информации, что и при работе с реляционными базами данных. Как
и при использовании реляционных баз данных, здесь возникает несоответствие меж¬
ду представлением постоянно хранимого объекта в системе и его представлением в
не объектно-ориентированной структуре. Для работы с такими объектами требуются
специальные службы.38.2. Решение: каркас интерфейса с базой данныхКаркас интерфейса с базой данных (persistent framework) — многократно используе¬
мый и обычно расширяемый набор классов, обеспечивающий обслуживание постоян¬
но хранимых объектов. Функции каркаса выполняет служба интерфейса с базой данных
(или подсистема), создаваемая на базе классов этого каркаса. Служба интерфейса с
базой данных обычно разрабатывается для взаимодействия с реляционными базами
данных. В этом случае она называется службой O-R-преобразования (O-R mapping ser¬
vice). Обычно служба интерфейса с базой данных выполняет преобразование объект¬
ной формы представления информации в форму записей (или другой структуриро¬
ванный формат данных, типа XML) и их хранение в базе данных, а также обратные
операции.В терминах многоуровневой архитектуры приложения NextGen служба интерфей¬
са с базой данных — это подсистема уровня технических служб.38.3. КаркасыРискуя примитивизировать это понятие, возьму на себя смелость утверждать, что
каркас (framework) — это расширяемый набор объектов для реализации взаимосвязан¬
ных функций. Типичным примером каркаса является каркас графического интерфей¬
са пользователя, в частности библиотека Swing для Java.Хороший каркас включает реализацию базовых и инвариантных функций, а так¬
же обеспечивает механизм подключения модифицируемых функций или их расши¬
рения.Например, каркас графического интерфейса Swing для Java содержит много клас¬
сов и интерфейсов для основных функций графического интерфейса пользователя.
Разработчики могут добавлять специализированные средства за счет реализации под¬
классов для классов Swing и перекрытия существующих методов. Разработчики мо¬
гут также подключать разнообразные обработчики событий (например, для класса
JButton), регистрируя слушателей или подписчиков на основе шаблона Observer.
Это и есть каркас.В целом, каркас — это набор классов:
646Часть V. Третья итерация фазы развития■ с высокой степенью зацепления, взаимодействующих между собой и обеспечи¬
вающих обслуживание ядра, т.е. неизменяемой части логической подсистемы;■ включающий конкретные и абстрактные классы, которые определяют интер¬
фейс между объектами;■ обычно (но не всегда) требующий определения пользователем подклассов для
существующих классов каркаса, их использования, настройки и расширения
служб каркаса;■ имеющий абстрактные классы, которые могут содержать как абстрактные, так
и конкретные методы;■ основанный на принципе Голливуда (Hollywood Principle) “Не звоните нам, мы
сами с вами свяжемся”. Это означает, что определенные пользователем клас¬
сы (например, новые подклассы) будут получать сообщения от определенных
ранее классов каркаса. Это обычно достигается путем реализации абстрактных
методов суперкласса.Следующий пример каркаса интерфейса с базой данных иллюстрирует это опре¬
деление.Каркасы предназначены для повторного использованияКаркасы предоставляют очень хорошие возможности для повторного использо¬
вания, гораздо более широкие, чем отдельные классы. Следовательно, если органи¬
зация заинтересована (а кто в этом не заинтересован?) в повторном использовании
своего программного кода, то необходимо сосредоточить внимание на создании кар¬
касов.38.4. Требования к каркасу интерфейса
с базой данныхДля приложения NextGen необходим каркас интерфейса с базой данных (per¬
sistence framework), обеспечивающий обслуживание постоянно хранимых объ¬
ектов. Назовем его PFW (Persistence Framework). PFW— это упрощенный каркас.
Полнофункциональные каркасы интерфейса с базой данных не относятся к вопро¬
сам, обсуждаемым в этой книге.Рассматриваемый здесь каркас должен обеспечивать реализацию следующих функ¬
ций.■ Хранение объектов на постоянном носителе и извлечение этих объектов■ Завершение и отмена транзакций (commit и rollback)Проектное решение должно быть расширяемым и поддерживать различные меха¬
низмы хранения данных, включая реляционную базу данных, обычные файлы, фор¬
мат XML и т.д.
Глава 38. Проектирование каркаса взаимодействия с базой данных на основе шаблонов 64738.5. Основные принципыВ последующих разделах будут рассмотрены некоторые основные принципы.■ Соответствие. Между классом и его представлением на постоянном носителе
должно существовать некоторое соответствие (например, таблица в базе дан¬
ных). Полл записи базы данных должны соответствовать атрибутам. Таким об¬
разом должно существовать соответствие между этими двумя схемами.■ Идентичность объектов. Для упрощения связывания записей с объектами и
во избежание неоправданного дублирования записи и объекты должны иметь
уникальные идентификаторы объектов.■ Преобразователи базы данных. За материализацию и дематериализацию
объектов, согласно шаблону Pure Fabrication, отвечает специальный класс-пре¬
образователь базы данных.■ Материализация и дематериализация. Материализация — это действие по пре¬
образованию необъектного представления данных (например, записей) в объект¬
ное представление. Дематериализация — это обратное действие (которое еще
называют деактивизацией).■ Кеширование. С целью повышения производительности специальные службы
кешируют материализованные объекты.■ Состояние транзакции данного объекта. Очень важно знать состояние объек¬
та в терминах его отношения к текущей транзакции. Например, полезно знать,
какие объекты были модифицированы, чтобы знать, нужно ли их снова записы¬
вать в базу данных.■ Операции транзакции. Операции commit и rollback.■ Пассивная материализация. Не все объекты должны материализоваться одно¬
временно. Конкретный экземпляр должен материализоваться только в случае
необходимости — по требованию.■ Виртуальные посредники. Пассивная материализация реализуется с использо¬
ванием продуманных ссылок, получивших название виртуального механизма по¬
средника.38.6. Шаблон представления объектов в виде таблицКак установить соответствие объекта с его представлением в реляционной базе
данных?Шаблон Representing Objects as Tables (Представление объектов в виде таблиц)
[28] предлагает для каждого класса объектов, подлежащих постоянному хранению,
определить отдельную таблицу (при использовании реляционной базы данных), а
атрибуты объекта, содержащие данные простых типов (чш:ла, строки, логические
переменные и т.д.), хранить в отдельных столбцах.Если все атрибуты объекта являются данными простых типов, то установка такого
соответствия не представляет сложностей. Однако реальность не столь проста, по¬
скольку одни объекты могут содержать ссылки на другие сложные объекты, а реля¬
ционная модель базы данных требует, чтобы эти значения были простыми (первая
нормальная форма) (рис. 38.1).
648 Часть V. Третья итерация фазы развитияManufacturernamecityManufacturer
name = Now&Zen
city = MumbaiТаблица manufacturernamecityNow&ZenMumbaiCelestialShorteningSan RamonPuc. 38.1. Соответствие объектов и таблиц38.7. Профиль моделирования данных UMLЕсли речь идет о хранении объектов в базе данных, то вполне естественно пред¬
положить наличие в рамках UML специальных обозначений для моделей данных.
Напомним, что модель данных является одним из официальных артефактов UP и отно¬
сится к дисциплине проектирования. Некоторые обозначения, применяемые в UML
для моделирования данных, приводятся на рис. 38.2.Агрегация означает ссылочное ограничение: строка Product Specification не может
существовать без связанной с ней строки ManufacturerРис. 38.2. Пример модели данных в UMLПредставленные на рис. 38.2 стереотипы не относятся к ядру UML — они состав¬
ляют часть расширения. В целом, в UML существует понятие профиля UML (UML pro¬
file), под которым понимается набор взаимосвязанных стереотипов, тегированных
значений и ограничений, объединенных общим предназначением. На рис. 38.2 по¬
казана часть профиля моделирования данных UML.38.8. Шаблон Object IdentifierЖелательно разработать приемлемый способ взаимосвязи объектов с записями,
а также гарантировать, что многократная материализация записей не приведет к ду¬
блированию объектов.Согласно шаблону Object Identifier (Идентификатор объектов) [28], каждой за¬
писи и объекту (или объекту-посреднику) присваивается идентификатор объекта
(OID — Object identifier).
Глава 38. Проектирование каркаса взаимодействия с базой данных на основе шаблонов 649Идентификатор объекта обычно представляет собой буквенно-цифровое значе¬
ние. Такой идентификатор является уникальным для каждого конкретного объекта.
Существуют различные подходы к формированию идентификаторов. Некоторые из
них предполагают уникальность идентификатора в рамках одной базы данных, дру¬
гие основаны на полной уникальности идентификаторов [3].В рамках объектного подхода идентификатор объекта представляется интерфей¬
сом или классом OID, инкапсулирующим реальное значение и его представление.
В реляционных базах данных идентификатор представляет собой символьную строку
фиксированной длины.Каждая таблица реляционной базы данных в качестве первичного ключа исполь¬
зует идентификатор объекта, прямо или косвенно связанный с каждым объектом.
Если каждый объект имеет свой идентификатор, используемый в качестве первич¬
ного ключа соответствующей таблицы, то каждому экземпляру объекта можно един¬
ственным образом сопоставить некоторую запись этой таблицы (рис. 38.3).Manufacturername
city
oid: OID:Manufacturer
name = Now&Zen
city = Mumbai
oid = xyz!23Таблица manufacturerOIDnamecityxyz123Now&ZenMumbaiabc345CelestialShorteningSan Ramona....Первичный ключЭто упрощенное решение. На самом
деле идентификатор OID можно поместить
в объект-посредникРис. 38.3. Объекты и записи связываются посредством идентификаторов объектовВ этом состоит основная идея проектного решения. На самом деле идентифика¬
тор объекта не обязательно помещать в объект, предназначенный для постоянного
хранения, хотя возможен и такой вариант. Его можно поместить в объект-посредник
(такой подход будет описан ниже). Конкретное проектное решение определяется
также выбором языка программной реализации.Идентификаторы объектов используются для взаимодействия с базой данных.38.9. Доступ к службе взаимодействия с базой
данных на основе шаблона FacadeПервым шагом на пути решения этой задачи является определение внешнего ин¬
терфейса для службы взаимодействия с базой данных (ее “фасада”). Напомним, что
шаблон Facade обеспечивает унифицированный интерфейс для подсистем. Для на¬
чала нужна операция, позволяющая восстановить объект по его идентификатору.
Однако помимо идентификатора объекта подсистеме нужно знать тип материали¬
зуемого объекта. Следовательно, параметром этой операции должен быть и класс
650 Часть V. Третья итерация фазы развитияобъекта. На рис. 38.4 показаны некоторые операции, реализуемые согласно шаблону
Facade для одного из адаптеров системы NextGen.PersistenceFacadegetlnstance(): PersistenceFacade
get(0ID, Class): Object
put(OID, Object):DBProductsAdapter~T:PersistenceFacadeobj =get(...)Tl// пример использования шаблона Facade
OID oid = new OID("XYZ123");ProductDescription pd= (ProductDescription) PersistenceFacade.getlnstance().
get(oid, ProductDescription.class);Puc. 38А. Применение шаблона Facade для взаимодействия с базой данных38.10. Объекты-преобразователи: шаблон
Database Mapper или Database BrokerОбъект PersistenceFacade, как и любой другой “фасадный” объект, сам не вы¬
полняет никаких действий, а делегирует запросы объектам подсистем.Кто должен отвечать за материализацию и дематериализацию объектов (напри¬
мер, объекта ProductDescription)?Согласно шаблону Information Expert, эту обязанность можно возложить на сам
класс (ProductDescription), поскольку он обладает некоторой информацией (со¬
храняемыми данными), необходимой для выполнения этой обязанности.Если объект, подлежащий постоянному хранению, содержит код для сохранения
самого себя в базе данных, то такое проектное решение называется прямым отобра¬
жением (direct mapping). Прямое отображение применимо в том случае, если код для
взаимодействия с базой данных автоматически генерируется и внедряется в описа¬
ние класса постпроцессором, и разработчику не требуется поддерживать этот код
для своих классов.Если же код для прямого отображения приходится добавлять и поддерживать
вручную, то такой подход обладает рядом недостатков, в том числе следующими.■ Связывание класса объектов, подлежащих постоянному хранению, со структу¬
рой базы данных (с нарушением принципов шаблона Low Coupling).■ Сложные обязанности в новых и несвязанных между собой областях (в разрез с
шаблоном High Cohesion). При этом обязанности технических служб смешива¬
ются с обязанностями объектов уровня логики приложения.
Глава 38. Проектирование каркаса взаимодействия с базой данных на основе шаблонов 651В дальнейшем будет использован классический подход непрямого отображения (in¬
direct mapping), при котором для преобразования объектов в структуру базы данных
используются другие объекты.В рамках этого подхода применяется шаблон Database Broker (Брокер базы дан¬
ных) [27]. Согласно этому шаблону, создается класс, отвечающий за материализацию,
дематериализацию и кеширование объектов. Этот шаблон называют также Database
Mapper (Преобразователь базы данных) [53]. Это название автору кажется более
предпочтительным, поскольку оно описывает обязанности класса, а термин “брокер”
в распределенных системах [17] имеет другое устоявшееся значение.1Для каждого класса объектов, подлежащих хранению в базе данных, определяет¬
ся отдельный класс-преобразователь. Из рис. 38.5 видно, что для каждого объекта,
подлежащего хранению в базе данных, может существовать собственный класс-пре¬
образователь, и для различных механизмов хранения данных могут использоваться
различные виды преобразователей. Приведем пример кода.class PersistenceFacade{//. . .public Object get(OID oid, Class persistenceClass){// объект IMapper выбирается на основе типа объекта,// подлежащего хранению в базе данныхIMapper mapper = (IMapper) mappers.get( persistenceClass );// делегирование прав
return mapper.get ( oid );}//. . .}Хотя на этой диаграмме показаны два класса-преобразователя для объекта
ProductDescription, для каждой конкретной базы данных будет использован толь¬
ко один из них.Преобразователи на основе метаданныхБолее гибким, но более сложным является подход к созданию преобразователей
на основе метаданных (данных о данных). Чтобы не создавать каждый конкретный
класс-преобразователь для каждого класса объектов, подлежащих хранению в базе
данных, преобразователи на основе метаданных динамически генерируют отображе¬
ние объектного представления в некоторое другое (например, в структуру реляци¬
онной базы данных). Это делается путем считывания описания преобразования из
метаданных, например, “ТаЫеХ отображается в Class Y, столбец Z отображается в
свойство объекта Р” (или еще более сложного описания). Такой подход применим
для языков с возможностями рефлексивного программирования, таких как Java, C#
или Smalltalk, а для остальных, например C++, — нет.1 В распределенных системах брокером называют внешний серверный процесс, делегирую¬
щий задачи внутренним серверным процессам.
652 Часть V. Третья итерация фазы развитияОбозначения UML это специфицированная ассоциация, которая означает следующее.1. Объект PersistenceFacade имеет ассоциацию 1 к М С объектом IMapper2. С использованием ключа типа class можно найти объект шаррег (путем поиска
в коллекции)PersistenceFacadegetlnstance(): PersistenceFacade Classget(OID, Class): Object
put(OID, Object)Обратите внимание, что
в данной версии метода
get больше не нужно
использовать параметр
с типом class, поскольку
класс “жестко” связан
с типом, предназначенным
для постоянного хранения<<interface>>IMapperget(OID) : Object
put(OID, Object)ProductDescriptionRDBMapperProductDescriptionFlatFileMapperManufacturerRDBMapper‘-oget (OID) :Object
put(OID, Object) Or get(OID):Obj ect
put(OID, Object)get(OID):Obj ect
put(OID, Object)Каждый класс-преобразователь передает и получает объекты
по-разному, в зависимости от вида хранимых данных и их
форматаРис. 38.5. Преобразователи базы данныхПреобразователи на основе метаданных позволяют изменять схему отображения
для уже функционирующего приложения без модификации исходного кода (что со¬
гласуется с шаблоном Protected Variations в смысле изменения схемы отображения).Тем не менее, важнейшим свойством рассматриваемого здесь каркаса на основе
обычных преобразователей или метаданных является инкапсуляция его реализации,
т.е. возможность использования без изменения клиента.38.11. Разработка каркаса на основе
шаблона Template MethodВ следующем разделе описываются важнейшие особенности проектирования пре¬
образователей. Эти принципы проектирования основываются на шаблоне Template
Глава 38. Проектирование каркаса взаимодействия с базой данных на основе шаблонов 653Method (Метод-шаблон) из группы GoF [58].2 Этот шаблон является основным прин¬
ципом проектирования каркасов3 и знаком большинству программистов если не по
названию, то по содержанию.Его назначение состоит в определении в суперклассе метода (метода-шаблона), за¬
дающего скелет алгоритма и содержащего варьируемую и неизменную части. Метод-
шаблон вызывает другие методы, часть из которых может перекрываться в произво¬
дных классах. Таким образом, производные классы могут перекрывать варьируемые
методы и добавлять собственную функциональность (рис. 38.6).// метод-шаблон
// его алгоритм является
// неизменяемой частью
public void update(){clearBackground();// подключаемый метод
//он является варьируемой
частью
repaint();Подключаемый метод:- варьируемая часть
перекрывается в подклассе;- может быть абстрактным
или иметь реализацию по
умолчаниюПерекрывающий ^
подключаемый метод:- перекрывает варьируемую
часть алгоритмаПРИНЦИП ГОЛЛИВУДА: ■“Не звоните нам, мы сами с Вами свяжемся.”
Обратите внимание, что метод MyExcel lent Butt on-
repaint вызывается из унаследованного метода
update суперкласса.Такой прием типичен при
встраивании методов в класс контураПодключаемый методMyExcellentButtonrepaint()НАШ классGUIComponentКласс каркаса ^Метод-шаблон ^repaint ()1IРис. 38.6. Шаблон Template Method в каркасе графического интерфейса пользователя2 Этот шаблон никак не связан с шаблонами в C++, поскольку он описывает шаблон алго¬
ритма.3 Более точно, каркасов в виде “белого ящика”. Под такими каркасами обычно понимают
иерархию классов и каркасов, требующих от пользователя знания их внутренней структуры и
проектных решений.
654 Насть V. Третья итерация фазы развития38.12. Материализация на основе
шаблона Template MethodПри создании двух или трех классов-преобразователей некоторые фрагменты
кода неизбежно повторяются. Базовая структура алгоритма материализации объекта
имеет следующий вид.if (объект в буфере)
возвратить его
elseсоздать объект на основе его представления в базе данных
сохранить объект в буфере
возвратить егоТочкой вариации является конкретный способ создания объекта.Создадим метод-шаблон get абстрактного суперкласса AbstractPersistenceMethod.
Проектное решение для такого метода-шаблона представлено на рис. 38.7.Обозначения UMLкКомментарий {leaf}
используется для конкретныхопераций классов.
Символ # означает/7 метод-шаблонpublic final Object get(OID oid)“защищенный”. Такойметод видим только
для подклассовobj := cachedObjects.get(oid);
if(obj == null)// подключаемый методobj = getObjectFromStorage(oid);cachedObj ects .put. (oid, obj) ;«interface»IMapperget (OID) : Object МЕТОД-ШАБЛОНput(OID, Object)return obj;ПОДКЛЮЧАЕМЫЙ МЕТОДVAbstract
PersistenceMapperо + get(OID) : Object {leaf} 6# getObjectFromStorage (OID) :Object-‘<3{abstract}Puc. 38.7. Применение шаблона Template Method для объектов-преобразователей
Глава 38. Проектирование каркаса взаимодействия с базой данных на основе шаблонов 655Как видно из этого примера, метод-шаблон обычно является открытым (public),
а подключаемый метод — защищенным (protected). Классы AbstractPersistence
Mapper и IMapper являются частью каркаса взаимодействия с базой данных. Теперь
разработчик может подключать свои методы к этому каркасу, добавляя собственные
подклассы и перекрывая или реализуя метод getObjectFromStorage. Пример такой
реализации показан на рис. 38.8.// метод-шаблонpublic final Object get(OID oid){obj := cachedObjects.get(oid);
if (obj == null ){// подключаемый методobj = getObjectFromStorage(oid)cachedObjects.put(oid,obj)}return obj
}IMapperQAbstractPersistenceMapper+ get(OID) : Object {leaf}# getObjectFromStorage(OID):Object
{abstract}II перекрытый подключаемый методprotected Object getObjectFromStorage(OID oid){String key = oid.toString();
dbRec = Результат выполнения SQL-запроса:
"Select * from PROD_DESC
where key = " + key
ProductDescription pd=new ProductDescription()
pd.setOID( oid );pd.setPrice( dbRec.getColumn("PRICE"));
pd.setItemID( dbRec.getColumn("ITEM_ID"));
pd.setDescrip( dbRec.getColumn("DESC"));
return pd;}ProductDescriptionRDBMapper# getObjectFromStorage(OID):ObjectPuc. 38.8. Перекрытие подключаемого методе?Предположим, что в реализации подключаемого метода на рис. 38.8 начальная
часть алгоритма, в которой выполняется SQL-оператор SELECT, одинакова для всех
объектов. Варьируется только имя таблицы базы данных.5 При таком предположении
можно снова применить шаблон Template Method и разделить изменяемую и неизмен¬
ную части алгоритма. На рис. 38.9 метод AbstractRDBMapper.getObjectFromStorage
является подключаемым с точки зрения метода AbstractPersistenceMapper.get, но
становится шаблоном для вновь подключаемого метода getObjectFromRecord.4 В Java объект dbRec, возвращаемый после выполнения SQL-запроса, будет представлять
собой результирующее множество JDBC.5 Зачастую все не так просто. Объект может извлекаться из нескольких таблиц или даже
различных баз данных. В этом случае первая версия шаблона Template Method является более
гибкой.
656 Насть V. Третья итерация фазы развитияIMapperprotected final Object
getObjectFromStorage(OID oid){dbRec = getDBRecord( oid );// hook methodreturn getObjectFromRecord(oid, dbRecprivate DBRecord getDBRecord OID oid){String key = oid.toString();
dbRec = SQL execution result of:
"Select * from "+ tableName +" where key =" + key
return dbRec;} 1// перекрытый подключаемый метод
protected Object
getObjectFromRecord(OID oid,DBRecord dbRec){ProductDescription pd=
new ProductDescription();
pd.setOID(oid);pd.setPrice(dbRec.getColumn("PRICE"));
pd.setltemID(dbRec.getColumn("ITEM_ID")
pd.setDescrip(dbRec.getColumn("DESC"));
return pd;}Abstract
PersistenceMa pper+ get(OID) : Object {leaf}# getObjectFromStorage(OID):Object{abstract}AbstractRDBMappertableName : StringQ+ <<constructor> AbstractRDBMapper(tableName)# getObjectFromStorage(OID):Object {leaf}># getObjectFromRecord(OID,DBRecord):Object{abstract}- getDBRecord(OID):DBRecordProductDescriptionRDBMapper+ <<constructor>>ProductDescriptionRDBMapper(tabName)# getObjectFromRecord(OID,DBRecord):ObjectPuc. 38.9. Повторное применение шаблона Template MethodОбратите внимание на объявление конструкторов в UML. Стереотип здесь исполь¬
зовать необязательно, особенно если имя конструктора совпадает с именем класса.Теперь в состав каркаса входят классы IMapper, AbstractPersistenceMapper и
AbstractRDBMapper. Разработчику приложения остается добавить свои собственные
производные классы, например ProductDescriptionRDBMapper, для соответствую¬
щей таблицы (имя которой должно быть передано конструктору объекта).Иерархия классов-преобразователей базы данных составляет важную часть кар¬
каса. Разработчики приложения могут добавлять свои производные классы в эту ие-
Глава 38. Проектирование каркаса взаимодействия с базой данных на основе шаблонов 657рархию и настраивать свое приложение для работы с новыми механизмами хране¬
ния данных или новыми таблицами и файлами в рамках существующего механизма
хранения. На рис. 38.10 показаны структуры некоторых пакетов и классов. Заметим,
что классы, составляющие специфику приложения NextGen, не относятся к пакету
общих технических служб Persistence. Эта диаграмма в сочетании с диаграммой на
рис. 38.9 демонстрирует важность визуальных языков типа UML для описания частей
программного обеспечения. Подобные диаграммы содержат много наглядной инфор¬
мации.NextGen PersistenceProductDescriptionRDBMapper+ ProductDescriptionRDBMapper(tableName)# getObjectFromRecord(OID,DBRecord):0bjectProductDescription
F i1eWi thXMLMapper# getObjectFromStorage(OID):0bjectSaleRDBMapper# getObjectFromRecord(OID,DBRecord):0bjectProductDescriptionInMemoryTestDataMapper# getObjectFromStorage(OID):ObjectPersistence1+ PersistenceFacade<<интерфейс>>IMappergetlnstance(): PersistenceFacadeClass >get(OID) : Objectget(OID, Class):0bject
put(OID, Object)1put(OID, Object)V1AbstractRDBMapper iAbstract
Per sis t enceMapper+ AbstractRDBMapper(tableName)# getObjectFromStorage(OID):Object {leaf}# getObjectFromRecord(OID,DBRecord) .-Object
- getDBRecord(OID) : DBRecord>+ get(OID) : Object {leaf}# getObjectFromStorage(OID):ObjectPuc. 38.10. Каркас взаимодействия с базой данных
658 Часть V. Третья итерация фазы развитияОбратите внимание на класс ProductDescriptionlnMemoryTestDataMapper на
рис. 38.10. Такие объекты можно использовать для тестирования программы без при¬
влечения внешних баз данных.Унифицированный процесс и описание
программной архитектурыВ рамках UP важное значение имеет документ с описанием программной архи¬
тектуры. Он позволяет разработчикам будущих систем ознакомиться с опытом сво¬
их предшественников и наиболее ценными архитектурными решениями. В этот до¬
кумент обычно включаются диаграммы, подобные представленным на рис. 38.9 и
38.10.Синхронизированные методы в UMLМетод AbstractPersistenceMapper.get содержит небезопасный с точки зрения
многопоточности фрагмент кода — один и тот же объект можно одновременно мате¬
риализовать в различных потоках. Как и все подсистемы технических служб, службу
взаимодействия с базой данных нужно реализовывать с учетом безопасности пото¬
ков. Действительно, функции системы могут выполняться в различных потоках или
даже на различных компьютерах. Тогда объект PersistenceFacade становится уда¬
ленным серверным объектом, а подсистема может функционировать одновременно в
нескольких потоках, обслуживая разных клиентов.Поэтому данный метод должен контролировать параллельное функционирование
потоков. В Java это достигается за счет использования ключевого слова synchro¬
nized. На рис. 38.11 показан фрагмент диаграммы классов, содержащий синхрони¬
зированный метод.// Java Вpublic final synchronized Object get( OID oid ){ ... }{guarded} означает “синхронизированный” метод.
T.e. внутри семейства условных методов данного
объекта одновременно может существовать лишь
один потокAbstract \PersistenceMapper \IMapper
 О9+ get(OID):0bject (leaf, guarded}Puc. 38.11. Синхронизированный метод в UML
Глава 38. Проектирование каркаса взаимодействия с базой данных на основе шаблонов 65938.13. Настройка преобразователейс помощью объекта MapperFactoryАналогично приведенному выше примеру использования шаблона Factory, объекты
IMapper для “фасадного” объекта PersistenceFacade тоже можно конфигурировать
с помощью объекта-фабрики MapperFactory. Однако в этом случае не желательно
для каждой операции определять отдельный преобразователь. Например, следующий
фрагмент нельзя считать удачным.class MapperFactory
{public IMapper getProductDescriptionMapper (){.. . }
public IMapper getSaleMapper (){. . . }}При таком подходе нарушается шаблон Protected Variations, поскольку не обеспе¬
чивается возможность добавления новых преобразователей. Поэтому более предпо¬
чтительным является следующий вариант.class MapperFactory
{public Map getAHMappers (){...}}Здесь классами являются ключи java.util.Мар (реализованные, возможно, с по¬
мощью HashMap), a IMapper становятся экземплярами с конкретными значениями.Поэтому фасадный объект может инициализировать коллекцию IMapper следую¬
щим образом.class PersistenceFacade
{private java.util.Map mappers =MapperFactory.getlnstance().getAllMappers();}Значения объектам IMapper можно присвоить следующим образом. Объект-
фабрика может считывать системные свойства для выяснения, какой из классов
IMapper нужно инстанцировать. При использовании языка с возможностями реф¬
лексивного программирования, например Java, инстанцирование может быть осно¬
вано на считывании имен классов в виде строк и использовании операции Class,
newlnstance. Тогда набор преобразователей можно модифицировать без изменения
исходного кода.38.14. Шаблон Cache ManagementС целью повышения производительности системы материализованные объекты
желательно хранить в локальном буфере (поскольку материализация — это сравни¬
тельно медленная операция), обеспечивая при этом поддержку операций управления
транзакциями типа commit.
660 Часть V. Третья итерация фазы развитияСогласно шаблону Cache Management (Управление буфером) [28], обязанность
по поддержке операций буферизации возлагается на классы-преобразователи базы
данных. Если для каждого класса объектов, хранящихся в базе данных, использует¬
ся отдельный преобразователь, то этот преобразователь поддерживает буферизацию
своих объектов.После материализации объекты помещаются в буфер, а в качестве ключа исполь¬
зуется их идентификатор. При запросе на определенный объект преобразователь
сначала выполняет поиск объекта в буфере, что позволяет избежать дополнительных
операций материализации.38.15. Объединение и сокрытие
операторов SQL в одном классеКодирование операторов SQL в различных классах-преобразователях каркаса вза¬
имодействия с базой данных не является преступлением. Однако такую реализацию
можно улучшить. Примем следующие предположения.■ Существует один “чисто синтетический” класс (удовлетворяющий шабло¬
ну Singleton) RDBOpe rat ions, в котором сосредоточены все операторы SQL
(SELECT, INSERT, ...).■ Классы-преобразователи взаимодействуют с этим объектом для получения
одной или нескольких записей из базы данных (например, Re suit Set).■ Интерфейс этого класса имеет следующий вид.class RDBOperations
{public ResultSet getProductDescriptionData (OID oid) {...}
public ResultSet getSaleData(OID oid) { . . . }}Тогда преобразователь должен быть реализован следующим образом.class ProductDescriptionRDBMapper extends AbstractPersistenceMapper
{protected Object getObjectFromStorage (OID oid){ResultSet rs =RDBOperations.getlnstance () .getProductDescriptionData(oid);ProductDescription ps = new ProductDescription();
ps.setPrice(rs.getDouble("PRICE"));
ps . setOID(oid);
return ps;}}Использование шаблона Pure Fabrication обеспечивает следующие преимущества.■ Простота поддержки и настройка производительности специалистами. Для
оптимизации производительности SQL требуются эксперты именно в этой об¬
ласти, а не специалисты по объектному программированию. Если все опера-
Глава 38. Проектирование каркаса взаимодействия с базой данных на основе шаблонов 661торы SQL сосредоточены в одном классе, то этот код можно предложить для
оптимизации специалисту по SQL.■ Инкапсуляция деталей реализации. Например, операторы SQL, обеспечиваю¬
щие получение данных, можно заменить вызовом хранимых процедур реляци¬
онной базы данных. Можно использовать и более тонкий подход, основанный
на метаданных, и динамически генерировать операторы SQL по схеме описа¬
ния метаданных, считываемой из внешнего источника.С точки зрения архитектора, интересный аспект данного проектного решения со¬
стоит в том, что оно учитывает навыки разработчика. При этом достигается баланс
между высокой степенью зацепления и удобством для специалиста. Не все проектные
решения определяются только принципами проектирования программных систем,
такими как связывание или зацепление.38.16. Состояние транзакции и шаблон StateВопросы поддержки транзакций достаточно нетривиальны, поэтому для простоты
(чтобы сосредоточить внимание на применении шаблона State из набора GoF) при¬
мем следующие предположения.■ Объекты, подлежащие хранению в базе данных, можно добавлять, удалять или
модифицировать.■ Действия над постоянно хранимыми объектами (например, их модификация)
не приводят к немедленному изменению базы данных, а выполняются в рамках
операции commit.Кроме того, будем считать, что результат операции зависит от состояния транзак¬
ции для данного объекта. Пример результатов подобных операций показан на диа¬
грамме состояний на рис. 38.12.Диаграмма состояний объектаPersistentObj ectNew[новый (не из базы данных)]commit / insertПояснения:New — только что созданный
объект, а не полученный
из базы данных;Old — старый объект;Clean — неизмененный объект;
Dirty — измененный объектРис. 38.12. Диаграмма состояний для объекта PersistentObj ect
662 Часть V. Третья итерация фазы развитияНапример, старым измененным объектом (OLD DIRTY) будем считать модифици¬
рованный объект, извлеченный из базы данных. При выполнении операции commit
этот объект необходимо обновить в базе данных (в отличие от старого неизменно¬
го объекта (OLD CLEAN), который после извлечения из базы данных не изменялся).
При использовании каркаса взаимодействия с базой данных операции сохранения
или удаления не выполняются немедленно. Просто подлежащие хранению объекты
переходят в определенное состояние, а необходимые действия выполняются при за¬
вершении или отмене транзакции.Для UML изменение состояний в рамках транзакций очень полезно отображать
на диаграмме состояний.Предположим, что все классы объектов, подлежащих хранению в базе данных,
расширяют класс PersistentObject,6 обеспечивающий реализацию общих техниче¬
ских служб для взаимодействия с базой данных7. Пример такой ситуации представлен
на рис. 38.13.Заметим, что методы commit и rollback предусматривают одинаковую логику вы¬
полнения, основанную на состоянии транзакции. И хотя они выполняют различные
действия, логическая структура этих методов одинакова.6 В [5] хорошо описан класс PersistentObject и уровни взаимодействия с базой данных,
хотя идея использования такого класса появилась гораздо раньше.7 Некоторые вопросы расширения класса PersistentObject обсуждаются ниже. Если
класс, представляющий понятие предметной области, расширяет класс технических служб, то
это приводит к смешиванию архитектурных уровней (базы данных и логики приложения).
Глава 38. Проектирование каркаса взаимодействия с базой данных на основе шаблонов 663public void commit ()
{switch ( state ){case OLD_DIRTY:// ...
break;
case OLD_CLEAN:// . . .
break;public void roolback()
{switch ( state ){case OLD_DIRTY:// ...
break;
case OLD_CLEAN:/ / ...
break;Чтобы многократно не использовать для решения поставленной задачи условные
операторы, можно воспользоваться шаблоном State (Состояние) из набора GoF.Шаблон StateКонтекст/ПроблемаПоведение объекта зависит от его состояния, а его методы содержат условную
логику, отражающую выполнение различных действий в зависимости от состоя¬
ния объекта. Существует ли альтернатива традиционной условной логике?РешениеДля каждого состояния создать отдельный класс (класс состояния) со стандарт¬
ным интерфейсом. Делегировать зависящие от состояния операции от контекст¬
ного объекта объекту его текущего состояния. Удостовериться, что контекстный
объект всегда указывает на объект текущего состояния.Рис. 38.14 иллюстрирует применение этого шаблона к подсистеме взаимодействия
с базой данных.Выполнение зависящих от состояния методов класса PersistentObject делеги¬
руется соответствующему объекту состояния. Если контекстный объект указывает на
состояние OldDirtyState, значит, при реализации метода commit объект будет мо¬
дифицирован в базе данных, а самому контекстному объекту будет присвоена ссылка
на состояние OldCleanState. Если же контекстный объект указывает на состояние
OldCleanState, то при реализации метода commit не будут выполнены никакие дей¬
ствия.Обратите внимание, что диаграмма классов на рис. 38.14 соответствует диаграмме
состояний на рис. 38.12. Шаблон State — один из механизмов программной реализа¬
ции модели перехода состояний8. Он обеспечивает переход объекта в различные со¬
стояния в ответ на внешние события.С точки зрения производительности, следует отметить, что классы состояний
(по иронии судьбы) не зависят от состояния. Поэтому нет необходимости создавать
несколько экземпляров объектов таких классов — каждый такой класс содержит по
единственному экземпляру. Тысячи объектов, подлежащих хранению в базе данных,
могут ссылаться на один и тот же экземпляр OldDirtyState.8 Существуют и другие механизмы, в том числе условная логика, интерпретаторы состояний
и генераторы кода на основе таблиц состояний.
664 Часть V. Третья итерация фазы развития{state.delete(this)}(state.rollback(this) TbPersistentObjeat
oid : OIDstate : PObjectStatecommit () /o'
delete () d
ф rollback ()
save () o'setState(PObjectState)b(state.commit(this)}b11 по умолчанию операции// не выполняются11 так обозначаетсяП тело метода(state.save(this)}PObjectStatebcommit(obj:PersistentObject)
delete(obj:PersistentObject)
rollback(obj:PersistentObject)
save(obj:PersistentObject)ProductDescriptionSale( // подтверждение ШPersistenceFacade.getlnstance().update(obj
obj.setState(OldCleanState.getlnstance()){ // отмена ™PersistenceFacade.getlnstance().reload(obj
obj.setState(OldCleanState.getlnstance()){ 11 удалениеobj.setState(OldDeletestate.getlnstanfce({ // сохранение
obj.setState(OldDirtyState.getlnstanfce()b-I IOldDirtyStateOldCleanStateNewStateOldDeleteStatecommit (...)
delete (...)
rollback (...)
 0delete (...)
save (...)commit (...)commit (...)
rollback (...)Qk.. : \{ // подтверждение ^PersistenceFacade.getlnstance().insert(obj)
obj.setState(OldCleanState.
getlnstance()) }( // подтверждениеbk
PersistenceFacade.getlnstance(
delete(obj)
obj.setState(DeletedState.getlnstance())Puc. 38.14. Применение шаблона State938.17. Обработка транзакций на основе
шаблона CommandВ предыдущем разделе транзакции рассматривались несколько упрощенно. В этом
разделе обсуждение транзакций будет продолжено, при этом будут освещены все во¬
просы, связанные с проектированием их обработки. Нестрого говоря, транзакция —9 Класс Deleted не изображен на этой диаграмме с целью экономии места.
Глава 38. Проектирование каркаса взаимодействия с базой данных на основе шаблонов 665это единица работы или набор задач, которые должны быть выполнены или отмене¬
ны одновременно, т.е. транзакцию можно рассматривать как атомарную операцию.В терминах службы взаимодействия с базой данных к задачам транзакции отно¬
сятся добавление, удаление и модификация объектов. В рамках одной транзакции
может быть добавлено два объекта, удалено три и один модифицирован. Для пред¬
ставления этих операций вводят класс Transaction [5]10. Как указывается в [53], по¬
рядок выполнения задач в рамках одной транзакции может повлиять на ее успешное
выполнение (и производительность).Можно привести следующие примеры.1. Допустим, база данных имеет ограничение целостности ссылок, которое сво¬
дится к следующему. При обновлении записи в таблице ТаЫеА, содержащей
внешний ключ к записи в таблице TableB, соответствующая запись в TableB
должна существовать.2. Транзакция включает задачу INSERT, согласно которой в таблицу TableB добав¬
ляется запись, и задачу UPDATE по добавлению записи в таблицу TableA. Если
операция UPDATE выполняется раньше, чем INSERT, то может возникнуть нару¬
шение целостности ссылок.Упорядоченность задач взаимодействия с базой данных может обеспечить зна¬
чительные преимущества. Некоторые вопросы упорядочения зависят от структуры
базы данных, но в целом стратегия такова: сначала выполняются операции добавле¬
ния, затем обновления, и, наконец, удаления.Нужно иметь в виду, что порядок задач в рамках транзакции может оказаться не
оптимальным с точки зрения их выполнения. Эти задачи необходимо переупорядо¬
чить до начала выполнения.Такую проблему решает шаблон Command (Команда) из набора GoF.Шаблон CommandКонтекст/ПроблемаКак обрабатывать запросы или задачи, требующие предварительной сортировки
(расстановки приоритетов), очередности, регистрации или задержки?РешениеДля каждой задачи создать класс, реализующий общий интерфейс.Это достаточно простой шаблон, имеющий множество полезных приложений.
При его использовании действия становятся объектами, а значит, их можно сорти¬
ровать, регистрировать, ставить в очередь и т.д. Например, на рис. 38.15 показаны
классы для операций с базой данных, созданные на основе шаблона Command.Обработка транзакций включает множество других вопросов, но основная идея
этого раздела состоит в представлении каждой задачи или действия в виде объекта
с полиморфным методом execute. Это повышает уровень гибкости при обработке
запросов.10 В [53] такой класс назван UnitOfWork.
666 Часть V. Третья итерация фазы развитияЗамечательным примером применения шаблона Command является реализа¬
ция команд графического интерфейса пользователя, подобных вырезанию и встав¬
ке. Например, метод execute объекта CutCommand выполняет вырезание, а метод
undo — отменяет его. Для отмены операции объекту CutCommand требуются исходные
данные. Все команды графического интерфейса пользователя поддерживают стек вы¬
полняемых действий, поэтому каждое действие можно отменить.Еще одним примером использования шаблона Command является обработка
запросов в серверной части приложения. При получении сообщения серверный
объект создает объект-команду для этого запроса и передает ее специальному объекту
CommandProcessor [17], который регистрирует, упорядочивает и выполняет команды.Transactioncommands : Listcommit () O''addDelete(obj: PersistentObject)
addlnsert(obj: PersistentObject)
addUpdate(obj: PersistentObject)
sort() 0 qsort()for each ICommand cmd
cmd.execute()} >1..*<<interface>>ICommandexecute()
undo ()...TИспользуйте объекты sortstrategy
чтобы обеспечить возможность
применения различных алгоритмов
сортировки объектов CommandВ данном примере при
отмене команд не
выполняется никаких
действий. Однако в более
сложных случаях
полиморфная операция
отмены команды
добавляется в каждый
подкласс, которому
известно,как такую
операцию нужно выполнитьcommands.add(new DBUpdateCommand(obj));DBCommandobject:PersistentObjectexecute() {abstract}
undo(){leaf}“A“1 1PersistentObjectcommit()Это может быть
простой вызов метода
объект.commit(),
однако каждый объект
может выполнять
и свои собственные
действияDBUpdateCommandDBInsertCommandDBDeleteCommand> execute()execute()execute()Рис. 38.15. Классы команд для операций с базой данных
Глава 38. Проектирование каркаса взаимодействия с базой данных на основе шаблонов 66738.18. Пассивная материализация
на основе шаблона Virtual ProxyЗачастую желательно отложить процесс материализации объекта на как мож¬
но более поздний срок обычно из соображений повышения производительности.
Допустим, что объекты ProductDescription ссылаются на объект Manufacturer,
который должен извлекаться из базы данных очень редко. Информация о производи¬
теле требуется только в том случае, если этот производитель вводит скидки на свои
товары.Отсроченная во времени материализация “дочерних” объектов называется пас¬
сивной материализацией (lazy materialization) и может выполняться с использованием
шаблона Virtual Proxy (Виртуальный объект-посредник) из набора GoF, представляю¬
щего собой одну из многих вариаций шаблона Proxy.Виртуальный объект-посредник — это объект-посредник для другого объекта
(реального объекта (real subject)), материализующий реальный объект при первом его
использовании. Таким образом, реализуется пассивная материализация. Виртуальный
объект-посредник — это “облегченный” объект, используемый вместо реального объек¬
та, который к настоящему времени может оказаться еще не материализованным.Конкретный пример использования шаблона Virtual Proxy для классов
ProductDescription и Manufacturer представлен на рис. 38.16. Это проектное ре¬
шение основано на предположении, что объекты-посредники знают идентификато¬
ры своих реальных объектов и при необходимости материализации используют их
для идентификации и извлечения реальных объектов.Обратите внимание, что видимость между экземплярами ProductDescription
и IManufacturer обеспечивается посредством атрибутов. Имя производителя для
данного экземпляра ProductDescription может еще не быть материализовано
в оперативной памяти. При отправке объектом ProductDescription сообщения
getAddress объекту-посреднику ManufacturerProxy (как материализованному объек¬
ту) объект-посредник материализует реальный экземпляр Manufacturer на основе
его идентификатора.Кто создает виртуальные объекты-посредникиИз рис. 38.16 видно, что виртуальный объект-посредник ManufacturerProxy вза¬
имодействует с объектом PersistenceFacade с целью материализации объектов. Но
какой класс должен отвечать за создание объектов ManufacturerProxy? Класс-преоб¬
разователь в структуру базы данных для объекта ProductDescription. Класс-преобра¬
зователь определяет момент материализации объекта, решает, какие из дочерних
объектов должны быть материализованы немедленно, а какие подлежат пассивной
материализации с использованием объектов-посредников.Рассмотрим два альтернативных решения: активную и пассивную материализа¬
цию.
668 Часть V. Третья итерация фазы развитияФактически ссылается
на экземплярManufacturerProxyPersis tentObjectoidProductSpecificationmanufacturer:IManufacturergeManufacturerAddress():Address{return menufacturer.getAddress
}О<<interface>>IManufacturergetAddress()—Q ManufacturerProxyrealSubject: IManufacturer.9 - getRealSubject():IManufacturer
+ getAddress(). .return getRealSubject().getAddress();1 _—ePuc. 38.16. Виртуальный объект-посредник для класса Manufacturer11 Активная материализация объекта Manufacturerclass ProductDescriptionRDBMapper extends AbstractPersistenceMapper
{protected Object getObjectFromStorage(OID oid){ResultSet rs =RDBOperations.getlnstance().getProductDescriptionData(oid);ProductDescription ps = new ProductDescription();
ps.setPrice(rs.getDouble("PRICE"));// основные операции выполняются здесь{ Цif (realSubject==null)
realSubj ect=PersistenceFacade.get(oid,Manufacturer.class);
return realSubject;
 «\1 >ManufactureraddressrealSubjectgetAddress()
Глава 38. Проектирование каркаса взаимодействия с базой данных на основе шаблонов 669String manufacturerForeignKey = rs.getString(MMANU_OID");OID manuOID = new OID(manufacturerForeignKey);
ps.setManufacturer ( (IManufacturer)PersistenceFacade.getlnstance().get(manuOID,Manufacturer.class);}Приведем решение на основе пассивной материализации.// Пассивная материализация объекта Manufacturerclass ProductDescriptionRDBMapper extends AbstractPersistenceMapper
{protected Object getObjectFromStorage (OID oid){ResultSet rs =RDBOperations.getlnstance().getProductDescriptionData(oid);ProductDescription ps = new ProductDescription();
ps.setPrice(rs.getDouble("PRICE"));// основные операции выполняются здесьString manufacturerForeignKey = rs.getString("MANU_OID");OID manuOID = new OID(manufacturerForeignKey);ps.setManufacturer( new ManufacturerProxy(manuOID));}Реализация виртуального объекта-посредникаРеализация виртуального объекта-посредника зависит от языка программирова¬
ния. Подробное рассмотрение этого вопроса не входит в задачи этой главы, поэтому
рассмотрим лишь общие принципы его реализации на разных языках.Язык Реализация виртуального объекта-посредникаC++ Определяется шаблонный класс “интеллектуальных” указателей. Определение интер¬фейса manufacturer не требуетсяJava Реализуется класс ManufacturerProxy. Определяется интерфейс Imanufacturer.Однако эти классы обычно не программируются вручную. Создается генератор кода,
анализирующий реальные классы (например, Manufacturer), и генерируются объектыIManufacturer И ProxyManufacturer.Еще одной альтернативой для языка Java является использование программного интер¬
фейса Dynamic ProxySmalltalk Определяется виртуальный трансформируемый объект-посредник, который для преоб¬
разования в реальный объект использует определения #doesNotunderstand: и
#become:. Определения интерфейса manufacturer не требуется
670 Часть V. Третья итерация фазы развития38.19. Представление отношений в таблицахВ предыдущем примере для ссылки на запись в таблице MANUFACTURER исполь¬
зуется внешний ключ MANU OID из таблицы PRODUCT SPEC. Возникает вопрос: как
представить взаимоотношения объектов в реляционной модели?Ответ на этот вопрос дает шаблон Representing Object Relationships as Tables
(Представление взаимосвязей объектов в виде таблиц) [28], который сводится к сле¬
дующему.■ Ассоциации “один к одному”.• Поместить идентификатор объекта OID в качестве внешнего ключа в одну
или обе таблицы, представляющие взаимосвязанные объекты.• Либо создать ассоциативную таблицу с идентификаторами каждого объекта,
участвующего во взаимоотношении.■ Ассоциации “один ко многим”.• Создать ассоциативную таблицу с идентификаторами каждого объекта, уча¬
ствующего во взаимоотношении.■ Ассоциации “многие ко многим”.• Создать ассоциативную таблицу, содержащую идентификаторы каждого объ¬
екта, участвующего во взаимоотношении.38.20. Суперкласс PersistentObjectОдним из типичных проектных решений при работе с постоянно хранимы¬
ми объектами является создание абстрактного суперкласса технических служб
PersistentObject, от которого наследуют свои свойства все другие объекты, пред¬
назначенные для постоянного хранения (рис. 38.17). В таком классе обычно опреде¬
ляются атрибуты для обеспечения постоянного хранения, в том числе идентифика¬
тор объекта, а также методы его сохранения в базе данных.Такой подход нельзя назвать неверным, однако он отличается сильным связыва¬
нием конкретного класса с классом PersistentObject, поскольку классы, реализую¬
щие понятия предметной области, наследуют свойства класса технических служб.Persis tentObjectA~ProductDescriptionВозможное проектное решение. Однако
оно оказывается проблематичным,
поскольку приводит к зацеплению и
смешиванию классов технических служб
с объектами, реализующими понятия
предметной области и логику
приложенияРис. 38.17. Проблемы, связанные с использованием суперкласса PersistentObject
Глава 38. Проектирование каркаса взаимодействия с базой данных на основе шаблонов 671Такое проектное решение не соответствует идее разделения обязанностей: обя¬
занности технических служб смешиваются с задачами объектов уровня логики при¬
ложения.Однако “разделение обязанностей” — это не конечная цель, к которой необхо¬
димо стремиться любой ценой. Как указывалось при описании шаблона Protected
Variations, разработчики должны выработать свою позицию и стараться избежать не¬
устойчивости проектного решения. Если в данном конкретном приложении наследо¬
вание свойств класса PersistentObject приводит к простому и прозрачному реше¬
нию и не создает проблем с поддержкой существующих классов, то почему бы его не
использовать? Ответ на этот вопрос зависит от требований и проектного решения
данного приложения. Определенное влияние на принятие такого решения оказывает
выбор языка программирования: языки, поддерживающие одиночное наследование
(такие как Java), допускают использование одного общего суперкласса.38.21. Нерешенные вопросыВ этой главе мы очень кратко рассмотрели проблемы и проектные решения по
созданию каркаса взаимодействия с базой данных и соответствующих служб. Однако
многие важные вопросы остались “за кадром”, в том числе следующие.■ Дематериализация объектов.• В двух словах этот процесс можно реализовать так. Конкретные преобразова¬
тели должны включать метод putObjectToStorage. При дематериализации
сложных иерархических объектов необходимо обеспечить взаимодействие
нескольких преобразователей и поддержку ассоциативных таблиц (при ис¬
пользовании реляционной базы данных).■ Материализация и дематериализация коллекций.■ Запросы на группы объектов.■ Полная обработка транзакций.■ Обработка ошибок при взаимодействии с базой данных.■ Принципы совместного использования данных многими пользователями и
стратегии блокировки данных.■ Вопросы безопасности — контроль доступа к базе данных.
Документирование архитектуры
с помощью N+1 представленияУ них есть компьютеры и может быть другое оружие массового поражения.Официальный отчет правительства СШАОсновные задачи■ Создать полезную документацию с описанием архитектуры на основе
ЛГ+1 (или 4+1) представления.■ Применить различные типы диаграмм UML.ВведениеКогда вырисовывается архитектура приложения, ее необходимо описать, чтобы
новые разработчики смогли ознакомиться с общей идеологией построения системы
и принять участие в ее разработке. В рамках UP архитектура описывается в специ¬
альном документе программной архитектуры (Software Architecture Document — SAD),
которому и посвящена данная глава.Что дальше?После построения каркаса взаимодействия с базой данных в данной главе
исследуются вопросы документирования архитектуры. В следующей главе речь
пойдет об управлении итеративной и гибкой разработко/\Диаграммы
развертывания
и компонентовРазработка
каркаса
взаимодействия
с базой данных о Документи¬рованиеархитектурыУправление
итеративной
и гибкой
разработкой—о—22 Зак. 3357
674 Часть V. Третья итерация фазы развития39.1. Документ SAD и архитектурные представленияДокумент SADПомимо диаграмм пакетов UML, классов и последовательностей, важным артефак¬
том модели проектирования в рамках UP является документ SAD. В нем описывают¬
ся важнейшие архитектурные решения. С его помощью разработчики могут ознако¬
миться с основными идеями, заложенными в систему. В документе SAD описываются
главные технические решения с помощью N+1 архитектурного представления UP.Зачем создавать документ SADЕсли в группу приходит новый разработчик, менеджер проекта может сразу на¬
править его на Web-узел проекта для ознакомления с документом SAD. Из этого до¬
кумента можно быстро получить общие сведения о системе.Поэтому при создании этого документа нужно задать себе вопрос: что бы я рас¬
сказал новому члену группы разработчиков, чтобы помочь ему поскорее войти в курс
дела?Архитектурные представленияРазработка архитектуры — это одна сторона вопроса, а ее описание — другая.В [82] предложены несколько представлений архитектуры. Основная идея архи¬
тектурного представления сводится к следующему.Архитектурное представлениеЭто представление архитектуры системы, в котором основное внимание уделяет¬
ся структуре, модулям, главным компонентам и потокам управления [112].Важным аспектом такого представления является мотивировка, объясняющая сде¬
ланный выбор.Архитектурное представление — это взгляд на систему с определенных позиций,
когда выделяются только основные идеи, а остальные отбрасываются.Архитектурное представление — это средство общения, изучения системы и ее
осмысления. Оно создается в виде текстового описания и диаграмм UML.Например, диаграммы пакетов и взаимодействия, описанные в главе 34, отражают
основные идеи логической структуры и программной архитектуры. В документе SAD
архитектор должен создать раздел Логическое представление, поместить в него эти
диаграммы UML и добавить некоторые комментарии, поясняющие назначение каж¬
дого пакета и уровня.Архитектурные представления призваны не предоставить полное описание неко¬
торого ракурса всей системы, а только отразить основные идеи. Они должны стро¬
иться по принципу “эскалатора”: в них должны содержаться лишь наиболее важные
идеи, которые можно пересказать своему коллеге, поднимаясь по эскалатору.Архитектурные представления можно разрабатывать на следующих этапах.
Глава 39. Документирование архитектуры с помощью Л/+1 представления 675■ После создания системы для следующих “поколений” разработчиков.■ После завершения очередного этапа разработки (например, в конце фазы раз¬
вития) для обучения разработчиков системы и новых членов команды.■ На ранних итерациях, в рамках проектирования системы.ЛН-1 (или 4+1) представлениеВ своей работе Крачтен (Cruchten) выделяет 4+1 представления, которые на се¬
годняшний день трансформировались в N+1 представление. Эта ситуация отражает
множество ракурсов системы. Изначально выделяли четыре архитектурных пред¬
ставления: логическое представление, представление процессов, развертывания и
данных. Они описаны в следующих разделах. Дополнительное представление — пред¬
ставление прецедентов — подытоживает все наиболее важные с точки зрения архи¬
тектуры прецеденты или сценарии, а также их реализацию. Представление преце¬
дентов придает завершенность описанию архитектуры и позволяет лучше понять
взаимосвязь других представлений.Детальное описание архитектурных представленийСуществует множество различных представлений, отражающих разные точки
зрения на архитектуру системы. Рассмотрим наиболее распространенные представ¬
ления.1. Логическое представление• Отражает концептуальную структуру программной системы в терминах уров¬
ней, подсистем, пакетов, каркасов, наиболее важных классов и интерфейсов.
В нем обобщается функциональность основных программных элементов, та¬
ких как подсистемы.• Отражает реализацию важных прецедентов (подобно диаграмме взаимодей¬
ствия), иллюстрирующих основные аспекты работы системы.• Это представление модели проектирования UP, построенное с использовани¬
ем обозначений пакетов UML, классов и диаграмм взаимодействия.2. Представление процессов• Отражает процессы и потоки, их обязанности, взаимодействие и размеще¬
ние логических элементов (уровней, классов, подсистем и т.д.).• Это представление модели проектирования UP, построенное с использова¬
нием обозначений пакетов UML, классов, диаграмм взаимодействия, а также
процессов и потоков.3. Представление развертывания• Отражает физическое распределение процессов и компонентов по процессо¬
рам и физическую конфигурацию сети.• Это представление модели развертывания UP, построенное с использовани¬
ем обозначений диаграмм развертывания UML. В этом представлении обыч¬
но отображается вся система, а не ее подмножество. Система обозначений
диаграммы развертывания UML описана в главе 37.
676 Часть V. Третья итерация фазы развития4. Представление данных• Отражает схему построения базы данных и преобразования объектного пред¬
ставления данных в реляционное, описывает хранимые процедуры и тригге¬
ры базы данных.• Это представление модели данных UP, построенное с использованием обо¬
значений диаграмм классов UML.• Потоки данных могут отображаться на диаграммах видов деятельности UML.5. Представление безопасности• Содержит краткое описание схем обеспечения безопасности, в том числе
HTTP-аутентификации и аутентификации базы данных.• Может быть представлено в виде модели развертывания UP, снабженной диа¬
граммами развертывания, на которых выделены ключевые моменты обеспе¬
чения безопасности.6. Представление реализации• Вспомним сначала определение модели реализации. В отличие от других мо¬
делей UP, представляющих собой диаграммы и текстовые описания, эта “мо¬
дель” включает исходный и выполняемый код системы. Она состоит из двух
частей: выполняемого кода и исходного кода с графическими ресурсами. В мо¬
дель реализации включаются также Web-страницы, библиотеки DLL и другие
элементы системы, в том числе пакеты Java и байт-код в виде файлов JAR.• В представление реализации включают краткое описание организации ис¬
ходного и выполняемого кода системы.• Это представление модели реализации UP, состоящее из текстового описа¬
ния и диаграмм пакетов и компонентов UML.7. Представление разработки• Содержит необходимую информацию о среде разработки. Например, в этом
представлении описываются организация файлов в каталоге, используемое
средство контроля версий и т.д.8. Представление прецедентов• Краткое описание наиболее архитектурно важных прецедентов и их нефунк¬
циональных требований. Реализация таких прецедентов затрагивает многие
архитектурно значимые элементы системы. В качестве примера можно при¬
вести прецедент Оформление продажи.• Это представление модели прецедентов UP, построенное с использованием
обозначений диаграмм прецедентов UML.Не забывайте о мотивацииКаждое представление включает не только диаграммы, но и поясняющий текст.
Зачастую при составлении документа SAD забывают описать мотивы тех или других
решений. Почему безопасность обеспечивается именно таким образом? Почему три
основных программных компонента размещаются на двух компьютерах, а не на трех?
На самом деле описание мотивировки зачастую является более важным, чем другие
разделы документа, когда возникает вопрос о внесении изменений в архитектуру.
Глава 39. Документирование архитектуры с помощью Л/+1 представления 67739.2. Структура документа SADВ контексте UP принят следующий формат документа SAD.Описание архитектуры программы
Архитектурное представление(Краткое описание структуры этого документа. Это полезно для читателей, не знакомых с идеей
технических описаний или представлений. Заметим, что все представления описывать не обяза¬
тельно.)Архитектурные факторы
(Сослаться на таблицу факторов в дополнительной спецификации.)Архитектурные решения
(Привести технические описания основных решений.)Логическое представление
(Диаграммы UML пакетов, классов и основных элементов. Основные элементы нужно проком¬
ментировать.)Представление развертывания
(Диаграммы развертывания UML, отражающие распределение процессов и компонентов по
узлам сети с комментариями по организации сети.)Представление процессов
(Диаграммы UML классов и взаимодействия, иллюстрирующие процессы и потоки в системе.
Взаимосвязанные потоки и процессы нужно сгруппировать, а их совместную работу прокоммен¬
тировать (например, с помощью RMI).)Представление прецедентов
(Краткое описание наиболее архитектурно важных прецедентов. Диаграммы взаимодействия
UML для реализаций некоторых архитектурно значимых прецедентов или их сценариев с ком¬
ментариями относительно основных архитектурных элементов.)Другие представления...39.3. Пример: описание архитектуры
POS-системы NextGenВ этом и последующих примерах не ставится задача привести исчерпывающее
описание архитектуры в документе SAD, а лишь проиллюстрировать стиль составле¬
ния этого документа.Описание программной архитектуры POS-системы NextGen
Архитектурное представлениеСодержит краткое описание различных аспектов архитектуры, в том числе:• логическое представление: ... краткое описание• представление данных: ...• представление процессов: ...
678 Часть V. Третья итерация фазы развитияКроме того, здесь содержатся ссылки на дополнительную спецификацию, в которой приводится
факторная таблица архитектурно важных требований.Каждое представление содержит описание мотивировки решений. Эти разделы особенно важны
при необходимости модификации архитектуры.Архитектурные факторы
Ссылка на таблицу факторов в дополнительной спецификации.Архитектурные решения (технические описания)Ссылка на таблицу факторов в дополнительной спецификации.Техническое описание
Надежность - восстановление информации при отказе удаленной службы.
Идея решения. Обеспечить прозрачный поиск нужной службы, переход от удаленной
службы к локальной и осуществить частичную репликацию локальной службы.
Факторы• Робастное восстановление при выходе из строя удаленной службы (системы складского
учета, системы вычисления налоговых платежей).• Робастное восстановление информации при выходе из строя удаленной базы данных с
описаниями товаров.РешениеРеализовать шаблон Protected Variations (Защищенные вариации) для защиты от влияния ме¬
стоположения службы с помощью интерфейса адаптера и объекта ServicesFactory. По воз¬
можности обеспечить локальную реализацию удаленных служб с упрощенным и ограниченным
поведением. Например, локальная система вычисления налогов может использовать фиксиро¬
ванные ставки налогов. Локальная база данных товаров может представлять собой небольшой
буфер с информацией о наиболее популярных товарах. Информацию для обновления системы
складского учета можно хранить локально и передавать удаленной системе после восстановле¬
ния соединения.Вопросы конкретной реализации этих решений описаны в разделе технической документации
“Адаптация — службы сторонних производителей”, поскольку реализации удаленных служб мо¬
гут изменяться.Для обеспечения качественного восстановления соединения с удаленными службами ис¬
пользуйте объекты-посредники, проверяющие дееспособность каждой удаленной службы и
перенаправляющие по возможности информацию напрямую удаленным службам.МотивировкаВладельцы магазинов не желают прекращать торговлю. Следовательно, в системе NextGen нуж¬
но предусмотреть высокий уровень надежности и возможность восстановления информации при
сбоях. Тогда она станет очень привлекательным продуктом, поскольку конкурирующие системы
такой возможности не обеспечивают. Небольшой размер буфера объясняется ограниченностью
ресурсов клиентских компьютеров. Системы налоговых платежей не устанавливаются на каждом
клиентском компьютере из-за высокой стоимости лицензии и сложности настройки (настройка
каждого рабочего места занимает почти неделю). Такое проектное решение обеспечивает точку
эволюции системы, и в будущем можно будет поместить службу вычисления налоговых плате¬
жей на каждом клиентском компьютере.Неразрешенные вопросы
Отсутствуют.Альтернативные решения
Обеспечение наивысшего уровня качества связи с удаленными службами авторизации платежей
по кредитной карточке для повышения надежности. Это возможно, но очень дорого.
Глава 39. Документирование архитектуры с помощью N+1 представления 679Техническое описание
Как обеспечить выполнение правил вычисления налоговых платежей?
Идея решения. Приобрести отдельный компонент для вычисления налоговых платежей.
Факторы...Другие технические описания ...Логическое представлениеДиаграмма пакетов показана на рис. 1.UISwingProcessSaleFrame\ DomainSalesRegister_V_SalePricingServiceAccessN\ServicesFactory/\1PaymentsCreditPaymentccinterface>>
ICreditAuthorization
ServiceAdapterInventory//—IUL <<interface>>
IInventory
AdapterPOSRuleEngine\POSRuleEngineFacadeTaxes<<interface>>ITaxCalculatorAdapterTechnical Services\4 \— 4I NPersistenceDBFacadeLog4JJessSOAPPuc. 1. Диаграмма пакетов для логического представления
680 Насть V. Третья итерация фазы развитияОбсуждение и мотивировкаИспользуется классическая многоуровневая архитектура. Между уровнями представления и
предметной области отсутствуют промежуточные уровни приложения и сеансов, поскольку си¬
стема является достаточно простой. Главный контроллер получает сообщения о системных опе¬
рациях от интерфейса пользователя. В роли контроллера выступает класс Register. На всякий
случай используется фасадный объект, обеспечивающий возможность изменения интерфейса в
будущем.Представление развертывания
Представление развертывания показано на рис. 2.Обсуждение и мотивировкаБаза данных товаров и система вычисления налоговых платежей размещаются на различных
компьютерах для повышения производительности и надежности работы системы. Вычисление
налоговых платежей ведется централизованно, а не дублируется на каждом терминале, посколь¬
ку эта система приобретается у стороннего производителя. Возможно, в будущем стоимость
этой системы снизится и она будет установлена на каждом терминале.
Глава 39. Документирование архитектуры с помощью N+1 представления 681Представление данных
Обсуждение и мотивировкаСценарий прецедента Оформление продажи — хороший пример для понимания потоков дан¬
ных в этом приложении. Потоки данных и способы их хранения иллюстрируются с помощью диа¬
граммы видов деятельности UML (рис. 3).Преобразование реляционного представления данных из базы данных Products в объекты Java
выполняется с помощью системы Hibernate.Преобразование данных о продажах, хранящихся в ERP-системе, осуществляется с помощью
специального адаптера NextGen. При этом данные трансформируются в формат XML.
Преобразование данных запросов о платежах, отправляемых внешней системе авторизации
платежей, в известный формат Visa выполняется с помощью специального адаптера NextGen.
Эти решения определяются с помощью внешних систем и баз данных, для которых необходимо
готовить информацию в специальном формате.Рис. 3. Потоки данных для сценария прецедента Оформление продажи
682 Часть V. Третья итерация фазы развитияПредставление прецедентовНаиболее важным с точки зрения архитектуры является описание прецедента Оформление
продажи, приведенное в главе 6. При реализации этого прецедента разрешается большинство
основных проблем и рисков. Главной системной операцией является enteritem (рис. 4).:Кассир: UI: :Swing::
Process
SaleJFrameenterltemi(id,qty) :Domain::
Sales::
Registerenteritem
(id,qty)
 to:Domain::
Products:
Product
Catalog11:Domain:::Tech-s:POSRule-Services::«subsystem»Domain::Engine::Persistence:::Tech-Sales::POSRule-Persistence¬ServicesSaleEngineFacade::JessFacadespec= j
getProduct)
Desc(id) i
 ►!makeLineltem
(spec,qty)desc=getObjectIIonPropertyEvent
(s,"sale.total",total)
 1 1 islnvalid
(lineltem
sale)
 tosomeJessCalls
(lineltem,sale)Puc. 4. Фрагмент реализации прецедента Оформление продажи
Другие представления...39.4. Пример: документ SAD для каркаса StrutsStruts — это популярный каркас с открытым кодом для обработки Web-запросов и
навигации между страницами на основе Java-технологии. В данном разделе рассма¬
тривается фрагмент документа SAD, детально иллюстрирующий логическое представ¬
ление.Документ SAD для каркаса Jakarta Struts
Архитектурное представлениеАрхитектурные факторы
Архитектурные решения
Глава 39. Документирование архитектуры с помощью А/+1 представления 683Логическое представлениеКаркас Struts и его подсистемы относятся к уровню интерфейса пользователя Web-приложения.
На рис. 1 показаны основные уровни и пакеты в виде диаграммы пакетов UML.Уровень интерфейса пользователя и управления приложениемПодсистема на основе каркаса StrutsВажные типы каркаса, ^
которые нужно учитыватьКонтейнерные
и вспомогательные
типыjavax.servlet J Уровень предметной области (бизнес-правил) • i Уровень технических службРис. 1. Основные уровни и пакеты каркаса StrutsСледует отличать уровень интерфейса пользователя, отвечающий за создание страниц и их со¬
держимого, и уровень управления приложением, компоненты которого реализуют потоки управ¬
ления и направляют команды от уровня представления другим компонентам системы. Обычно
каркасы Web-представлений включают реализацию управления приложением. Это же относится
и к каркасу Struts, в котором разработчики могут создавать подклассы класса Action, отвечаю¬
щие за реализацию потоков управления.Архитектурные шаблоныАрхитектур Struts основывается на шаблоне Model-View-Controller, при этом роли основных ком¬
понентов распределяются следующим образом.Controller — это многопоточный фасадный объект Singleton, отвечающий за получение и пере¬
направление HTTP-запросов, а также за взаимодействие с другими объектами и управление
потоками приложения.View — это компоненты, отвечающие за генерирование содержимого экрана (т.е. HTML-страниц).
Model — это компоненты, отвечающие за реализацию логики и состояние объектов предметной
области.Struts обеспечивает архитектурные решения по разделению потоков управления, содержимого и
логики приложения. При этом отдельные модули каркаса являются узко специализированными и
обладают высоким зацеплением.Реализация шаблона МУС в компонентах Struts представлена на рис. 2.
684 Часть V. Третья итерация фазы развитияКонтроллер. шОбъект-синглетон, получаю¬
щий и перенаправляющий
HTTP-запросы конкретному
экземпляру класса Action
на основе предопределен¬
ных преобразований
шаблонов URIСвязан с контроллером. ^Частично отвечает за управление по¬
током. Экземпляры подклассов воз¬
вращают экземпляр ActionForward,
определяющий для объекта Act ion-
Servlet адресата которому нужно
передать управление.Связан с моделью.Отвечает за перенаправление зап¬
росов объектов модели предметной
областиСвязан с видом. ^Экземпляры подклассов автомати¬
чески заполняются (объектом Action
Servlet) входными данными клиенте
ких форм на основе шаблона имено¬
вания свойств JavaBeans.Связан с моделью."Знает" о состоянии приложения.
Может использоваться для копирова¬
ния состояния в объекты из модели
предметной областиorg.apache.strutsaction "1d 1ActionServletdoGet (...)
doPost(...)
process (...)
processXXX(...)URI patternL1ч 0 ActionVГ° ActionFormГ 'execute(ActionForm,...):ActionForwardAВид. IСервлеты, автоматически
сгенерированные из страницы
JSP, которые формируют
и форматируют отображаемое
содержимоеMyDomainObject1 о"Чистая" модель. ^
Отвечает за состояния
приложения и его логикуРис. 2. Реализация шаблона МУС в компонентах StrutsСвязанные шаблоныОбъект ActionServlet функционирует как фасадный объект на уровне представления. Объект
Action возвращает ему объект Act ionForward, который используется для перехода на следу¬
ющий шаг.Объекты ActionServlet и Action иллюстрируют применение шаблона Command Processor,
который является разновидностью шаблона GoF Command. При этом объект ActionServlet
играет роль командного процессора, получающего запросы и передающего их объекту Action,
который и отвечает за их выполнение.В каркасе Struts реализованы шаблоны Front Controller и Business Delegate. Объект
ActionServlet выступает в роли внешнего контроллера или начальной точки обработки запро¬
сов, а объекты Action делегируют запросы объектам уровня предметной области.Объекты Action играют роль адаптеров при обращении к интерфейсам объектов уровня пред¬
метной области.Как видно из рис. 3, объект ActionServlet соответствует также шаблону Template Method.
Глава 39. Документирование архитектуры с помощью А/+1 представления 685Точки вариации каркасаКонфигурационный файл с отображениями, ш
которые определяют взаимосвязь между
классами ActionForm, Action И1Ж1.ЭТО
важная точка вариации, которая потоки
управления и отображения действия позволяет
разрешить с использованием декларативного
подхода на основе данныхstruts-config.xmlЗапускаетметод-шаблон,соответст¬вующийпроцессуШаблонTemplateMethodПодклю-1чаемыеметоды*org.apache.strutsaction |КActionServlet+doGet(...)+doPost(...)^process (...)
#processActionCreate(...)
#processActionPerform(...
#processXXX(...)7Г+execute(ActionForm,...):
ActionForwardXActionForm7sMyPresentationSubsystemMyActionServlet#processActionPerform(...)
 о MyActionl+execute(...):
 9 MyActionForml+getZipCode(): String
+setZipCode(String)Иногда для Ь
реализации конт¬
роллеров с раз¬
личным поведе¬
нием на основе
класса Action¬
Servlet созда¬
ются подклассы.
При этом пере-
опре деляется
метод из семейс¬
тва processXXXСоздание подклассов класса Action и пе-*
реопределение метода execute - это основ¬
ная точка вариации для настройки каркаса.
Этот метод вызывается объектом Action¬
Servlet. Именно здесь можно разместить
собственную логику управления приложе¬
нием, например, проверку входных данных
выбор требуемой страницы или действияСоздание подклас- ^
сов ActionForm и доба¬
вление методов доступа
к свойствам в стиле
JavaBeans - это важный
механизм передачи
входных данных форм
между объектами
HTTPRequest и объек¬
тами состоянийРис. 3. Точки вариации каркаса StrutsТочки вариации каркасаПри использовании каркаса главное — определить точки вариации, в которых разработчик мо¬
жет подключить дополнительные надстройки, реализующие поведение конкретного приложения.
Это делается с помощью механизма наследования, композиции на основе интерфейсов и де¬
кларативных ограничений, обычно определяемых во внешних файлах конфигурации (см. рис. 3).
Другие представления
686 Часть V. Третья итерация фазы развития39.5. Итеративное документирование архитектурыПроцесс UP и документ SADНачало. Если непонятно, насколько технически реально удовлетворить архи¬
тектурно значимые требования, можно реализовать проверку архитектурной концеп¬
ции (architectural proof-of-concept). В UP эта процедура называется архитектурным
синтезом (architectural synthesis). Она отличается от принятых в прежние времена
программных экспериментов, связанных с реализацией отдельных технических ре¬
шений. Архитектурный синтез позволяет проверить выполнимость архитектурно
значимых требований в комплексе.Развитие. Основная задача этой фазы — реализация наиболее сложных архитек¬
турных элементов, поэтому основные усилия по архитектурному анализу надо скон¬
центрировать именно на этой стадии. К ее завершению должны быть составлены та¬
блица факторов, технические описания и документ SAD.Передача. Хотя в идеале все архитектурные решения должны быть реализованы
задолго до этой фазы, следует просмотреть документ SAD, сверить описанную в нем
архитектуру с реальной и удостовериться в корректности описания системы.Последующая эволюция системы. Перед переходом к разработке новых версий
системы следует еще раз оценить архитектурные факторы и решения. Например, ре¬
шение по использованию в версии 1.0 единственного экземпляра системы вычисле¬
ния налоговых платежей, вызванное в свое время соображениями экономии, может
быть пересмотрено, поскольку со временем такие системы могут подешеветь. Тогда
в последующих версиях системы можно использовать локальные службы вычисления
налоговых платежей.39.6. Дополнительная литератураПомимо основной статьи [82] автор советует ознакомиться с работой Клеменса
(Clements) Documenting Software Architectures: Views and Beyond.
ЧастьVIСпециальные вопросыВ этой части...Глава 40. Еще раз об итеративной разработке и гибком
управлении проектом
1!I
Еще раз об итеративной
разработке и гибком
управлении проектомПредсказание— очень трудное дело, особенно если оно касается будущего.Автор неизвестенОсновные задачи■ Систематизировать требования и риски.■ Сопоставить и сравнить адаптивное и предиктивное планирование.ВведениеИтеративное и гибкое планирование проекта и вопросы управления — это доста¬
точно емкие проблемы. Тем не менее не лишним будет кратко рассмотреть некото¬
рые ключевые моменты итеративного процесса разработки, и в частности UP. К их
числу относятся следующие: что делать на следующей итерации? Как отслеживать
изменение требований к системе в итеративном процессе разработки? Как организо¬
вать артефакты проекта?Что дальше? После изучения вопросов документирования архитектуры в этой главерассматриваются вопросы управления итеративной и гибкой разработкой проектаРазработкакаркасавзаимодействия
с базой данныхо /Документи¬рованиеархитектурыУправление
итеративной
и гибкой
разработкой
—•—
690 Часть V. Третья итерация фазы развития40.1. Как спланировать итерациюСуществует много подходов к планированию итераций, но все они сводятся при¬
мерно к следующему.1. Сначала определяется длительность итерации. Обычно итерация длится от
двух до шести недель. Чем короче, тем лучше. Более длинные итерации исполь¬
зуются в больших коллективах разработчиков (возможно, географически рас¬
пределенных) и при высокой степени неопределенности в разработке проекта.
Если дата завершения итерации установлена, ее необходимо строго придержи¬
ваться. Однако если к запланированной дате коллектив не успевает выполнить
всю работу, количество задач можно сократить.2. Затем проводится совещание по планированию следующей итерации. Если те¬
кущая итерация завершается в пятницу, то именно в этот день проводится со¬
вещание по планированию следующей итерации, которая должна начаться в
понедельник. В идеале на подобной встрече должны присутствовать все заинте¬
ресованные лица: пользователи, разработчики, главный архитектор, менеджер
проекта и т.д.3. Составляется список потенциальных целей следующей итерации. Эти цели ран¬
жируются в соответствии с некоторыми приоритетами. Перечень целей обыч¬
но составляют потребители (они формулируют бизнес-цели проекта) совместно
с главным архитектором (он отвечает за формулировку технических целей).4. Каждый член команды разработчиков формирует свой индивидуальный график
работы (в часах или днях) для данной итерации (возможно, некоторые участ¬
ники проекта планируют идти в отпуск или брать отгулы). Все индивидуальные
графики обобщаются в рамках единой схемы.5. Одна из целей итерации (например, реализация прецедента) описывается во
всех деталях. Затем проводится семинар разработчиков, на котором методом
мозгового штурма определяются основные задачи по достижению этой цели.• Все задачи интегрируются в одну схему.6. Шаг 5 повторяется до тех пор, пока не будут рассмотрены все задачи итерации.
Если объем работ примерно соответствует имеющимся в наличии ресурсам и
задачи итерации могут быть выполнены в срок, семинар завершается.Обратите внимание, что при подобном гибком подходе к управлению проектами
разработчики активно привлекаются к процессу планирования и оценивания, а не
просто ставятся перед фактом.40.2. Адаптивное и предиктивное планированиеОдной из основных идей итеративной разработки является обеспечение адапта¬
ции за счет обратной связи, а не попытка составить детальный план реализации все¬
го проекта. Следовательно, в рамках UP детальный план составляется только на сле¬
дующую итерацию. Задачи остальных итераций определяются адаптивно с течением
времени (рис. 40.1). Помимо обеспечения гибкости, причиной такого планирования
является то, что при итеративной обработке сразу определяются не все требования,
Глава 40. Еще раз об итеративной разработке и гибком управлении проектом 691и в начале разработки не вырабатывается конкретное проектное решение.1 План со¬
ставляется с учетом мнения всей команды в процессе разработки. Допустим, в начале
проекта был разработан хорошо продуманный план реализации, а в процессе его вы¬
полнения стало ясно, как этот проект можно усовершенствовать. На первый взгляд,
такую ситуацию можно рассматривать как провал проекта, хотя на самом деле это
совсем не так.Тем не менее, необходимо определить основные цели и этапы проекта. При ите¬
ративной разработке не предполагается хаотического движения. Группа разработчи¬
ков должна знать основные этапы и задачи, однако детали реализации проекта могут
варьироваться. Например, для приложения NextGen можно поставить задачу: за три
месяца завершить реализацию прецедентов Оформление продажи, Возврат товара и
Аутентификация пользователей, а также разработать процедуру регистрации поль¬
зователей и подключения новых правил ценообразования. Однако детальные планы
реализации этих прецедентов разрабатываются по ходу проекта. Порядок действий и
задачи для каждой итерации на эти три месяца не фиксируются. Подробно планирует¬
ся только следующая двухнедельная итерация, и так, шаг за шагом, группа движется к
поставленной цели и намеченному сроку ее реализации. Естественно, порядок выпол¬
нения проекта определяется внутренними зависимостями компонентов и ресурсов, од¬
нако не все виды деятельности детально планируются на начальной стадии проекта.Заинтересованные лица должны одобрить план разработки (задачи на три меся¬
ца). Детальное планирование лучше всего возложить на плечи группы разработчи¬
ков, которые могут адаптивно учитывать новые обстоятельства (см. рис. 40.1).Проект находится в данной точке (посередине итерации)Адаптивная разработка позволяет
избежать детерминированного
планирования, т.е. деталей будущих
итераций. Лучше планировать лишь
одну или две последующих итерацийТребования умозрительно планируются
для слишком поздних итерацийА, БД,Е??в,Г?ОКИмеет смысл планировать следующую
итерацию и, возможно, часть еще одной
итерации. Остальное планирование
является умозрительным,
детерминированным и неадаптивнымКОНЕЦ ЭТАПА: дата (возможно, через два месяца) и набор
целей, которые должны быть достигнуты.При адаптивной итеративной разработке и планировании
стоит зафиксировать дату и цели на макроуровне, однако
путь их достижения не планируется подробно. Поиск лучшего
пути достижения целей выполняется адаптивноРис. 40.1. Важно определишь основные этапы проекта, но не следует составлять
детальный план на слишком длительный срок1 Точное проектное решение и детализированные требования в начале проекта не извест¬
ны даже в рамках “каскадной” разработки, хотя она предполагает детальное планирование все¬
го проекта.
692 Часть V. Третья итерация фазы развитияИ наконец, хотя в рамках UP предпочтение отдается адаптивному планированию
на одну итерацию, вполне возможно составить успешный план разработки системы
на две или три итерации вперед. При этом планы на более поздние сроки следует
считать менее надежными.40.3. Планы для фазы и итерацииНа макроуровне можно определить сроки и задачи основных этапов, на
микроуровне проработать план следующей итерации (например, на четыре недели
вперед). Эти два плана в UP описываются в “Плане фазы разработки” и “Плане ите¬
рации” — разделах “Плана разработки программного обеспечения”. План фазы опре¬
деляет основные задачи и сроки их выполнения, в том числе дату завершения дан¬
ной фазы и даты получения промежуточных результатов. План итерации определяет
задачи текущей и последующей итерации, но не всех итераций сразу (рис. 40.2).На начальной стадии сроки основных этапов являются весьма приблизительны¬
ми. На стадии развития эти оценки уточняются. Одной из задач фазы развития яв¬
ляется получение реалистичной информации о сроках реализации основных задач и
целях проекта.Короткий, длиной
несколько страниц.
Содержит примерную
дату завершения фазы и
этапов, а также
приблизительные цели,
которые должны быть
достигнутыJLНачалоРазвитиежПлан фазы—Конец этапаirКонстр!иронанио!ЖПередачаПлан итерацииДетальное планирование в
плане итерации касается
текущей деятельности и
' недалекого будущего
(например, следующей
итерации)Рис. 40.2. Планы для фазы и итерации
Глава 40. Еще раз об итеративной разработке и гибком управлении проектом 69340.4. Как составить план итерации с учетом
прецедентов и сценариевУнифицированный процесс разработки строится на основе прецедентов, поэто¬
му их реализации подчинена вся деятельность разработчиков. На каждой итерации
нужно реализовать один или несколько прецедентов или сценариев, если прецедент
достаточно сложен для реализации на одной итерации. Поскольку некоторые требо¬
вания не отражаются в прецедентах (например, регистрация и подключение правил
ценообразования), то эти свойства тоже должны быть реализованы на одной или не¬
скольких итерациях (рис. 40.3).Поскольку зачастую единицей планирования является сценарий, а не полный пре¬
цедент, требования тоже желательно систематизировать на уровне сценариев. При
этом возникает вопрос: как помечать сценарии? Ответ на этот вопрос достаточно
прост. Необходимо использовать предложенный Кокбурном формат полного описа¬
ния прецедентов. Например, рассмотрим следующий фрагмент прецедента./ / / / /1237ПрецедентОформлениепродажиУ \ПрецедентОформлениепродажиПрецедентОформлениепродажиV/,%==Прецедент или свойство
зачастую оказываются
слишком сложными, чтобы
завершить их реализацию в
течение одной короткой
итерации.Таким образом, реализацию
их различных частей или
сценариев нужно
распределить по различным
итерациямПрецедент
Вычисление
арендной платыСвойство:РегистрацияОшибка:В17шРис. 40.3. Распределение работы по итерациям
694 Часть V. Третья итерация фазы развитияПрецедент П1. Оформление продажиОсновной успешный сценарий (или основной процесс).1. Покупатель подходит к кассовому аппарату POS-системы с выбранными товарами.2. Кассир открывает новую продажу.3. Кассир вводит идентификатор товара.4. Система записывает наименование товара и выдает его описание, цену и общую стоимость.Цена вычисляется на основе набора правил.Кассир повторяет действия, описанные в пп. 3-4, для каждого наименования товара.5. Система вычисляет общую стоимость покупки с налогом.6. Кассир сообщает покупателю общую стоимость и предлагает оплатить покупку.7. Покупатель оплачивает покупку, система обрабатывает платеж.8. ...Расширения (или альтернативные потоки)7а. Оплата наличными.1. Кассир вводит предложенную покупателем сумму.2. Система вычисляет положенную сдачу и открывает кассу с наличностью.3. Кассир складывает поученные деньги и выдает сдачу покупателю.4. Система регистрирует платеж наличными.76. Оплата по кредитной карточке.1. Покупатель вводит информацию о своей кредитной карточке.2....7в. Оплата чеком.7г. Оплата по дебитной карточке.Сценарий этого прецедента, предполагающий оплату по кредитной карточке,
можно обозначить как Оформление продажи-7б. Именно это название можно исполь¬
зовать для отслеживания процесса разработки и создания отчетов.Задачи первых итераций определяются по результатам систематизации требова¬
ний. Например, прецедент Оформление продажи, безусловно, имеет очень высокий
приоритет. Следовательно, к нему нужно приступать на первой итерации. Тем не ме¬
нее, на этой итерации реализуются не все сценарии этого прецедента, а лишь самые
простые успешные сценарии, реализация которых затрагивает базовые элементы си¬
стемы, например оплату наличными.На следующих итерациях можно реализовать другие архитектурно важные тре¬
бования, связанные с этим прецедентом. При этом разработчики приступят к реа¬
лизации многих архитектурных аспектов системы: основных уровней, базы данных,
интерфейса пользователя и интерфейса между основными подсистемами. Таким об¬
разом, уже на ранних итерациях будут реализованы многие важные части системы —
в этом и состоит задача фазы развития.
Глава 40. Еще раз об итеративной разработке и гибком управлении проектом 69540.5. Приблизительность начальных оценокЧто посеешь, то и пожнешь. Оценки, построенные на основе ненадежной и не¬
четкой информации, сами являются нечеткими и ненадежными. В рамках UP одно¬
значно постулируется, что оценки, полученные на начальной стадии, не являются
окончательными (это касается всех методов, но в UP это явно провозглашается).
Ранние оценки лишь дают общее представление о целесообразности проекта, при
реализации которого можно будет получить более точные оценки. Более реалистич¬
ная информация появляется уже после первой итерации фазы развития. Оценки, по¬
лученные после второй итерации, уже вполне заслуживают доверия (рис. 40.4)./ /V уV /Начало/РгtЗВИТieКОНС7])уир(тамie7/ \Оценки, полученные на
начальной фазе,не
используются для
определения
продолжительности и
результатов всего проекта.
Они лишь дают реалистичную
оценку целесообразности
выполнения проектаВ конце первой итерации
фазы развития появляется
более правдоподобная
оценкаПосле двух итераций фазы
развития и на последующих
итерациях формируются
достаточно реалистичные
оценки возможности
успешного завершения всего
проекта и соответствующие
срокиРис. 40.4. Оценки и фазы проектаПолезные оценки можно получить только на итерациях стадии развития.Это не значит, что не нужно стремиться к точности оценок с самого начала. Если
это возможно — очень хорошо. Однако в большинстве случаев это не реально из-за
использования новых технологий, методик и других аспектов. Поэтому в UP реко¬
мендуется приступать к планированию проекта и бюджета по истечении нескольких
итераций разработки.40.6. Организация артефактов проектаВ UP артефакты организованы в терминах дисциплин. Модель прецедентов и до¬
полнительная спецификация являются частью дисциплины определения требований.
План разработки относится к дисциплине управления проектом и т.д. Следовательно,
в рабочем каталоге можно организовать папки, имена которых соответствуют назва¬
ниям дисциплин, и помещать в них соответствующие артефакты (рис. 40.5).
696 Часть V. Третья итерация фазы развитияВ NextGen POSна 01 Бизнес-моделированиеhC3 02 Требования # i -СО 03 Проектирование
I--C3 04 Реализация
НШ 05 Тестирование
НСЗ 06 Развертывание
j "03 07 Конфигурация Ь У И
hQ 08 Управление проектомd|||
03 ОкружениеjПрецеденты и другие
артефакты требований
помещаются в
соответствующую папкуАртефакты планирования
помещаются в папку
управления проектомРис. 40.5. Организация артефактов UP в папки в соответствии с дисциплинамиТакая организация применима для большинства артефактов, не относящихся к
стадии реализации. Некоторые артефакты стадии реализации, такие как база данных
или выполняемые файлы, обычно располагаются в других каталогах.СоветПосле каждой итерации используйте средство контроля версий для пометки и
фиксации состояния всех элементов папок проекта (включая исходный код).
Назовите эти версии артефактов “Развитие-1”, “Развитие-2” и т.д. Впоследствии
эти метки позволят оценить скорость реализации проекта и объем работ, выпол¬
ненный на каждой итерации.40.7. Вы не поняли принципов итеративного
планирования, если...■ Пытаетесь детально спланировать все итерации сразу, указав задачи каждой
итерации.■ Рассчитываете на надежность начальных оценок и строите на их основе дол¬
госрочные планы; считаете оценивание затрат тривиальной или не слишком
сложной задачей.■ На ранних итерациях решаете простые проблемы, не связанные с высокими
рисками.Если в вашей организации процесс планирования выглядит примерно так, как
описано ниже, значит, вы не поняли основных принципов планирования.1. На начальной стадии планирования на высоком уровне определяются новые
системы и средства, например “Web-система для управления финансами”.
Глава 40. Еще раз об итеративной разработке и гибком управлении проектом 6972. Менеджер по техническим вопросам в сжатые сроки оценивает затраты и дли¬
тельность сложных, дорогостоящих и рискованных проектов, разрабатываемых
с привлечением новых технологий.3. План и бюджет проекта составляются на год.4. Заинтересованные лица привлекаются в том случае, если реальный ход проекта
не соответствует первоначальным оценкам. Тогда осуществляется переход к п. 1.Такой подход не обладает итеративностью и реалистичностью, присущими уни¬
фицированному процессу разработки.40.8. Дополнительная литератураВ работе [84] содержится много полезных советов по организации процесса раз¬
работки, а также наглядно представлены недостатки каскадного процесса проектиро¬
вания и преимущества итеративных методов.В работе Organizational Patterns of Agile Software Development Коплиена (Coplien) и
Харрисона (Harrison) содержится богатая коллекция полезных советов по организа¬
ции успешного итеративного и гибкого процесса разработки, а также менеджменту
проектами.Работа Software Project Management: A Unified Framework Ройса (Royce) посвящена ите¬
ративной разработке в рамках UP, а также планированию и управлению проектами.В работе Surviving Object-Oriented Projects: A Manager's Guide Кокбурна (Cockburn) со¬
держится много полезной информации об итеративном планировании и переходу к
итеративной разработке систем на основе объектной технологии.Еще одним полезным источником информации является работа [14].В работе [81] несколько глав посвящены планированию и управлению проектами
в рамках UP.В качестве предостережения нужно отметить, что в некоторых книгах за словами
“итеративная разработка” и “унифицированный процесс проектирования” кроется
предиктивный или каскадный подход к планированию.В работе [92] дается прекрасный обзор многих методик и вопросов планирования
и управления проектом и рисками.
Артефакты унифицированного
процесса, шаблоны
GRASP и условные
обозначения языка UMLПримерный набор артефактов унифицированного
процесса и время их создания
(н - начало, р - развитие)ДисциплинаАртефактИтерация-*НачалоИРазвитиеЕ1..ЕпКонструи.
рование Т1 нт„
С1..СП T1Jn“Бизнес-модели¬Модель предметной областинрование”“Требования”Модель прецедентовнPВидение системынPДополнительная спецификациянPСловарь терминовнP“Проектирование”Модель проектирования
Описание архитектурыннPМодель данныхнР“Реализация”Модель реализациинР Р
700 Приложение АПример взаимосвязи артефактов
унифицированного процессаПримеры взаимосвязи артефактов унифицированного процесса
Модель предметной областиКонцептуальные
классы предметной
области в процессе
проектирования
определяют имена
некоторых
программных
классовSaleОбрабатываетсяRegisterProductCatalogdateTime1 1Понятия предметной области
Модель прецедентов:SystemДиаграммы прецедентовОформлениепродажи1. Покупатель
подходит2. Кассир
начинает
новую
продажу3. ...Прецеденты:КассирmakeNewSaleСистемныесобытия ►>enterltem
(id,quantity)Системные
диаграммы
последовательностей // Реализация \
прецедента \с использованиемМодель проектированиявзаимодеиствия:Register:ProductiCatalogmakeNewSale ienterltem
(id,quantity)createdesc=getDescription(id)addLine!tem(desc,quantity)Классы, спроектированные в процессе реализации
прецедентов, можно отобразить на диаграмме
классовRegistermakeNewSale()
enterltem(...) >1 catalogProductCataloggetDescription(...):ProductDescription
Артефакты унифицированного процесса, шаблоны GRASP и условные обозначения языка UML 701Основные шаблоны распределения
обязанностей (шаблоны GRASP)ШаблонОписаниеInformation ExpertCreatorControllerLow Coupling
(оценочный)High Cohesion
(оценочный)PolymorphismPure FabricationIndirectionProtected VariationsКакой класс обычно должен отвечать за выполнение обязанностей?Эта обязанность назначается информационному эксперту — классу, имеющему
информацию, которая необходима для выполнения обязанностиКто должен отвечать за создание экземпляров классов? (Шаблон Factory позволяет
получить альтернативное проектное решение.) Классу в назначается обязанность
по созданию экземпляров класса а, если выполняется одно из следующих условий.• Класс в содержит объекты а• Класс в агрегирует объекты а• Класс в обладает данными инициализации для объекта а• Класс в записывает экземпляры объектов а• Класс в активно использует объекты аКакой класс, не относящийся к уровню интерфейса пользователя, должен коор¬
динировать (контролировать) выполнение системных операций? Эта обязанность
назначается классу, удовлетворяющему одному из следующих условий.• Класс представляет всю систему, корневой объект, устройство или подсистему в
целом (внешний контроллер).• Класс представляет некоторый сценарий прецедента, в процессе выполнения
которого выполняются системные операции (контроллер прецедента или кон¬
троллер сеанса)Как можно снизить влияние изменений?Обязанности распределяются таким образом, чтобы степень связанности остава¬
лась низкой. Используйте этот принцип для оценки различных альтернатив про¬
ектных решенийКак обеспечить сфокусированность обязанностей объектов, простоту их интерфей¬
сов, возможность управления сложностью и обеспечение низкого связывания?
Обязанности распределяются таким образом, чтобы степень зацепления остава¬
лась высокой. Используйте этот принцип для оценки различных альтернатив про¬
ектных решенийКто должен выполнять обязанности, если поведение зависит от типа?Если поведение объектов одного типа (класса) может изменяться, обязанности
распределяются для различных вариантов поведения с использованием поли¬
морфных операций для этого классаЕсли у разработчика возникли проблемы, как можно обеспечить реализацию ша¬
блонов High Cohesion и Low Coupling?Создается искусственный класс, не представляющий конкретного понятия из
предметной области, т.е. синтезируется искусственная сущность для поддержки
высокого зацепления, слабого связывания и повторного использования. Этому
классу должны быть назначены обязанности с высокой степенью зацепленияКто должен обеспечить отсутствие прямого связывания?Вводится промежуточный объект для обеспечения связи между другими компо¬
нентами или службами, которые не связаны между собой напрямуюКак распределить обязанности между объектами, подсистемами и системами так,
чтобы вариации или нестабильность их элементов не оказывала отрицательного
влияния на другие элементы?Идентифицируются конкретные нестабильные точки. Обязанности распределя¬
ются таким образом, чтобы вокруг этих точек был создан “стабильный” интерфейс
702 Приложение АУсловные обозначения языка UMLДиаграммы классовАльтернативное
ОбозначениеШЬ
абстрактного класса
{abstract}АбстрактныйклассХ«interface»ИнтерфейсХоперация!()Конечныйклассdeaf}ОбобщениеРеализацияинтерфейсаОбъект-синглетонКлассУоперация!()АльтернативноеобозначениеЦМЬРеализацииинтерфейсахоперация!()ИнтерфейсХ ОЦелое' 1Ассоциации:КлассА1 Имя ассоциации ► 1роль-1Кратность:роль-2АссоциативныйКласс0 или
больше;
“много”1..40От одного 1..*
до сорокаКомпозицияClassX- атрибутКлассаИлиСтатическийАтрибут:Int
+ открытыйАтрибут:String- закрытыйАтрибутз акрытыйПоПредположениюАтрибут
инициализированныйАтрибут:Bool=true
коллекцияОбъектов:VeggieBurger [*]
атрибутСВозможнымНулевым
Значением:String [0..1]
конечныйАтрибут:Int=5 {readonly}
/производныйАтрибут+ методКлассаИлиСтатическийМетод()+ открытыйМетод()
открытыйПоПредположениюМетод()- закрытыйМетод()# защищенныйМетод()~ видимыйМетодПакета()«constructor» SuperClassFoo(Long)
методСПараметрами(parml:String, parm2:Float)
методСВозвращаемымЗначением():VeggieBurger
методГенерирущийИсключение(){exception IOException}
абстрактныйМетод()
абстрактныйМетод2() {abstract}
//альтернативное обозначение
конечныйМетод() {leaf}//не перекрывается в подклассах
синхронизованныйМетод() {guarded}класс I ОДИН или -5—1 класс Р°™°
 больше пятьdomain::ClassX оmyclock:RunnableПакет, содержащий
данный класстуСlock Я
Направление связиClockmyThread:Threadrun{)RunnableАктивный класс!Диаграммы прецедентов
Артефакты унифицированного процесса, шаблоны GRASP и условные обозначения языка UML 703Диаграммы последовательностей:ProductCatalog Гinitialize I
 ►,(|> Видимость обеспечивается посредствомиспользования шаблона проектирования Singletonpsa=getProductsAdapter:ServicesFactory
 ! Активный объект, реализующий
различные интерфейсыЬexternalService:
DBProductsAdapter ! create(externalService)ЧЭ—loop jpsa:LocalProducts
{active}[всегда],.-0 A:products =
getProductUpdates(;¥—I—В Java вызов ^метода run интерфейса
Runnable рассматривается
как асинхронное сообщение.
Такие сообщения
обозначаются с помощью
стрелки другого видаЕсли методы запускаются в другом
потоке, соответствующее выражение
UMLHa диаграммепоследовательностей может начинаться
с имени или символьного обозначения
потока. Например, все сообщения,
обрабатываемые в потоке LocalProduct
будут помечаться символом а //это сообщение обрабатывается!
//в своем собственном потоке
{всегда выполняется циклически:- "засыпает" на N минут- обновляет буфер}: A: В: СdoXopt7alt[цвет = красный]
doAdoBdoCauthenticate(id)ref^AuthenticateUsersd AuthenticateUser7authenticate(id)doMldoM2Диаграммы коммуникациипервоеСообщениеanX:ClassX1:сообщение1(anX) —►2:[цвет = красный]:сообщение2()st = getSubtotalИтерация по всем
элементам коллекцииpi:Personlineltems[i]:
SalesLineltem
ПриложениеСловарь терминовАбстрактный класс(Abstract class)OID Идентификатор объекта.Private Спецификатор закрытой области. Обычно в закрытой об¬
ласти объявляются все атрибуты и некоторые методы.Public Спецификатор открытой области. Обычно в открытой
области объявляются некоторые методы, но не атрибуты.Класс, который можно использовать только в качестве
суперкласса для некоторых других классов. Такой класс
не может иметь экземпляров, кроме экземпляров произ¬
водных классов.Абстракция (Abstraction) Выделение важных или общих свойств подобных поня¬
тий, а также выделение в результате важных характери¬
стик сущности.Агрегация (Aggregation) Свойство ассоциации, представляющей отношение “це¬
лое-часть”, и (обычно) ограничение времени жизни ча¬
стей временем жизни целого.Активный объект Объект, для которого существует отдельный поток управ-
(Active object) ления.Анализ (Analysis) Исследование предметной области, которое приводит к
созданию моделей, описывающих статические и динами¬
ческие характеристики ее объектов. Этот процесс при¬
зван ответить на вопрос “Что?”, а не на вопрос “Как?”.Архитектура (Architecture) Описание организации и структуры системы. При раз¬
работке программных систем рассматривается несколько
различных уровней архитектуры, начиная с физической
или аппаратной архитектуры и заканчивая логической
архитектурой каркасов приложения.Описание набора однородных связей между объектами
двух классов.Именованная характеристика или свойство класса.Ассоциация (Association)
Атрибут (Attribute)23 3ak. 3357
706 Приложение БАтрибут класса(Class attribute)Видимость (Visibility)Делегирование(Delegation)Закрытая область(Private)Идентичность объекта(Object identity)Иерархия классов(Class hierarchy)Инкапсуляция(Encapsulation)Инстанцирование(Instantiation)Интерфейс (Interface)Квалифицированнаяассоциация(Qualified association)Класс (Class)Классификация(Classification)Композитный класс(Composition)Конкретный класс(Concrete class)Конструктор(Constructor)Контейнерный класс(Container class)Характеристика или свойство, общее для всех экземпля¬
ров класса. Эта информация обычно хранится в опреде¬
лении класса.Способность видеть другой объект или ссылаться на него.Передача сообщения другому объекту при получении со¬
общения. Таким образом, первый объект делегирует свои
обязанности второму объекту.Механизм ограничения доступа к членам класса со сторо¬
ны других объектов. Обычно в закрытой области объяв¬
ляются все атрибуты и некоторые методы.Свойство объекта, состоящее в том, что существование
объекта не зависит от любых значений, связанных с этим
объектом.Описание отношений наследования между классами.Механизм, используемый для сокрытия данных, внутренней
структуры и деталей реализации некоторого элемента, тако¬
го как объект или подсистема. Все взаимодействие с объек¬
том выполняется через открытый интерфейс операций.Создание экземпляра класса.Набор сигнатур открытых операций.Ассоциация, участники которой определяются значением
квалификатора.В языке UML это “описание набора объектов с общими
атрибутами, операциями, методами, взаимосвязями и по¬
ведением” [107]. Данный термин можно использовать
для представления программных или концептуальных
элементов.Определяет отношение между классом и его экземпляра¬
ми. Соответствие классификации (classification mapping)
устанавливает расширение класса.Класс, каждый экземпляр которого состоит из объектов
других классов.Класс, который может иметь экземпляры.Специальный метод, вызываемый при создании экзем¬
пляра класса в языке C++ или Java. Зачастую конструктор
выполняет инициализацию объекта.Класс, разработанный для поддержки выполнения опера¬
ций с набором объектов.
Словарь терминов 707Каркас (Framework)Кооперация(Collaboration)Кратность (Multiplicity)
Метамодель (Metamodel)Метод (Method)Метод класса(Class method)Метод экземпляра(Instance method)Модель (Model)Наследование(Derivation)Наследование(Inheritance)Обобщение(Generalization)Набор взаимодействующих абстрактных и конкретных
классов, который можно использовать в качестве ша¬
блона для решения группы взаимосвязанных проблем.
Каркас обычно дополняется производными классами с
конкретным поведением.Взаимодействие двух или нескольких объектов в рамках
отношения “клиент/сервер” для реализации некоторой
службы.Допустимое число объектов, принимающих участие в не¬
которой ассоциации.Модель, определяющая другие модели. Метамодель UML
определяет типы элементов языка UML, такие как клас¬
сификатор.В UML это конкретная реализация алгоритма выполне¬
ния операции для некоторого класса. Неформально это
программная процедура, которая выполняется в ответ на
сообщение.Метод, определяющий поведение самого класса, а не его
экземпляров.Метод, действие которого распространяется на один эк¬
земпляр. Реализуется путем передачи сообщения данному
экземпляру.Описание статических или динамических характерис¬
тик системы, представленное с различных точек зрения
(обычно в текстовом виде или в виде диаграмм).Процесс определения нового класса на основе свойств
существующего класса и добавления к нему новых атрибу¬
тов и методов. Существующий класс при этом называется
суперклассом, а новый — подклассом или производным
классом.Возможность объектно-ориентированных языков про¬
граммирования, благодаря которой можно создавать
специализированные подклассы на основе более общих
суперклассов. Атрибуты и методы суперклассов автомати¬
чески присваиваются производным классам.Выявление общих свойств понятий и определение прин¬
ципов взаимодействия суперкласса (общего понятия) и
подклассов (специализированных понятий). Это способ
классификации понятий, который затем отражается в ие¬
рархии классов. Концептуальные подклассы и суперклас¬
сы связаны отношением “обобщение-специализация”.
708 Приложение БОбъект (Object)Объект, подлежащий
постоянному хранению(Persistent object)Объектно-ориентированноепроектирование(Object-oriented design)Объектно-ориентированныйанализ(Object-oriented analysis)Объектно-
ориентированный язык
программирования(Object-oriented
programming language)Обязанность(Responsibility)Ограничение(Constraint)Операция (Operation)Описание операции(Contract)Открытая область(Public)Переменная экземпляра(Instance variable)Переход (Transition)В UML это экземпляр класса, инкапсулирующий опреде¬
ленное состояние или поведение. Неформально это при¬
мер некоторой сущности.Объект, время жизни которого может превышать время
жизни процесса или потока, в котором он был создан.
Такие объекты существуют до момента их явного удаления.Определение логики программного решения в терминах
программных объектов, а именно — их классов, атрибу¬
тов, методов и их взаимодействия.Исследование предметной области или системы в терми¬
нах понятий предметной области, таких как концептуаль¬
ные классы, ассоциации и изменение состояний.Язык программирования, поддерживающий принципы
инкапсуляции, наследования и полиморфизма.Услуга или набор услуг, обеспечиваемых некоторым эле¬
ментом (например, классом или подсистемой). Обязан¬
ность охватывает одну или несколько задач или обяза¬
тельств элемента.Ограничение или условие, налагаемое на элемент.В UML это “спецификация преобразования или запроса,
выполняемого объектом” [107]. Операция имеет сигнату¬
ру, определяемую ее именем и параметрами, и выполня¬
ется посредством передачи сообщения. Метод — это реа¬
лизация операции со специфическим алгоритмом.Описание обязанностей и постусловий, реализуемых при
выполнении операции или метода. Используется также
для обозначения множества всех условий, связанных с
интерфейсом.Механизм обеспечения доступа к членам класса со сто¬
роны других объектов. Обычно в открытой области объ¬
являются некоторые методы, но не атрибуты, поскольку
открытость атрибутов нарушает принцип инкапсуляции.Атрибут экземпляра, используемый в Java или Smalltalk.Взаимосвязь между состояниями, активизирующаяся в ре¬
зультате некоторого события или выполнения некоторых
условий.
Словарь терминов 709Переход состояний(State transition)Подкласс (Subclass)Подтип (Subtype)Полиморфизм(Polymorphism)Полиморфная операция(Polymorphic operation)Получатель (Receiver)
Понятие (Concept)Постоянный носитель(Persistence)Постусловие(Post-condition)Предметная область(Domain)Предусловие(Pre-condition)Проектирование(Design)Рекурсивная ассоциация(Recursive association)Роль (Role)
Связывание (Coupling)Связь (Link)
Событие (Event)Изменение состояния объекта. Нечто, о чем сигнализи¬
руют события.Класс, являющийся специализацией другого класса (су¬
перкласса). Подкласс наследует атрибуты и методы супер¬
класса.Концептуальный подкласс. Специализация другого типа
(супертипа), согласованная с супертипом.Возможность разной реакции различных классов или объ¬
ектов на одно и то же сообщение, основанная на исполь¬
зовании полиморфных операций. Возможность опреде¬
лять полиморфные операции.Операция, которая по-разному реализуется различными
классами.Объект, которому отправляется сообщение.Категория идей или предметов. В данной книге исполь¬
зуется для определения понятий реального мира, в отли¬
чие от программных сущностей. Понятие определяется
своими атрибутами, операциями и семантикой. Понятие
в широком смысле (concept’s extension) — это набор эк¬
земпляров или примеров объектов, описываемых данным
понятием. Зачастую используется в качестве синонима
термина “класс”.Место постоянного хранения состояний объекта.Ограничение, которое должно соблюдаться после выпол¬
нения операции.Формальная область, определяющая объект или сферу
интересов.Ограничение, которое должно соблюдаться до начала вы¬
полнения операции.Процесс разработки спецификации для реализации си¬
стемы на основе результатов анализа. Логическое описа¬
ние принципов работы системы.Ассоциация, в которой классы начального и конечного
объектов совпадают.Именованный конец ассоциации, указывающий ее задачу.Зависимость между элементами (обычно — классами, па¬
кетами или подсистемами), вызываемая взаимодействием
между элементами для реализации службы.Наличие связи между двумя объектами; экземпляр ассоци¬
ации.Важное действие или стечение обстоятельств.
710 Приложение БСообщение (Message)Состояние (State)
Суперкласс (Superclass)Супертип (Supertype)Сущность (Intension)Чистые данные(Pure data values)Шаблон (Pattern)
Экземпляр (Instance)Средство “общения” между объектами; обычно — запрос
на выполнение метода.Содержание объекта между событиями.Класс, от которого другие классы наследуют атрибуты и
методы.Концептуальный суперкласс. Задает более общий тип в
отношении “общее-частное”; объект, имеющий подтипы.Определение понятия.Типы данных, для которых не играют роли идентичность
каждого отдельного экземпляра, например числа, логиче¬
ские значения и строки.Именованное описание проблемы, ее решения, области
применения этого решения и способов его применения
в новых ситуациях.Отдельный член класса, в UML называемый объектом.
Литература1. Abbott, R. Program Design by Informal English Descriptions. Communications of the ACM,
vol. 26(11), 1983.2. Alexander, C, Ishikawa, S. and Silverstein, M. 1977. A Pattern Language—Towns-Building-
Construction. Oxford University Press.3. Ambler, S. The Unified Process — Elaboration Phase. Lawrence, KA.: R&D Books, 2000.4. Ambler, S., Constantine, L. Enterprise-Ready Object IDs. The Unified Process — Construction
Phase. Lawrence, KA.: R&D Books, 2000.5. Ambler, S. Whitepaper: The Design of a Robust Persistence Layer For Relational Databases,
www.ambysoft.com, 2000.6. Ambler, S. Agile Modeling, John Wiley & Sons, 2002.7. Beedle, М., Devos, М., Sharon, Y., Schwaber, K. and Sutherland, J. SCRUM: A Pattern
Language for Hyperproductive Software Development. Pattern Languages of Program Design.
vol. 4. Reading, MA.: Addison-Wesley, 2000.8. Beck, K. and Cunningham, W. Using Pattern Languages for Object-Oriented Programs.
Tektronix Technical Report No. CR-87-43, 1987.9. Beck, K., and Cunningham, W. A Laboratory for Object-oriented Thinking. Proceedings of
OOPSLA 89. SIGPLAN Notices, Vol. 24, № 10, 1989.10. Bass, L., Clements, P., and Kazman, R. Software Architecture in Practice. Reading, MA.:
Addison-Wesley, 1998.11. Beck, K. Patterns and Software Development. Dr. Dobbs Journal. Feb 1994.12. Beck, K. Extreme Programming Explained— Embrace Change. Reading, MA.: Addison-
Wesley, 2000.13. Bell, A. Death by UML Fever. ACM Queue. March 2004.14. Beck, K., Fowler, M. Planning Extreme Programming. Reading, MA.: Addison-Wesley,
2000.15. Bjnirner, D., and Jones, C. editors. The Vienna Development Method: The Meta-Language,
Lecture Notes in Computer Science, vol. 61. Springer-Verlag, 1978.16. Booch, G., Jacobson, I., and Rumbaugh, J. The UML specification documents. Santa
Clara, CA.: Rational Software Corp., 1997. (Спецификацию можно найти по адресу
www.rational.com.)17. Buschmann, F., Meunier, R., Rohnert, H., Sommerlad, P., and Stal, M. Pattern-Oriented
Software Architecture: A System of Patterns. West Sussex, England: Wiley, 1996.18. Boehm. B. A Spiral Model of Software Development and Enhancement. IEEE Computer. May
1988.
712 Литература19. Boehm, В., et al. Software Cost Estimation with COCOMO II. Englewood Cliffs, NJ.:
Prentice-Hall, 2000.20. Booch, G. Object-Oriented Design. Ada Letters vol. 1(3,. 1982.21. Booch, G. Object-Oriented Analysis and Design. Redwood City, CA.: Benjamin/Cummings,
1994.22. Booch, G. Object Solutions: Managing the Object-Oriented Project. Menlo Park, CA.:
Addison-Wesley, 1996.23. Boehm, B., and Papaccio, P. Understanding and Controlling Software Costs. IEEE
Transactions on Software Engineering. Oct 1988.24. Booch, G., Rumbaugh, J, and Jacobson, I., The Unified Modeling Language User Guide.
Reading, MA.: Addison-Wesley, 1999.25. Brooks, F. The Mythical Man-Month. Reading, MA.: Addison-Wesley, 1975.26. Brown, К. Описание шаблона Convert Exception, (http://c2.com.), 2001.27. Brown, K., and Whitenack, B. Crossing Chasms, A Pattern Language for Object-RDBMS
Integration, White Paper, Knowledge Systems Corp., 1995.28. Brown, K, and Whitenack, B. Crossing Chasms. Pattern Languages of Program Design vol.2. Reading, MA.: Addison-Wesley, 1996.29. Cook, S., and Daniels, J. Designing Object Systems. Englewood Cliffs, NJ.: Prentice-Hall,
1994.30. Coad, P., De Luca, J., Lefebvre, E. Java Modeling in Color with UML. Englewood Cliffs,
NJ.: Prentice-Hall, 1999.31. Constantine, L, and Lockwood, L. Software for Use: A Practical Guide to the Models and
Methods of Usage-Centered Design. Reading, MA.: Addison-Wesley, 1999.32. Constantine, L., Myers, G, and Stevens, W. Structured Design. IBM Systems Journal, vol.
13 (No. 2, 1974), pp. 115-139, 1974.33. Coad, P. Object-oriented Patterns. Communications of the ACM, Sept. 1992.34. Coad, P. Object Models: Strategies, Patterns and Applications. Englewood Cliffs, NJ.:
Prentice-Hall, 1995.35. Cockburn, A. Using Natural Language as a Metaphoric Basis for Object-Oriented Modeling
and Programming. IBM Technical Report TR-36.0002, 1992.36. Cockburn, A. Structuring Use Cases with Goals. Journal of Object-Oriented Programming,
Sep-Oct, and Nov-Dee. SIGS Publications, 1997.37. Cockburn, A. Writing Effective Use Cases. Reading, MA.: Addison-Wesley, 2001.38. Coleman, D., et al. Object-Oriented Development: The Fusion Method. Englewood Cliffs,
NJ.: Prentice-Hall, 1994.39. Constantine. L. Segmentation and Design Strategies for Modular Programming. In Barnett
and Constantine (eds.), Modular Programming: Proceedings of a National Symposium.
Cambridge, MA.: Information & Systems Press, 1968.40. Constantine, L. Essentially Speaking. Software Development May. CMP Media, 1994.41. Conway, M. Proposal for a Universal Computer-Oriented Language. Communications of the
ACM. 5-8 Volume 1, Number 10, October, 1958.42. Coplien, J. The History of Patterns.(Cm. http://c2.com/cgi/wiki7HistoryOfPatterns.), 1995.
Литература 71343. Coplien, J. A Generative Development-Process Pattern Language. Pattern Languages of
Program Design vol. 1. Reading, MA.: Addison-Wesley, 1995.44. Coplien, J., and Schmidt, D., eds. Pattern Languages of Program Design vol. 1. Reading,
MA.: Addison-Wesley, 1995.45. Cunningham, W. EPISODES: A Pattern Language of Competitive Development. Pattern
Languages of Program Design vol. 2. Reading, MA.: Addison-Wesley, 1996.46. Cutter Group. Report: The Corporate Use of Object Technology, 1997.47. Corbato, F, and Vyssotsky, V. Introduction and overview of the Multics system. AFIPS
Conference Proceedings 27, 185-196, 1965.48. Dijkstra, E. The Structure of the THE-Multiprogramming System. Communications of the
ACM, 11(5), 1968.49. Eck, D. The Most Complex Machine. A К Paters Ltd., 1995.50. Fowler, M. Analysis Patterns: Reusable Object Models. Reading, MA.: Addison-Wesley,
1996.51. Fowler, M. Refactoring: Improving the Design of Existing Code. Reading, MA.: Addison-
Wesley, 1999.52. Fowler, M. Put Your Process on a Diet Software Development. December. CMP Media,
2000.53. Fowler, M. Draft patterns on object-relational persistence services.(Cm. www.martin-fowler.com.), 2001.54. Fowler, M. Patterns of Enterprise Application Architecture. Reading, MA.: Addison-Wesley,
2002. (Мартин Фаулер, Архитектура корпоративных программных приложений, пер.
с англ., ИД “Вильямс”, 2004 г. )55. Fowler, М. UML Distilled, 3rd edition. Reading, MA.: Addison-Wesley. 2003.56. Schulte, R. Three-Tier Computing Architectures and Beyond. Published Report Note
R-401-134. Gartner Group, 1995.57. Gemstone Corp. Описание набора архитектурных шаблонов.
(www.javasuccess.com.), 2000.58. Gamma, Е., Helm, R., Johnson, R., and Vlissides, J. Design Patterns. Reading, MA.:
Addison-Wesley, 1995.59. Gilb, T. Principles of Software Engineering Management. Reading, MA.: Addison-Wesley,
1988.60. Guiney, E., and Kulak, D. Use Cases: Requirements in Context. Reading, MA.: Addison-
Wesley, 2000.61. Goldberg, A., and Kay, A. Smalltalk-72 Instruction Manual. Xerox Palo Alto Research
Center, 1976.62. Guthrie, R., and Larman, С .Java 2 Performance and Idiom Guide. Englewood Cliffs, NJ.:
Prentice-Hall, 2000.63. Grady, R. Practical Software Metrics for Project Management and Process Improvement.
Englewood Cliffs, NJ.: Prentice-Hall, 1992.64. Grosso, W. Описание шаблонов проектирования, (http://c2.com.), 2000.65. Gause, D., and Weinberg, G. Exploring Requirements. NY, NY.: Dorset House, 1989.66. Harrison, N. Patterns for Logging Diagnostic Messages. Pattern Languages of Program
Design vol. 3. Reading, MA.: Addison-Wesley, 1998.
714 Литература67. Hay, D. Data Model Patterns: Conventions of Thought. NY, NY.: Dorset House, 1996.68. Highsmith, J. Adaptive Software Development: A Collaborative Approach to Managing Complex
Systems. NY, NY: Dorset House, 2000.69. Hohman, L. Beyond Software Architecture: Creating and Sustaining Winning Solutions.
Reading, MA.: Addison-Wesley, 2003.70. Hofmeister, C, Nord, R., and Soni, D. Applied Software Architecture. Reading, MA:
Addison-Wesley, 2000.71. Jackson, M. Software Requirements and Specification. NY, NY: ACM Press, 1995.72. Jacobson, I., et al. Object-Oriented Software Engineering: A Use Case Driven Approach.
Reading, MA.: Addison-Wesley, 1992.73. Jeffries, R., Anderson, A., Hendrickson, C. Extreme Programming Installed. Reading,
MA.: Addison-Wesley, 2000.74. Jacobson, I., Booch, G., and Rumbaugh, J. The Unified Software Development Process.
Reading, MA.: Addison-Wesley,. 1999.75. Johnson, J. ROI— Its Your Job, XP 2002, Sardinia, Italy, 2002.76. Jones, C. Applied Software Measurement. NY, NY: McGraw-Hill, 1997.77. Jones, C. Estimating Software Costs. NY, NY.: McGraw-Hill, 1998.78. Kay, A. FLEX, a flexible extensible language. M. Sc. thesis, Electrical Engineering,
University of Utah. May. (Univ. Microfilms), 1968.79. Kruchten, P, and Larman, C. How to Fail with the Rational Unified Process: 7 Steps to Pain
and Suffering (in German), Objekt Spektrum. June 2001.80. Kovitz, B. Practical Software Requirements. Greenwich, СТ.: Manning, 1999.81. Kruchten, P. The Rational Unified Process— An Introduction, 2nd edition. Reading, MA.:
Addison-Wesley, 2000.82. Kruchten, P. The 4+1 View Model of Architecture. IEEE Software 12(6), 1995.83. Lakos, J. Large-Scale C++ Software Design. Reading, MA.: Addison-Wesley, 1996.84. Larman, C. Agile and Iterative Development: A Manager's Guide. Reading, MA.: Addison-
Wesley, 2003.85. Larman, C. What UML Is and Isn’t. JavaPro Magazine. March 2004.86. Larman, C, and Basili, V. Iterative and Incremental Development: A Brief History, IEEE
Computer, June 2003.87. Lieberherr, K., Holland, I and Riel, A. Object-Oriented Programming: An Objective Sense of
Style. OOPSLA 88 Conference Proceedings. NY, NY: ACM SIGPLAN, 1988.88. Liskov, B. Data Abstraction and Hierarchy, SIGPLAN Notices, 23,5 (May, 1988).89. Leffingwell, D., and Widrig, D. Managing Software Requirements: A Unified Approach.
Reading, MA.: Addison-Wesley, 2000.90. MacCormack, A. Product-Development Practices That Work. MIT Sloan Management
Review. Volume 42, Number 2, 2001.91. Martin, R. Designing Object-Oriented C++ Applications Using the Booch Method. Englewood
Cliffs, NJ.: Prentice-Hall, 1995.92. McConnell, S. Rapid Development. Redmond, WA.: Microsoft Press, 1996.93. Meyer, B. Object-Oriented Software Construction, first edition. Englewood Cliffs, NJ.:
Prentice-Hall, 1988.
Литература 71594. Martin, J., and Odell, J. Object-Oriented Methods: A Foundation. Englewood Cliffs, NJ.:
Prentice-Hall, 1995.95. Moreno, A.M. Object Oriented Analysis from Textual Specifications. Proceedings of the
9th International Conference on Software Engineering and Knowledge Engineering,
Madrid, June 17-20 (1997).96. McMenamin, S., and Palmer, J. Essential Systems Analysis. Englewood Cliffs, NJ:
Prentice-Hall, 1984.97. The Merriam-Webster Dictionary. Springfield, MA.: Merriam-Webster, 1989.98. Nixon, R. Six Crises. NY, NY.: Touchstone Press, 1990.99. UML 2.0 Infrastructure Specification, www.omg.org, Object Management Group, 2003.100. UML 2.0 Superstructure Specification, www.omg.org, Object Management Group, 2003.101. Parkinson, N. Parkinson's Law: The Pursuit of Progress, London, John Murray, 1958.102. Parnas, D. On the Criteria To Be Used in Decomposing Systems Into Modules, Communications
of the ACM, Vol. 5, No. 12, December 1972.103. Putnam, L., and Myers, W. 1992. Measures for Excellence: Reliable Software on Time, Within
Budget. Yourdon Press.104. Pree, W. Design Patterns for Object-Oriented Software Development. Reading, MA.: Addison-
Wesley, 1995.105. Renzel, K. Error Handling for Business Information Systems: A Pattern Language. (Статью
можно найти по адресу http://www.objectarchitects.de/arcus/cookbook/
exhandling/.), 1997.106. Rising, L. Pattern Almanac 2000. Reading, MA.: Addison-Wesley.107. Rumbaugh, J, Jacobson, I., and Booch, G. The Unified Modeling Language Reference
Manual. Reading, MA.: Addison-Wesley, 1999.108. Rumbaugh, J, Jacobson, I., and Booch, G. The Unified Modeling Language Reference
Manual, 2e. Reading, MA.: Addison-Wesley, 2004.109. Ross, R. The Business Rule Book: Classifying, Defining and Modeling Rules. Business Rule
Solutions Inc., 1997.110. Royce, W. Managing the Development of Large Software Systems. Proceedings of IEEE
WESCON. Aug 1970.111. Rumbaugh, J., et al. Object-Oriented Modelling and Design. Englewood Cliffs, NJ.:
Prentice-Hall, 1991.112. The Rational Unified Process Product. (Интерактивная документация по унифици¬
рованному процессу RUP.)113. Rumbaugh, J. Models Through the Development Process. Journal of Object-Oriented
Programming May 1997. NY, NY: SIGS Publications.114. Shaw, M. Some Patterns for Software Architectures. Pattern Languages of Program Design
vol. 2. Reading, MA.: Addison-Wesley, 1996.115. Tim Johnson. Chaos: Charting: the Seas of Information Technology. Published Report. The
Standish Group, 1994.116. Schneider, G., and Winters, J. Applying Use Cases: A Practical Guide. Reading, MA.:
Addison-Wesley, 1998.117. Thomas, M. IT Projects Sink or Swim. British Computer Society Review, 2001.
716 Литература118. Tsichiritzis, D., and Klug, A. The ANSI/ХЗ/SPARC DBMS framework: Report of the study
group on database management systems. Information Systems, 3, 1978.119. Tufte, E. The Visual Display of Quantitative Information. Graphics Press, 1992.120. Vlissides, J., et al. Patterns Languages of Program Design vol. 2. Reading, MA.: Addison-
Wesley, 1996.121. Wirfs-Brock, R. Designing Scenarios: Making the Case for a Use Case Framework. Smalltalk
Report Nov-Dee 1993. NY, NY: SIGS Publications, 1993.122. Warmer, J., and Kleppe, A. The Object Constraint Language: Precise Modeling With UML.
Reading, MA.: Addison-Wesley, 1999.123. Wirfs-Brock, R., and McKean, A. Object Design: Roles, Responsibilities, and Collaborations.
Reading, MA.: Addison-Wesley, 2002.124. Wirfs-Brock, R., Wilkerson, B., and Wiener, L. Designing Object-Oriented Software.
Englewood Cliffs, NJ.: Prentice-Hall, 1990.
Предметный указательСимволы100% Rule, 535АAbstractclass, 289; 541; 705
Factory, шаблон, 617
use case, 519
Abstraction, 705
Action, 500
Activation bar, 258
Active
class, 267; 297
object, 267; 297; 604; 705
Activity diagram, 500; 501
Actor, 96; 100Adapter, шаблон, 448; 460; 601
Adaptive Software Development, 48
Addition use case, 519
Aggregation, 292; 705
Agile
Alliance, 59
development, 58
modeling, 38; 60
UP, 62
Analysis, 33; 705
Application logic, 228
Architectural
baseline, 162proof-of-concept, 577; 686
prototype, 162
synthesis, 577; 686
Architecturally significant requirement, 565
Architecture, 705
Artifact, 64
Association, 183; 705
class, 294
Associative class, 545
Asynchronous message, 266
Attribute, 190; 705
visibility, 389вBase use case, 519
Black-box use case, 116
Bloated controller, 338
BOM, 168Boundary object, 334
Business
modeling, 65
object model, 168
rule, 91; 151сCache Management, шаблон, 660
CASE-средство, 243; 422
Centralized Error Logging, шаблон, 609
Class, 706
attribute, 706
diagram, 277
hierarchy, 428; 543; 706
method, 707
Classification, 706
Classifier, 40; 280
Cohesion, 341
Collaboration, 707
diagram, 36
Command, шаблон, 341; 665
Comment, 284Communication diagram, 246; 252
Composite, шаблон, 475
Composition, 320; 706
Concept, 709
Conceptual
class partition, 536
object model, 35
perspective, 39
Concrete
class, 706
use case, 115; 519
Conflict resolution strategy, 475
Constraint, 285; 288; 708
Construction, 63
Constructor, 391; 706
718 Предметный указательContainer, 575
class, 706
Context object, 472
Continuous integration, 47
Contract, 708
Controller, объект, 330
Controller, шаблон, 309; 329; 354; 437; 587;
701Control object, 334
Convert Exceptions, шаблон, 607
CORBA, спецификация, 611
Coupling, 289; 313; 326; 709
Coverage, 163
CRC card, 248Creator, шаблон, 309; 319; 355; 437; 701DData
dictionary, 91; 149
flow diagram, 501
model, 170
type, 193
Data-driven design, 465
DatabaseBroker, шаблон, 650
design, 33
engine, 641
DCD, 278
Decision, 503
Delegation, 706
Event Model (DEM), 493
Dependency line, 231
Deployment
architecture, 228
diagram, 247
Derivation, 707
Derived attribute, 192
Design, 33; 65; 709
by contract, 223
class diagram, 37; 278
model, 65; 278
Development Case, 68
Device node, 640
DFD, 501Diagnostic Logger, шаблон, 609
Direct mapping, 650
Discipline, 64Domain, 709
layer, 236
model, 35; 65Object Factory, шаблон, 636
rule, 151Don’t Talk to Strangers, шаблон, 453
DSDM, 48
Dynamic
model, 246
modeling, 251
view, 37EEager initialization, 468
Eclipse, 243
EEN, 640
Eiffel, 223
Elaboration, 63; 161
Elementary Business Process (EBP), 121
Encapsulation, 706
Entity object, 334
Error, 606
Dialog, шаблон, 610
Essential use case, 114
Event, 508; 709
Evo, 70Evolution point, 455; 563; 572
Executable architecture, 162
Execution specification bar, 258
Expert, шаблон, 437
Extension, 170Extreme Programming (XP), 47; 70; 400; 410FFacade controller, 333
Factory, шаблон, 464; 601
Failure, 606
Fault, 606
Feature, 91Feature-Driven Development, 48
Final class, 289
Foreign key attribute, 196
Fork, 500Forward engineering, 422
Frame, 260
Framework, 645; 707
Function point, 210
FURPS+, модель, 100; 565
Предметный указатель 719GGeneralization, 288; 428; 519; 532; 707
Generalization-specialization type
hierarchy, 532
Global visibility, 392
Glossary, 91; 136; 149
GRASP, 305; 307; 318; 353HHibernate, 74High Cohesion, шаблон, 309; 341; 437; 701
iImplementation perspective, 39
Inception, 63Indirection, шаблон, 437; 449; 701
Indirect mapping, 651
Information Expert, шаблон, 309; 321; 357;
701Inheritance, 288; 543; 707
Initial domain object, 371
Instance, 710
method, 707
variable, 708
Instantiation, 706
Intension, 170
Interaction
diagram, 251; 252
frame, 207
Interface, 291; 440; 706
realization, 291
Is-а Rule, 535
ISO 9126, 90; 566
Issue card, 570
Iteration, 48
plan, 63
Iterative development, 48JJavaMessaging Service(JMS), 574
Native Interface (JNI), 617
JavaPOS, 615
Join, 500JUnit, каркас модульного тестирования, 411кKeyword, 286LLaw of Demeter, шаблон, 453
Layer, 228Layers, шаблон, 341; 575
Lazy
initialization, 468
materialization, 667
Lean Development, 48
Link, 269; 709
Local visibility, 391
Logical architecture, 228
Low Coupling, шаблон, 309; 326; 437; 701мMediator, шаблон, 451
Merge, 503
Message, 710
Metaclass, 265
Metadata, 149
Metamodel, 707
UML, 38
Method, 221; 285; 286; 707
Microsoft Transaction Service, 575
Model, 707
driven architecture, 39
Model-View Separation, шаблон, 238; 487;
596Multiplicity, 186; 707
MVS, 235NName The Problem Not The Thrower,
шаблон, 607
Note, 284оO-R mapping service, 645
Object, 500; 708
Constraint Language (OCL), 217; 222
design, 33
identifier, 648
Identifier, шаблон, 648
720 Предметный указательidentity, 706Management Group (OMG), 42
Modeling Technique (OMT), метод, 42
Object-oriented
analysis, 33; 708
design, 708
programming, 34
language, 708
Object-Oriented Software Engineering
(OOSE), метод, 42
Observer, шаблон, 485
OCL, 217; 222; 293
OCP, принцип, 457
Offstage actor, 100
OID, 705Open-Closed Principle, 457
Operating system, 640
Operation, 221; 708
specification, 221OS, 640pPackage, 485
diagram, 247
Parameterized type, 295
Parameter visibility, 390
Partition, 237; 500
Pattern, 30; 306; 710
of assigning responsibilities, 305
Persistent
framework, 645
object, 644; 708
Petri net, 506
Phase plan, 63
Physical design, 632
Polymorphic operation, 709
Polymorphism, 437; 438; 701; 709
POS-система, 76
Postcondition, 108; 709
Precondition, 108; 709
Primary actor, 100
Private, 281
Profile, 38Proof-of-concept programming, 226
Property string, 288Protected Variations, шаблон, 451; 571;
678; 701Proxy, шаблон, 611
Public, 281Publish-Subscribe, шаблон, 487
Pure
data values, 710Fabrication, шаблон, 341; 437; 445; 701QQualified association, 294; 552; 706
Qualifier, 294; 552
Quality attribute, 91; 141RRational Unified Process (RUP), 46
RDD, 304
Receiver, 709
Recursive association, 709
Refactoring, 47; 243; 413
Reference, 264
Reflexive association, 553
Remote Proxy, шаблон, 611
Representing Objects as Tables, шаблон, 647
Requirement, 65; 88
analysis, 33
Resource adapter, 461
Responsibility, 116; 304; 708
assignment, 32
Responsibility-driven design, 247; 304
Reverse engineering, 422
Risk, 163
RMI, 611
Role, 185; 709Round-trip engineering, 422RUP, унифицированный процесс, 46sSAD, 673
Scenario, 96
Scrum, 31; 47; 58Secure Electronic Transaction (SET), 624
SEI, институт, 92
Sequence
diagram, 36; 206; 246; 252
number, 270
Signature, 221
Singleton, шаблон, 392; 466
Предметный указательSocket notation, 291
Software
architecture, 231
architecture
document (SAD), 576; 673
development process, 46
Engineering Institute (SEI), 565
Specification perspective, 39
State, 508; 710
transition, 709
шаблон, 221; 661
State-independent object, 509
Static
model, 246
object modeling, 277
view, 37
Stereotype, 124; 270; 287
Strategy, шаблон, 471
Structural property, 280
Struts, каркас, 682
Subclass, 532; 709
Subfunction-level use case, 107
Subtype, 709
Superclass, 428; 532Supplementary specification, 65; 91; 136Supporting actor, 100SWEBOK, 92Symbol, 170Systembehavior, 206
event, 206
feature, 146
operation, 206; 213
operation
contract, 211
sequence diagram, 206; 524
use case, 107тTag, 287Tagged value, 270
Technical
memo, 570
service, 228
Template, 295
Method, шаблон, 653
Test-driven development, 47; 58Test-first programming, 70; 400; 410
Thread, 266Three-tier architecture, 594
Token, 506Transition, 63; 508; 708
Two-tier architecture, 595иUML profile, 648
UnifiedModeling Language (UML), 30; 37
Process (UP), 31; 46
UnifiedPOS, 615
Unit testing, 410UP, унифицированный процесс, 46
Business Object Model, 201
Use-case, 31; 98
controller, 333
driven development, 128
instance, 97
model, 65; 91; 98
User-goal level use case, 107vValue object, 194
Variation point, 455; 563
Virtualmachine, 640
Proxy, шаблон, 667
Visibility, 278; 288; 358; 389; 706
Vision, 91
Visual Studio, 243wWaterfall lifecycle, 52
Web-браузер, 641
Wiki, 245AАбстрактный
класс, 289; 541; 705
класс-фабрика, 619
прецедент, 519
Абстракция, 168; 705
Автоматизация проектирования, 423
722 Предметный указательАгрегация, 292; 705
Адаптация, 53
Адаптер ресурсов, 461
Активная инициализация, 468; 604
Активный
класс, 267; 297
объект, 267; 297; 604; 705
Анализ, 33; 705
архитектурный, 561; 563
требований,31; 33
Артефакт, 64; 85; 641
Архитектура, 231; 705
логическая, 228
многоуровневая, 232
программная, 231; 673
развертывания, 228
системы, 231
трехуровневая, 594
Архитектурная основа, 162
Архитектурное
предложение, 570
представление, 674
Архитектурно значимое требование, 565
Архитектурный
анализ, 91; 561; 563
прототип, 162
синтез, 577; 686
фактор, 564
Асинхронное
событие, 518
сообщение, 266; 399; 608
Ассоциативный класс, 545
Ассоциация, 183; 705
имя, 185
кратность, 186
обозначение, 184
рефлексивная , 553
роль, 185
Атрибут, 190; 705
внешнего ключа, 196
качества, 90; 141ББизнес-моделирование, 65; 505
Бизнес-правило, 91; 142; 151
Блок
выполнения, 258
примечаний, 284Брокер, 452Быстрый подход к моделированию, 38вВидение, 91Видимость, 358; 387; 706
глобальная, 392
локальная, 391
посредством
атрибутов, 389
параметров, 390
Виртуальная машина, 593; 640
Внешний контроллер, 316; 330; 333
ВОМ, 201гГибкий метод, 58Гибкое моделирование, 60; 244Границы системы, 163ДДвухуровневая архитектура, 595
Действие, 500
Делегирование, 706
Дематериализация, 647
Дескриптор, 287
Диаграммавзаимодействия, 36; 246; 251; 252; 349
видов деятельности, 501
классов, 168; 277; 393; 395
проектирования, 37; 278
коммуникации, 246; 252; 253
компонентов, 641
пакетов, 247; 583последовательностей, 203; 206; 252; 524
системная, 206
потоков данных, 501
прецедентов, 123
развертывания, 247; 675
состояний, 508
Динамическая модель, 246
Динамическоемоделирование, 251
представление, 37
Дисциплина определения требований, 695
Документ SAD, 576; 674
Предметный указатель 723Дополнительная спецификация, 91; 136;576; 695Дополнительный прецедент, 519зЗакрытая область, 706
Зацепление, 341иИдентификатор объекта, 648
Идентичность объекта, 706
Иерархия
классов, 428; 706
программных, 543
обобщения-специализации, 532
Имя
ассоциации,185
атрибута, 280
Инвариант, 223
Инкапсуляция, 706
Инстанцирование, 706
Институт программных технологий, 565
Интерфейс, 291; 440; 444; 706
пользователя, 228
Информационный эксперт, 322
Исключение, 399; 606
Искусственный класс, 445
Исполнитель, 96; 100
вспомогательный, 100
закулисный, 100
основной,100
Исполняемая архитектура, 162
Исходный специальный объект, 371
Итеративная разработка, 45; 48; 50
на основе рисков, 56
Итеративный процесс разработки, 31; 689
Итерация, 48
длительность, 51кКаркас, 645; 707
интерфейса с базой данных, 645
Карта CRC, 248
Квалификатор, 294
Квалифицированная ассоциация, 706Класс, 40; 706
абстрактный, 705
ассоциации, 294; 543
искусственный, 445
концептуальный, 165; 353
описания, 181
программный, 353
проектирования, 40
Класс-фабрика, 465
Классификатор, 40; 280
Классификация, 706
понятий,428
Ключевое слово, 286
Комментарий, 284
Композитный класс, 706
Композиция, 320
Компонент, 641
Конкретный
класс, 706
прецедент, 519
Конструктор, 391; 706
Контейнер, 575
Контейнерный класс, 706
Контекст, 389
Контекстный объект, 472
Контроллер, 330
прецедента, 316; 330; 333
сеанса, 316; 330
Концептуальная объектная модель, 35
Концептуальный класс, 40; 165; 170; 353
Кооперация, 707
Кратность, 186; 707лЛинияассоциации, 280
жизни, 257
зависимости, 231
Логическая архитектура, 228
Логическое представление, 581; 675мМаркер, 506
Материализация, 647
по требованию, 667
Метаданные, 149
724 Предметный указательМетакласс, 265
Метамодель, 707
UML, 38
Метка, 287Метод, 221; 285; 286; 707
OOSE, 42
класса, 707
ОМТ, 42
Метод-шаблон, 653
Многоуровневая архитектура, 232
Моделирование
гибкое, 244
статическое, 277
Модель, 707
DEM, 493FURPS+, 90; 100; 565
бизнес-объектов, 168; 505
данных, 170; 648
концептуальная, 168
предметной области, 35; 65; 165; 169; 201
прецедентов, 91; 98; 695
проектирования, 278; 675
развертывания, 591
реализации, 393
сетевых протоколов, 590
Модульное тестирование, 410нНаследование, 288; 543; 707
Начальная фаза, 81; 160
Независимый от состояния объект, 509
Непрерывная интеграция, 47
Непрямое отображение, 651
Непрямой объект, 454оОбласть видимости, 278; 281; 288; 387; 389
Обобщение, 288; 428; 529; 532; 707
Обратная связь, 53
Обратное проектирование, 422
Объединение, 500
Объект, 500; 708
значений, 194
фасадный, 484
Объект-декоратор, 575
Объект-посредник, 611; 667
Объект-синглетон, 257Объект-фабрика, 371
Объектная
бизнес-модель UP, 201
модель анализа, 168
Объектно-ориентированное
программирование, 34
проектирование, 33; 36; 708
Объектно-ориентированный
анализ, 33; 708язык программирования, 708
Объектный язык ограничений (ОСЬ), 217;
222Обязанность, 116; 304; 708
Ограничение, 285; 288; 708
Операционная система, 640
Операция, 221; 286; 708
доступа, 286
системная, 213
Описание
архитектурных подходов, 570
операции,708
системной, 211
Опорный объект, 611
Основной прецедент, 519
Основные принципы проектирования
архитектуры, 573
Отказ, 606Открытая область, 708
Отношение
включения, 516
обобщения, 519; 521
обобщения-специализации, 428
расширения, 520
Ошибка, 606пПакет, 485; 633Параметризованный тип, 295
Пассивнаяинициализация, 468; 604
материализация, 647; 667
Передача агрегатного объекта, 483
Переменная экземпляра, 708
Переход, 508; 708
План
итерации, 63
разработки, 695
Предметный указатель 725Поведение системы, 206
Повреждение, 606Повышение устойчивости пакета, 634
Пограничный объект, 334
Подкласс, 428; 532Подлежащий постоянному хранению
объект, 708
Подтип, 709Полиморфизм, 266; 274; 438; 444; 709
Полиморфная операция, 709
Получатель, 709
Понятие, 709
предметной области, 40
Последовательный жизненный цикл, 52
Посткомпилятор, 575
Постоянно хранимый объект, 644
Постусловие, 108; 214; 709
Поток, 266
Правило
100%, 535
Is-a, 535предметной области, 151
Предметная область, 709
Представление
данных, 676
прецедентов, 676
процессов, 675
развертывания, 675
разработки, 676
реализации, 676
Предусловие, 108; 213; 709
Прецедент, 31; 34; 95; 98; 519
базовый, 115
вспомогательный, 107
конкретный, 115
методы выделения, 117
основной успешный сценарий, 109
пользовательский, 107
расширение, 109
реализация, 348
системный, 107
специальные требования, 111
типа черный ящик, 116
формат, 101
Примечание, 284
Примитивный тип, 194
Принцип ОСР, 457Проверка архитектурной концепции, 577;
686Программирование
в парах, 58на основе тестирования, 400; 410
с предварительным тестированием, 70
Программная архитектура, 673
Программный класс, 40; 353
Проектирование, 33; 65; 709
базы данных, 33
на основе
данных, 452; 465
обязанностей, 30; 304
описаний, 223
физическое, 632
Производный
атрибут, 192
класс, 707
Пространство имен, 231
Прототип, 84
Профиль, 38
UML, 648
Процесс разработки программного
обеспечения, 46
Прямое
отображение, 650
проектирование, 422
Прямой объект, 454
рРазвернутый прецедент, 101
Раздел, 237; 500Разделение концептуального класса, 536
Раздутый контроллер, 338
Разработка
на основе
рисков, 58
свойств, 31
тестирования, 47
под управлением прецедентов, 128
Ракурс модели, 39
Ранжирование прецедентов, 164
Распределение обязанностей, 32; 305
Расширение, 170
UML, 287
прецедента, 109
726 Предметный указательРеализация
интерфейса, 291
прецедента, 348
Рекурсивная ассоциация, 709
Рефакторинг, 47; 243; 413
Риск, 161; 163
Родовой тип, 295
Роль, 185; 549; 709сСвободный прецедент, 101
Свойство, 288
структурное, 280
Связывание, 289; 709
Связь, 269; 709
СДП, 204Сервлет-контейнер, 641
Сеть Петри, 506
Сжатый прецедент, 101
Сигнал, 608
Сигнатура, 221
Символ, 170
Синглетон, 295
Системаавтоматизации торговли, 76
операционная, 640
управления базами данных, 641
Системная операция, 206; 213; 329
Системное
свойство, 146
событие, 206
Системный интерфейс, 214
Слияние, 503
Словарьпредметной области, 169
терминов, 91; 136; 149
Служба O-R-преобразования, 645
Событие, 508; 709
Содержание, 170
Сокет, 291Сокрытие информации, 457
Сообщение, 269; 710
create, 270порядковый номер, 270
условное, 261; 272
Составная ассоциация, 552
Состояние, 508; 710Специализация, 529
Спецификатор, 552
Спецификация, 221
CORBA, 611
Спиральная модель, 70
Средство автоматизациипроектирования, 423
Ссылка, 264
Стандарт
JavaPOS, 615
UnifiedPOS, 615
Статическая модель, 246
Статическое представление, 37
Степеньвнутреннего связывания пакетов, 633
связанности, 313; 326
Стереотип, 124; 270; 287
Стратегия разрешения конфликтов, 475
Строка свойств, 283; 288
Суперкласс, 428; 532; 707
Сценарий, 96
реализации качественных требований, 565тТегированное значение, 270
Тематическая карта, 570
Техническое описание, 570
Точкавариации, 455; 563
ветвления, 500
эволюции, 455; 563; 572
Требование,65; 88
категории, 90
функциональное, 91
Трехуровневая архитектура, 594уУкрупненный план проекта, 63
Унифицированный
процесс, 31; 45; 63; 128
RUP, 46
UP, 46
гибкий, 62
дисциплины, 64
фазы, 63
язык моделирования, 30
Предметный указатель 727Управление требованиями, 88
Управляющий объект, 334
Уровень, 228; 237
архитектурный, 237
данных, 594
интерфейса, 594
логики приложения, 74; 594
предметной области, 236
Условное сообщение, 261; 272
Условный переход, 503
Устройство, 640
Уточненная ассоциация, 294ФФазаконструирования, 132
начальная, 132
развития, 132; 161
Фасадный объект, 484
сеансов, 587
Физическое
проектирование, 632
Финальный класс, 289
Фрейм, 260
взаимодействия, 207
Функциональная точка, 210
Функциональное свойство, 91ЦЦиклическое проектирование, 422чЧистые данные, 710шШаблон, 30; 295; 306; 710
Abstract Factory, 617
Adapter, 448; 460; 601
Cache Management, 660
Centralized Error Logging, 609
Command, 341; 665
Composite, 475Controller, 315; 329; 354; 587; 701
Convert Exceptions, 607
Creator, 319; 355; 701
Database Broker, 650
Diagnostic Logger, 609
Domain Object Factory, 636
Don’t Talk to Strangers, 453
Do It Myself, 621
Error Dialog, 610
Expert, 312
Facade, 483; 585
Factory, 601
GoF, 303GRASP, 303; 307; 308; 353; 437
High Cohesion, 341; 701
Indirection, 449; 462; 701
Information Expert, 321; 357; 701
Layers, 233; 341; 575
Low Coupling, 313; 326; 591; 701
Mediator, 451Model-View Separation, 238; 596Name The Problem Not The Thrower, 607Object Identifier, 648Observer, 485Polymorphism, 438; 701Protected Variations, 451; 462; 591; 701Proxy, 611Publish-Subscribe, 487Pure Fabrication, 341; 445; 701Representing Objects as Tables, 647Singleton, 257; 392; 466State, 221; 661Strategy, 471Template Method, 653Virtual Proxy, 667распределения обязанностей, 305эЭволюционная разработка, 48
Эволюция требований, 151
Экземпляр, 255; 710
прецедента, 97
Экстремальное программирование, 47; 70
Элементарный бизнес-процесс, 121
Научно-популярное изданиеКрэг ЛарманПрименение UML 2.0
и шаблонов проектирования
Практическое руководство
3-е изданиеЛитературный редактор Е.П. Перестюк
Верстка Т.Н. Артеменко
Художественный редактор Е.П. ДынникКорректоры Л.А. Гордиенко, Л.В. ЧернокозинскаяИздательский дом “Вильямс”127055, г. Москва, ул. Лесная, д. 43, стр. 1Подписано в печать 30.10.2012. Формат 70x100/16
Гарнитура Times. Печать офсетная
Уел. печ. л. 59,34. Уч.-изд. л. 41,62
Тираж 1000 экз. Заказ № 3357Первая Академическая типография “Наука”
199034, Санкт-Петербург, 9-я линия, 12/28
ОСВОЙ САМОСТОЯТЕЛЬНО UML
ЗА 24 ЧАСА
3-Е ИЗДАНИЕДжозеф ШмуллерДиаграммыСвязи, ассоциации и наследованиеUML 2.0оделирование системMSI-Джозеф ШмуллерSAMSТретье изданиеwww.williamspublishing.comВсего за 24 урока,
продолжительностью
не более одного часа, вы
познакомитесь с основами
универсального языка
моделирования (UML) и
научитесь с его помощью
создавать диаграммы.
Используя простой подход и
пошаговое изложение, когда
каждый последующий урок
вытекает из предыдущего,
вы освоите основы
языка UML, даже если
начинаете практически
с нуля. Опытный
специалист Джозеф
Шмуллер познакомит
вас с языком UML,
используя показательные
и интересные примеры,
которыми вы сможете
воспользоваться в
своей деятельности!ISBN 5-8459-0855-8в продаже
РЕФАКТОРИНГ
С ИСПОЛЬЗОВАНИЕМ
ШАБЛОНОВДжошуа Кериевскиwww.williamspublishing.comДанная книга представляет
собой результат многолетнего
опыта профессионального
программиста по применению
шаблонов проектирования.
Авторский подход к про¬
ектированию состоит в том,
что следует избегать как недо¬
статочного, так и избыточного
проектирования, постоянно
анализируя готовый работо¬
способный код и реорганизуя
его только в том случае, когда
это приведет к повышению его
эффективности, упрощению
его понимания и сопро¬
вождения. Автор на основании
как собственного, так и чужого
опыта детально рассматривает
различные признаки кода,
требующего рефакторинга,
описывает, какой именно
рефакторинг наилучшим
образом подходит для той
или иной ситуации, и описы¬
вает его механику, подробно
разбирая ее на конкретных
примерах из реальных задач.
Книга может рассматриваться
и как учебник по рефакторин¬
гу для программиста среднего
уровня, и как справочное
пособие для профессионала.It/H'diiC HMui' Pamfxi Дж онсона и Мартына Фаущш
Ilw.m.iwu/' Джона Бранта нДона Pot'iepmi a^ ~ h%
iHРефакторинг %,./С ИСПОЛЬЗОВАНИЕМ
ШАБЛОНОВ1жоН!У\ Ккии векиISBN 5-8459-1087-0в продаже
АРХИТЕКТУРАКОРПОРА¬ТИВНЫХПРОГРАММНЫХПРИЛОЖЕНИЙМартин Фаулер. //■ . РААРХИТЕКТУРА
КОРПОРАТМ1ШЫХ ^
ПРОГРАММНЫХ
ПРИ.ЮЖИН ИЙм t Ф/smV/ / /
п /,
А -.у > v\<.*»• г/. <■
i v.i. !«-•. Мн / / ‘7,<-'5' '/jwww.williamspublishing.com
ISBN 5-8459-0604-0Создание компьютерных систем
дело далеко не простое.По мере того как возрастает их
сложность, процессы констру¬
ирования соответствующего
программного обеспечения
становятся все более
трудоемкими, причем затраты
труда растут экспоненциально.
Как и в любой профессии,
прогресс в программировании
достигается исключительно
путем обучения, причем не только
на ошибках, но и на удачах —
ак своих, так и чужих.Книга дает ответы на трудные
вопросы, с которыми приходится
сталкиваться всем разработчикам
корпоративных систем. Автор,
известный специалист в области
объектно-ориентированного
программирования, заметил, что
с развитием технологий базовые
принципы проектирования
и решения общих проблем
остаются неизменными,
и выделил более 40 наиболее
употребительных подходов,
оформив их в виде типовых
решений. Результат перед вами —
незаменимое руководство по
архитектуре программных систем
для любой корпоративной
платформы. Это своеобразное
учебное пособие поможет вам не
только усвоить информацию,
но и передать полученные знания
окружающим значительно
быстрее и эффективнее, чем это
удавалось автору
Книга предназначена для
программистов, проектиров¬
щиков и архитекторов, которые
занимаются созданием
корпоративных приложений
и стремятся повысить качество
принимаемых стратегических
решений.в продаже
ФАБРИКИ РАЗРАБОТКИ
ПРОГРАММДжек Гринфилд
Кейт ШортСвоевременно. Практично. Надежно.Фабрики
разработки
программПотоковая
сборка типовых
приложений,
моделирование,
структуры
и инструментыДжок Гринфилд и Кейт Шорт
при участии Стива Кука и Стюарта Кейта
Предисловие Джона Кру пиwww.dialektika.comКнига известных
специалистов в области
разработки архитектур
крупных программных
систем посвящена новому
подходу к созданию линеек
программного обеспечения,
допускающих быструю
адаптацию под постоянно
меняющиеся требования
со стороны заказчиков. В
книге рассматриваются
фундаментальные вопросы
сложности и изменчивости
программного обеспечения,
разработки с помощью
моделей и шаблонов, а также
специализированных языков
проектирования. Большое
внимание уделяется проблеме
систематического повторного
использования, построению
линеек программных
продуктов и абстрагированию,
основанному на платформах.
Рассматриваемый пример
фабрики охватывает
все представленные
теоретические сведения.Книга рассчитана на
архитекторов и разработчиков
крупных программных систем,
и будет полезна руководителям
программных проектов.ISBN 978-5-8459-1181-0в продаже
ПРОДВИЖЕНИЕ САЙТА
В ПОИСКОВЫХ СИСТЕМАХПод ред.
И. Ашманова
и А. Ивановаwww.williamspublishing.comОсновная цель владельца
любого сайта состоит
в привлечении на него
заинтересованного посетителя.
О том, как успешно достичь
этой цели с минимальными
затратами времени
и денег, и рассказывают
авторы книги — активно
практикующие специалисты
с большим стажем работы.
Здесь вы найдете ответы
на важнейшие вопросы:
что такое поисковые
системы и каталоги,
как пользователи ищут
информацию, как продвигать
сайт, т.е. добиваться, чтобы
пользователи приходили
на ваш сайт и покупали именно
у вас. Подробно обсуждаются
современные способы сетевой
рекламы и нестандартные
способы продвижения, даются
конкретные рекомендации
по оптимизации сайтов
различной тематики.Книга непосредственно
адресована тем, кто только
начинает заниматься
поисковой оптимизацией
и ищет наиболее действенные
методы решения этой задачи.Р йштанобИ. Ашманов А. ИвановПРОДВИЖЕНИЕ
САЙТА В ПОИСКОВЫХ
СИСТЕМАХ* Научитесь адекватно оценивать,
собственный сайт и сравнивать
его с сайтами конкурентов!• Все рекомендации дамы активно
практикующими специалистамис большим стажем работы, что позволит
помучить максимальный результат
с минимальными затратами
времени и денег!ISBN 978-5-8459-1155-1в продаже
ОСНОВЫ КОНТЕНТНОЙ
ОПТИМИЗАЦИИЭФФЕКТИВНАЯ ИНТЕРНЕТ-КОММЕРЦИЯ
И ПРОДВИЖЕНИЕ САЙТОВ В ИНТЕРНЕТН.В. Евдокимов\ Т5/TYQnfY^Y^rMl Н.В. ЕвдокимовКОНШИНОЙЭФФЕКТИВНАЯ ИНТЕРНЕТ-КОММЕРЦИЯ И
ПРОДВИЖЕНИЕ САЙТОВ В ИНТЕРНЕТщШwww.williamspublishing.com“Основы контентной
оптимизации” — уникальное
издание в области Интернет-
маркетинга. На страницах
этой книги начинающий
специалист по продвижению
бизнеса в Интернете сможет
найти решение одного
из ключевых вопросов
Интернет-маркетинга — вопроса
привлечения на сайт
посетителей, потенциальных
клиентов и партнеров.
Уникальная методика
привлечения, получившая
название “контентная
оптимизация”, в разработке
которой автор книги принимал
самое непосредственное
участие, раскрыта в этом
издании на доступном
рядовому читателе уровне,
и готова к применению
в практической деятельности.
Твердая теоретическая база,
подкрепленная “живыми”,
взятыми из реальной жизни
примерами, четкая структура,
живой и образный язык — всё
это делает “Основы контентой
оптимизации” настольной
книгой как для начинающих,
так и для опытных специалистов
в области Интернет-маркетинга.ISBN 5-8459-1095-1в продаже
C# 2005
ДЛЯ ПРОФЕССИОНАЛОВКристиан Нейгел,
Билл Ивьен, Джей Гпинн,
Карли Уотсон,
Морган Скиннер, Аллен Джонсwww.dialektika.comКнигу отличает простой
и доступный стиль
изложения, изобилие
примеров и множество
рекомендаций по написанию
высококачественных программ.
Подробно рассматриваются
такие вопросы, как основы
языка программирования
С#, организация среды
.NET Framework 2.0, работа
с данными, создание
Windows- и Web-приложений,
взаимодействие через сеть,
создание Web-служб и
многое другое. Немалое
внимание уделено проблемам
безопасности и сопровождения
кода. Тщательно подобранный
материал позволит без труда
разобраться с тонкостями
использования Windows
Forms и Web Forms. Читатели
ознакомятся с работой в
Visual Studio .NET, а также
с применением таких
технологий, как СОМ,
ADO.NET, ASP.NET и GDI+.
Прилагаемый к книге компакт-
диск содержит исходные
коды всех примеров, что
существенно упростит
освоение материала.Книга рассчитана на
программистов разной
квалификации, а также
будет полезна для студентов
и преподавателей.ISBN 5-8459-1052-8в продаже
ЯЗЫК ПРОГРАММИРОВАНИЯ
C# 2005 И ПЛАТФОРМА .NET 2.0
3-е изданиеЭндрю ТроелсенЯЗЫК ПРОГРАММИРОВАНИЯC# 2005И ПЛАТФОРМА. NET 2.03-е изданиеПрофессиональное исследование возможностей■ Apress*www.apressxomwww.williamspublishing.comВ этой книге содержится
описание базовых принципов
функционирования
платформы .NET, системы
типов .NET и различных
инструментальных средств
разработки, используемых
при создании приложений
.NET. Представлены
базовые возможности
языка программирования
C# 2005, включая новые
синтаксические конструкции,
появившиеся с выходом
.NET 2.0, а также синтаксис
и семантика языка CIL.В книге рассматривается
формат сборок .NET,
библиотеки базовых классов
.NET, файловый ввод-вывод,
возможности удаленного
доступа, конструкция
приложений Windows Forms,
доступ к базам данных
с помощью ADO.NET,
создание Web-приложений
ASP.NET и Web-служб XML.
Книга содержит множество
примеров программного кода,
призванного помочь читателю
в освоении предлагаемого
материала. Программный код
примеров можно загрузить
с Web-сайта издательства.ISBN 5-8459-1124-9в продаже
Инженерия программного обеспечения/объектно¬
ориентированный анализ и проектирование• Новое издание всемирного бестселлера, представляющего
собой введение в объектно-ориентированный анализ и
проектирование с использованием UML 2.0• Новые примеры, иллюстрирующие многие из
рассматриваемых ключевых понятийПрименение UML 2.0 и шаблонов проектировния - во всем мире
известное издание, с помощью которого можно начать “мыслить объек¬
тами” и проникнуть в самую суть объектно-ориентированного анализа и
проектирования. Основываясь на двух предыдущих изданиях, получивших
широкую поддержку во всем мире, Крэг Ларман полностью обновил книгу,
чтобы рассказать о новом стандарте UML 2.0, помочь читателям освоить
искусство объектного проектирования и способствовать развитию эффек¬
тивных приемов итеративного и гибкого моделирования.Основываясь на своем беспрецедентном опыте преподавателя и консуль¬
танта, Ларман помогает читателям разобраться с подходами эволюцион¬
ного определения требований и прецедентов, моделированием предмет¬
ной области, проектированием на основе обязанностей, а также наиболее
важными принципами объектно-ориентированного проектирования и мно¬
гоуровневой архитектурой. С помощью этой книги вы сможете познако¬
миться также с шаблонами проектирования GoF и GRASP, итеративными
методами, гибким подходом к использованию унифицированного процес¬
са и многими другими темами. К наиболее важным усовершенствованиям
данного издания относятся следующие.• Описание нового стандарта UML2.0, гибкого моделирования, разработки
на основе тестирования и рефакторинга• Многочисленные рекомендации, позволяющие лучше освоить приемы
итеративной и эволюционной объектно-ориентированной разработки• Существенно обновленный материал с новыми диаграммами, облегчаю¬
щий процесс обучения• Новые дополнительные ресурсы, которые можно использовать в процессе
обучения студентов• Рекомендации по применению унифицированного процесса как легко¬
го и гибкого подхода к разработке совместно с приемами из других итера¬
тивных методов, таких как ХР и Scrum• Описание подходов к использованию языка UML для документирования
архитектуры• Новая глава об эволюционных требованиях и много другого интересного
материалаТретье издание книги Применение UML2.0 и шаблонов проектирова¬
ния - это практическое руководство по анализу и проектированию на осно¬
ве объектов, а также по разработке легко разворачиваемых, надежных
и простых в поддержке систем.Prentice HallUpper Saddle River, NJ 07458www.phptr.com/larmanwww.craiglarman/com“Немногие умеют хорошо
объяснять. Еще меньше людей
способны выполнять анализ и
проектировать программные
системы. Крэг Ларман обладает
двумя этими качествами.”— Джон Влиссидес, автор книг
Design Patterns и Применение
шаблонов проектирования.
Дополнительные штрихи
(ИД “Вильямс”, 2003 г.)Об автореКрэг Ларман руководит научными
исследованиями в известной
консалтинговой компании
в Валтехе (Valtech), офисы которой
расположены в США, Европе и
Азии. В международном сообществе
специалистов по программным
системам он известен как эксперт
в области объектно-ориентированного
анализа и проектирования, применения
шаблонов проектирования и гибких
итеративных методов, а также
использования унифицированного
процесса (Unified Process - UP)
в качестве гибкого подхода
к разработке. Он автор известной книги
Agile and Iterative Development:A Managers Guide (издательство
Addison-Wesley, 2004) и вместе с
Реттом Гутри (Rhett Guthrie) является
соавтором книги Java Performance and
Idiom Guide (издательство Prentice Hall,
2000).Крэг Ларман имеет степени
бакалавра и магистра информатики
Ванкуверского университета имени
Саймона Фрейзера в Канаде.ISBN 978-5-8459-1185-8070 1 5ВИЛЬЯМСIkmИздательский дом “Вильямс”PRENTICEHALLwww.williamspublishing.comPTR785845911858