Обложка
Титульный лист оригинала
Титульный лист перевода
Аннотация
Оглавление
Содержание
Предисловие
Изменения, внесенные в третье издание
Часть I. Концепции
Структура растений и животных
Структура материи
Структура общественных институтов
1.2 Сложность, присущая программному обеспечению
Почему программному обеспечению присуща сложность?
Сложность предметной области
Трудности управления проектированием
Необходимость обеспечить гибкость программ
Сложность описания дискретных систем
1.3 Пять признаков сложной системы
Относительность выбора элементарных компонентов
Разделение функций
Общая структура
Устойчивые промежуточные формы
1.4 Организованная и неорганизованная сложность
Пределы человеческих возможностей
1.5 Упорядочение хаоса
Алгоритмическая декомпозиция
Объектно-ориентированная декомпозиция
Сравнение алгоритмической и объектно-ориентированной композиции
Роль абстракции
Роль иерархии
1.6 О проектировании сложных систем
Смысл проектирования
Важность моделирования
Элементы методологии проектирования программного обеспечения
Объектно-ориентированные модели
Резюме
Глава 2. Объектная модель
Топология языков первого поколения и ранних языков второго поколения
Топология языков программирования позднего второго и раннего третьего поколения
Топология поздних языков третьего поколения
Топология объектных и объектно-ориентированных языков
2.2 Основные положения объектной модели
Объектно-ориентированное проектирование
Объектно-ориентированный анализ
2.3 Составные части объектного подхода
Инкапсуляция
Модульность
Иерархия
Контроль типов
Параллелизм
Персистентность
2.4 Применение объектной модели
Нерешенные вопросы
Резюме
Глава 3. Классы и объекты
Состояние
Поведение
Операции
Роли и обязанности
Объекты как автоматы
Индивидуальность
3.2 Отношения между объектами
Видимость
Синхронизация
Агрегация
3.3 Природа класса
Интерфейс и реализация
Жизненный цикл класса
3.4 Отношения между классами
Наследование
Агрегация
Зависимости
3.5 Взаимосвязь классов и объектов
Роль классов и объектов в анализе и проектировании
3.6 Качество классов и объектов
Выбор операций
Временная и пространственная семантика
Выбор отношений
Выбор реализации
Упаковка
Резюме
Глава 4. Классификация
Итеративная суть классификации
4.2 Идентификация классов и объектов
Применение классических и современных теорий
Объектно-ориентированный анализ
Анализ характеристик
4.3 Основные абстракции и механизмы
Идентификация механизмов
Резюме
Часть II. Метод
Модели и представления
Таксономия диаграмм
Практическое использование диаграмм
Концептуальные, логические и физические модели
Роль инструментов проектирования
Продукты объектно-ориентированного конструирования
Пропорциональное увеличение или уменьшение
Синтаксис и семантика языка UML
Источники информации о языке UML 2.0
5.2 Диаграммы пакетов
Основы: области видимости элементов
Основы: отношение зависимости
Основы: диаграммы пакетов
Уточненная концепция: импорт и доступ
5.3 Диаграммы компонентов
Основы: диаграмма компонентов
Основы: интерфейсы компонентов
Основы: реализация компонентов
Уточненная концепция: внутренняя структура компонентов
5.4 Диаграммы развертывания
Основы: обозначение узла
Основы: диаграмма развертывания
5.5 Диаграммы прецедентов использования
Основы: прецеденты использования
Основы: диаграмма прецедентов использования
Уточненная концепция: отношения «include>> и «extend»
Уточненная концепция: обобщение
5.6 Диаграммы деятельности
Основы: начало и остановка
Основы: узлы принятия решений и слияний
Основы: разделы
Уточненные концепции: разветвления, объединения и параллельность
Уточненные концепции: потоки объектов
Уточненные концепции: дополнительные элементы
5.7 Диаграммы классов
Основы: отношения между классами
Уточненные концепции: видимость
Уточненные концепции: имена полюсов ассоциации и квалификаторы
Уточненные концепции: ограничения
Уточненные концепции: классы ассоциаций и примечания
5.8 Диаграммы последовательностей
Основы: \
Уточненные концепции: уничтожение
Уточненные концепции: спецификация выполнения
Уточненные концепции: механизм использования взаимодействий
Уточненные концепции: управляющие конструкции
5.9 Диаграммы обзора взаимодействий
Основы: элементы потока управления
Основы: элементы диаграммы взаимодействий
5.10 Диаграммы композитных структур
Основы: порты и интерфейсы сложной структуры
Основы: соединительные звенья композитной структуры
Уточненные концепции: механизм сотрудничества
5.11 Диаграммы конечных автоматов
Основы: переходы и состояния
Уточненные концепции: вход, операция и выход из состояния
Уточненные концепции: управляемые переходы
Уточненные концепции: сложные и вложенные состояния
Уточненные концепции: параллельность и управление
Уточненные концепции: состояние конечного автомата
Уточненные концепции: дополнительные элементы диаграмм конечных автоматов
5.12 Диаграммы синхронизации
Основы: схема
Основы: события
Основы: ограничения
Уточненные концепции: альтернативное представление
Уточненные концепции: события и сообщения
5.13 Диаграммы объектов
Основы: отношения между объектами
Уточненные концепции: имена и квалификаторы
5.14 Диаграммы коммуникации
Основы: нумерация сообщений
Уточненные концепции: сообщения и синхронизация
Уточненные концепции: итерационные выражения и дополнительные условия
Резюме
Глава 6. Процесс
Рациональный процесс проектирования
6.2 Макропроцесс: жизненный цикл разработки программного обеспечения
Содержание макропроцесса — стадии
Временные координаты макропроцесса — контрольные точки и этапы
Временной аспект макропроцесса — итерации
Планирование выпусков
6.3 Микропроцесс: анализ и проектирование
Уровни абстракции
Микропроцесс и уровни абстракции
Идентификация элементов
Определение взаимодействия между элементами
Определение отношений между элементами
Детализация семантики элементов
Резюме
Глава 7. Практические вопросы
Планирование заданий
Инспектирование проекта
7.2 Подбор кадров
Роли разработчиков
7.3 Управление выпусками
Интеграция
Тестирование
7.4 Повторное использование
Как осуществить повторное использование?
7.5 Гарантия качества и его показатели
Объектно-ориентированные показатели
7.6 Документация
Содержание документации
7.7 Инструменты
Организационные выводы
7.8 Специальные вопросы
Адаптация объектных технологий
7.9 Преимущества и риски объектно-ориентированной разработки
Риски, связанные с объектно-ориентированным проектированием
Резюме
Часть III. Приложения
Определение границ задачи
Формулировка прецедентов выполнения заданий
Определение сценариев использования системы
8.2 Разработка
Определение действий, связанных с разработкой архитектуры
Обоснование предложенной системной архитектуры
Распределение нефункциональных требований и определение интерфейсов
Согласование системной архитектуры и ее разворачивание
Декомпозиция системной архитектуры
8.3 Конструирование
8.4 Сопровождение
Изменение аппаратного оборудования
Глава 9. Система управления трафиком
Определение прецедентов использования системы
9.2 Разработка
Определение архитектуры системы TTMS
От проектирования системы к разработке аппаратного оборудования и программного обеспечения
Ключевые абстракции и механизмы
9.3 Конструирование
Планирование расписания движения поездов
Отображение информации
Сбор показаний датчиков
Управление версиями
Архитектура системы
Спецификация подсистем
9.4 Эксплуатация
Глава 10. Искусственный интеллект: криптоанализ
Определение границ задачи
Архитектура информационной доски
Анализ источников знаний
10.2 Разработка
Зависимости и утверждения
10.3 Конструирование
Проектирование источников знаний
Проектирование специализированных источников знаний
Обобщение источников знаний
Проектирование модуля управления
Интеграция модели
Интеграция объектов верхнего уровня
Реализация механизма оценки предположений
Добавление новых источников знаний
10.4 Сопровождение
Изменение технических требований
Глава 11. Сбор данных: метеорологическая станция
Определение границ рассматриваемой задачи
Сценарии
11.2 Проектирование
Архитектурная основа
11.3 Конструирование
Планирование выпусков
Механизм датчиков
Механизм работы дисплея
Механизм пользовательского интерфейса
11.4 Эксплуатация
Глава 12. Web-приложение: система планирования отпусков
Модель использования
12.2 Разработка
Логическое представление
Представление процессов
Представление реализации
Представление сценариев использования
12.3 Конструирование
Модели анализа и проектирования
Сущности
Сервисные объекты данных
Генерация первичного ключа
Методы поиска
Контроллеры
Web-страницы и пользовательский интерфейс
Заполнение динамического содержания
Вызов бизнес-функций
12.4 Внедрение и эксплуатация
Приложение А. Объектно-ориентированные языки программирования
Язык программирования Smalltalk
Язык программирования C++
Язык программирования Java
Приложение Б. Рекомендации по дальнейшему чтению
Примечания
Глоссарий
Библиография
Предметный указатель
Текст
                    Объектно-
ориентированный анализ
и проектирование
с примерами
приложений


Object-oriented analysis and design with application Third edition Grady Booch Robert A. Maksimchuk Michael W. Engle Bobbi J. Young, Ph.D. Jim Conallen Kelli A. Houston Addison-Wesley Upper Saddle River, NJ · Boston · Indianapolis · San Francisco New York · Toronto · Montreal · London · Munich · Paris · Madrid Capetown · Sydney · Tokyo · Singapore · Mexico City
Объектно- ориентированный анализ и проектирование с примерами приложений Третье издание Гради Буч, Роберт А. Максимчук, Майкл У. Энгл, Бобби Дж. Янг, Джим Коналлен, Келли А. Хьюстон Посвящается Джен — моей подруге, любимой, Гради ш Издательский дом "Вильяме" Москва ♦ Санкт-Петербург ♦ Киев 2008
ББК 32.973.26-018.2.75 0-29 УДК 681.3.07 Издательский дом "Вильяме" Зав. редакцией С.К Тригуб Перевод с английского и редакция канд. физ.-мат. наук Д.А. Клюшина По общим вопросам обращайтесь в Издательский дом "Вильяме" по адресу: info@williamspublishing.com, http://www.williamspublishing.com Буч, Гради, Максимчук, Роберт Α., Энгл, Майкл У, Янг, Бобби Дж., Коналлен, Джим, Хьюстон, Келли А. 0-29 Объектно-ориентированный анализ и проектирование с примерами приложений, 3-е изд.: Пер. с англ. - М.: 000 "И.Д. Вильяме", 2008. - 720 с.: ил. — Парал. тит. англ. ISBN 978-5-8459-1401-9 (рус.) Книга представляет собой новое издание бестселлера Гради Буча по объектно-ориентированному анализу и проектированию. Авторы описывают объектные методы решения сложных проблем, связанные с разработкой систем и программного обеспечения. Используя многочисленные примеры, они иллюстрируют основные концепции объектно-ориентированного подхода на примере разработки систем управления, сбора данных и искусственного интеллекта. Читатели найдут в книге практичные советы, касающиеся важных вопросов анализа, проектирования, реализации и оптимального управления проектами. Книга будет полезна системным аналитикам и архитекторам, программистам, преподавателям и студентам высших учебных заведений, а также всем специалистам по информационным технологиям. ББК 32.973.26-018.2.75 Все названия программных продуктов являются зарегистрированными торговыми марками соответствующих фирм. Никакая часть настоящего издания ни в каких целях не может быть воспроизведена в какой бы то ни было форме и какими бы то ни было средствами, будь то электронные или механические, включая фотокопирование и запись на магнитный носитель, если на это нет письменного разрешения издательства Addison-Wesley Publishing Company, Inc. Authorized translation from the English language edition published by Addison-Wesley Publishing Company, Inc, Copyright © 2007 Pearson Education, Inc. All rights reserved. No part of this book may be reproduced or transmitted in any form or by any means, electronic or mechanical, including photocopying, recording or by any information storage retrieval system, without permission from the Publisher. Russian language edition published by Williams Publishing House according to the Agreement with R&I Enterprises International, Copyright © 2008 ISBN 978-5-8459-1401-9 (рус.) © Издательский дом "Вильяме", 2008 ISBN 0-201-89551-Х (англ.) © Pearson Education, Inc., 2007
ОГЛАВЛЕНИЕ Предисловие 17 Часть I. Концепции 31 Глава 1. Сложность 33 Глава 2. Объектная модель 59 Глава 3. Классы и объекты 106 Глава 4. Классификация 150 Часть П. Метод 175 Глава 5. Обозначения 177 Глава 6. Процесс 281 Глава 7. Практические вопросы 338 Часть III. Приложения 367 Глава 8. Системная архитектура: спутниковая система навигации 370 Глава 9. Система управления трафиком 413 Глава 10. Искусственный интеллект: криптоанализ 452 Глава И. Сбор данных: метеорологическая станция 487 Глава 12. Web-приложение: система планирования отпусков 526 Приложение А. Объектно-ориентированные языки программирования 575 Приложение Б. Рекомендации по дальнейшему чтению 595 Примечания 605 Глоссарий 629 Библиография 641 Предметный указатель 715
СОДЕРЖАНИЕ Предисловие 17 Изменения, внесенные в третье издание 17 Часть I. Концепции 31 Глава 1. Сложность 33 1.1 Структура сложных систем 34 Структура персонального компьютера 34 Структура растений и животных 35 Структура материи 36 Структура общественных институтов 37 1.2 Сложность, присущая программному обеспечению 37 Определение сложности программного обеспечения 37 Почему программному обеспечению присуща сложность? 38 Сложность предметной области 38 Трудности управления проектированием 40 Необходимость обеспечить гибкость программ 41 Сложность описания дискретных систем 41 1.3 Пять признаков сложной системы 42 Иерархическая структура 42 Относительность выбора элементарных компонентов 43 Разделение функций 43 Общая структура 44 Устойчивые промежуточные формы 44 1.4 Организованная и неорганизованная сложность 45 Каноническая форма сложной системы 45 Пределы человеческих возможностей 48 1.5 Упорядочение хаоса 48 Роль декомпозиции 49 Алгоритмическая декомпозиция 49
СОДЕРЖАНИЕ 7 Объектно-ориентированная декомпозиция 50 Сравнение алгоритмической и объектно-ориентированной композиции 51 Роль абстракции 51 Роль иерархии 54 1.6 О проектировании сложных систем 55 Инженерное дело как наука и искусство 55 Смысл проектирования 55 Важность моделирования 56 Элементы методологии проектирования программного обеспечения 57 Объектно-ориентированные модели 57 Резюме 58 Глава 2. Объектная модель 59 2.1 Эволюция объектной модели 59 Поколения языков программирования 60 Топология языков первого поколения и ранних языков второго поколения 62 Топология языков программирования позднего второго и раннего третьего поколения 63 Топология поздних языков третьего поколения 64 Топология объектных и объектно-ориентированных языков 65 2.2 Основные положения объектной модели 67 Объектно-ориентированное программирование 69 Объектно-ориентированное проектирование 72 Объектно-ориентированный анализ 73 2.3 Составные части объектного подхода 73 Абстрагирование 75 Инкапсуляция 81 Модульность 85 Иерархия 89 Контроль типов 94 Параллелизм 97 Персистентность 100 2.4 Применение объектной модели 102 Преимущества объектной модели 103 Нерешенные вопросы 104 Резюме 104 Глава 3. Классы и объекты 106 3.1 Природа объектов 106
8 СОДЕРЖАНИЕ Что является и что не является объектом? 107 Состояние 109 Поведение 112 Операции 113 Роли и обязанности 114 Объекты как автоматы 116 Индивидуальность 116 3.2 Отношения между объектами 119 Связи 119 Видимость 122 Синхронизация 122 Агрегация 122 3.3 Природа класса 123 Что такое класс 123 Интерфейс и реализация 124 Жизненный цикл класса 126 3.4 Отношения между классами 127 Ассоциация 127 Наследование 129 Агрегация 139 Зависимости 140 3.5 Взаимосвязь классов и объектов 141 Отношения между классами и объектами 141 Роль классов и объектов в анализе и проектировании 141 3.6 Качество классов и объектов 142 Измерение качества абстракции 142 Выбор операций 144 Временная и пространственная семантика 145 Выбор отношений 146 Выбор реализации 147 Упаковка 148 Резюме 148 Глава 4. Классификация 150 4.1 Важность правильной классификации 150 Трудности классификации 151 Итеративная суть классификации 153 4.2 Идентификация классов и объектов 154 Классический и современный подходы 155 Применение классических и современных теорий 159 Объектно-ориентированный анализ 160
СОДЕРЖАНИЕ 9 Анализ характеристик 161 4.3 Основные абстракции и механизмы 167 Идентификация основных абстракций 168 Идентификация механизмов 170 Резюме 173 Часть II. Метод 175 Глава 5. Обозначения 177 5.1 Элементы обозначений 177 Краткий исторический очерк 178 Модели и представления 178 Таксономия диаграмм 179 Практическое использование диаграмм 181 Концептуальные, логические и физические модели 182 Роль инструментов проектирования 183 Продукты объектно-ориентированного конструирования 184 Пропорциональное увеличение или уменьшение 184 Синтаксис и семантика языка UML 185 Источники информации о языке UML 2.0 185 5.2 Диаграммы пакетов 186 Основы: обозначения пакетов 186 Основы: области видимости элементов 187 Основы: отношение зависимости 189 Основы: диаграммы пакетов 189 Уточненная концепция: импорт и доступ 191 5.3 Диаграммы компонентов 195 Основы: обозначение компонентов 195 Основы: диаграмма компонентов 197 Основы: интерфейсы компонентов 199 Основы: реализация компонентов 200 Уточненная концепция: внутренняя структура компонентов 202 5.4 Диаграммы развертывания 203 Основы: обозначение артефактов 204 Основы: обозначение узла 205 Основы: диаграмма развертывания 206 5.5 Диаграммы прецедентов использования 208 Основы: действующие лица 208 Основы: прецеденты использования 209 Основы: диаграмма прецедентов использования 209 Уточненная концепция: отношения «include>> и «extend» 212
СОДЕРЖАНИЕ Уточненная концепция: обобщение 217 5.6 Диаграммы деятельности 218 Основы: действия 218 Основы: начало и остановка 219 Основы: узлы принятия решений и слияний 219 Основы: разделы 220 Уточненные концепции: разветвления, объединения и параллельность 221 Уточненные концепции: потоки объектов 223 Уточненные концепции: дополнительные элементы 223 5.7 Диаграммы классов 223 Основы: классы 225 Основы: отношения между классами 226 Уточненные концепции: шаблонные (параметризованные) классы 229 Уточненные концепции: видимость 231 Уточненные концепции: имена полюсов ассоциации и квалификаторы 233 Уточненные концепции: ограничения 234 Уточненные концепции: классы ассоциаций и примечания 237 5.8 Диаграммы последовательностей 239 Основы: объекты и взаимодействия 239 Основы: "линия жизни" и сообщения 240 Уточненные концепции: уничтожение 242 Уточненные концепции: спецификация выполнения 242 Уточненные концепции: механизм использования взаимодействий 243 Уточненные концепции: управляющие конструкции 244 5.9 Диаграммы обзора взаимодействий 245 Основы: рамки 246 Основы: элементы потока управления 247 Основы: элементы диаграммы взаимодействий 248 5.10 Диаграммы композитных структур 248 Основы: части композитных структур 249 Основы: порты и интерфейсы сложной структуры 249 Основы: соединительные звенья композитной структуры 250 Уточненные концепции: механизм сотрудничества 250 5.11 Диаграммы конечных автоматов 252 Основы: начальное, конечное и простое состояния 253 Основы: переходы и состояния 254 Уточненные концепции: вход, операция и выход из состояния 255
СОДЕРЖАНИЕ 11 Уточненные концепции: управляемые переходы 256 Уточненные концепции: сложные и вложенные состояния 258 Уточненные концепции: параллельность и управление 259 Уточненные концепции: состояние конечного автомата 265 Уточненные концепции: дополнительные элементы диаграмм конечных автоматов 265 5.12 Диаграммы синхронизации 265 Основы: элементы диаграмм синхронизации 267 Основы: схема 267 Основы: события 268 Основы: ограничения 268 Уточненные концепции: альтернативное представление 269 Уточненные концепции: события и сообщения 270 5.13 Диаграммы объектов 271 Основы: объекты 271 Основы: отношения между объектами 272 Уточненные концепции: имена и квалификаторы 273 5.14 Диаграммы коммуникации 274 Основы: объекты, связи и сообщения 274 Основы: нумерация сообщений 275 Уточненные концепции: сообщения и синхронизация 277 Уточненные концепции: итерационные выражения и дополнительные условия 278 Резюме 279 Глава 6. Процесс 281 6.1 Основные принципы 281 Характерные черты удачных проектов 281 Рациональный процесс проектирования 285 6.2 Макропроцесс: жизненный цикл разработки программного обеспечения 290 Обзор 291 Содержание макропроцесса — стадии 291 Временные координаты макропроцесса — контрольные точки и этапы 295 Временной аспект макропроцесса — итерации 301 Планирование выпусков 304 6.3 Микропроцесс: анализ и проектирование 307 Обзор 307 Уровни абстракции 308 Микропроцесс и уровни абстракции 315
12 СОДЕРЖАНИЕ Идентификация элементов 318 Определение взаимодействия между элементами 324 Определение отношений между элементами 328 Детализация семантики элементов 331 Резюме 336 Глава 7. Практические вопросы 338 7.1 Управление и планирование 339 Управление риском 339 Планирование заданий 340 Инспектирование проекта 342 7.2 Подбор кадров 343 Распределение ресурсов 343 Роли разработчиков 344 7.3 Управление выпусками 348 Управление конфигурацией и контроль версий 348 Интеграция 349 Тестирование 349 7.4 Повторное использование 350 Элементы повторного использования 350 Как осуществить повторное использование? 351 7.5 Гарантия качества и его показатели 351 Качество программного продукта. 352 Объектно-ориентированные показатели 353 7.6 Документация 356 Наследие разработки 356 Содержание документации 357 7.7 Инструменты 358 Виды инструментов 358 Организационные выводы 359 7.8 Специальные вопросы 360 Специализированные проблемы 360 Адаптация объектных технологий 361 7.9 Преимущества и риски объектно-ориентированной разработки 363 Преимущества 363 Риски, связанные с объектно-ориентированным проектированием 363 Резюме 365 Часть III. Приложения 367 Глава 8. Системная архитектура: спутниковая система навигации 370 8.1 Начало 371
СОДЕРЖАНИЕ 13 Требования, предъявляемые к спутниковой системе навигации 371 Определение границ задачи 374 Формулировка прецедентов выполнения заданий 377 Определение сценариев использования системы 380 8.2 Разработка 383 Разработка хорошей архитектуры 385 Определение действий, связанных с разработкой архитектуры 386 Обоснование предложенной системной архитектуры 387 Распределение нефункциональных требований и определение интерфейсов 397 Согласование системной архитектуры и ее разворачивание 400 Декомпозиция системной архитектуры 403 8.3 Конструирование 410 8.4 Сопровождение 410 Добавление новых функциональных возможностей 410 Изменение аппаратного оборудования 411 Глава 9. Система управления трафиком 413 9.1 Начало 414 Требования к системе управления движением 415 Определение прецедентов использования системы 417 9.2 Разработка 423 Анализ функциональных возможностей системы 423 Определение архитектуры системы TTMS 426 От проектирования системы к разработке аппаратного оборудования и программного обеспечения 430 Ключевые абстракции и механизмы 434 9.3 Конструирование 435 Механизм передачи сообщений 436 Планирование расписания движения поездов 440 Отображение информации 443 Сбор показаний датчиков 445 Управление версиями 445 Архитектура системы 446 Спецификация подсистем 447 9.4 Эксплуатация 450 Глава 10. Искусственный интеллект: криптоанализ 452 10.1 Начало 453 Требования криптоанализа 453 Определение границ задачи 454 Архитектура информационной доски 456
14 СОДЕРЖАНИЕ Анализ источников знаний 459 10.2 Разработка 460 Объекты информационной доски 460 Зависимости и утверждения 462 10.3 Конструирование 464 Проектирование объектов класса Blackboard 465 Проектирование источников знаний 470 Проектирование специализированных источников знаний 470 Обобщение источников знаний 472 Проектирование модуля управления 477 Интеграция модели 478 Интеграция объектов верхнего уровня 478 Реализация механизма оценки предположений 482 Добавление новых источников знаний 483 10.4 Сопровождение 484 Расширение функциональных возможностей 484 Изменение технических требований 486 Глава 11. Сбор данных: метеорологическая станция 487 11.1 Начало 487 Требования к метеорологической станции 488 Определение границ рассматриваемой задачи 488 Сценарии 499 11.2 Проектирование 500 Прецеденты использования системы мониторинга погодных условий 501 Архитектурная основа 511 11.3 Конструирование 513 Механизм временных рамок 513 Планирование выпусков 516 Механизм датчиков 517 Механизм работы дисплея 520 Механизм пользовательского интерфейса 521 11.4 Эксплуатация 524 Глава 12. Web-приложение: система планирования отпусков 526 12.1 Начало 527 Требования 527 Модель использования 529 12.2 Разработка 531 Представление развертывания 532 Логическое представление 533
СОДЕРЖАНИЕ 15 Представление процессов 535 Представление реализации 538 Представление сценариев использования 538 12.3 Конструирование 543 Модель действий пользователя 544 Модели анализа и проектирования 546 Сущности 557 Сервисные объекты данных 561 Генерация первичного ключа 563 Методы поиска 565 Контроллеры 567 Web-страницы и пользовательский интерфейс 567 Заполнение динамического содержания 569 Вызов бизнес-функций 572 12.4 Внедрение и эксплуатация 573 Приложение А. Объектно-ориентированные языки программирования 575 Эволюция языков программирования 575 Язык программирования Smalltalk 578 Язык программирования C++ 584 Язык программирования Java 589 Приложение Б. Рекомендации по дальнейшему чтению 595 Примечания 605 Глоссарий 629 Библиография 641 Предметный указатель 715
Посвящается Джен — моей подруге, возлюбленнной
ПРЕДИСЛОВИЕ По божьей милости человечество жаждет духовной гармонии, эстетического совершенства, безопасности для своих близких, справедливости и свободы. Высокая производительность труда не в состоянии непосредственно обеспечить эти потребности. Тем не менее она избавляет человека от нужды, высвобождая время для духовного развития, эстетического наслаждения, семейных радостей, а также позволяет обществу уделять особое внимание распространению религии, укреплению справедливости и защите свобод. Харлан Миле, "DPMA и производительность труда" Программисты стремятся создавать работоспособные и полезные системы, но сталкиваются с необходимостью решать сложные задачи в условиях ограниченных вычислительных и трудовых ресурсов. Объектно-ориентированная технология (object-oriented (00) technology) возникла и развивалась именно как средство решения проблем, связанных со сложностью, присущей многим программным системам. Время доказало мощь и универсальность объектного подхода. Изменения, внесенные в третье издание Со времени выхода в свет второго издания книги Object-Oriented Analysis and Design with Applications технология достигла больших успехов. Некоторые из них перечислены ниже. • Получило повсеместное распространение широкополосное беспроводное соединение в сети Интернет. • Появилась нанотехнология, на основе которой создаются ценные изобретения. • Роботы уже путешествуют по Марсу. • Специальные эффекты, созданные с помощью компьютеров, позволили кинематографу воссоздавать любую фантазию с абсолютным реализмом.
18 Предисловие • Стали доступными персональные транспортные средства на воздушной подушке. • Повсеместное распространение получили мобильные телефоны. • Расшифрован геном человека. • Объектно-ориентированная технология стала основным методом промышленной разработки программного обеспечения. Использование объектно-ориентированной парадигмы широко используется во всем мире. Однако, как выясняется, многие люди еще не освоили этот метод разработки проектов. Переработанное издание книги станет полезным как для читателей, уже применяющих объектно-ориентированный подход, так и для тех, кто не очень хорошо его понимает. Люди, впервые изучающие объектно-ориентированный анализ и проектирование (object-oriented analysis and design (OOAD)), найдут в книге следующую информацию. • Концептуальные основы и перспективы развития объектно-ориентированного подхода. • Примеры использования методы 00AD на протяжении всего жизненного цикла системы. • Введение в систему стандартных обозначений, используемых при проектировании систем и программного обеспечения, — Unified Modeling Language (UML 2.0) Для опытных проектировщиков, использующих метод 00AD, книга будет интересной по следующим причинам • Язык UML 2.0 по-прежнему неизвестен многим опытным проектировщикам. Они найдут в книге новую систему обозначений. • С учетом критических замечаний, полученных после выхода в свет предыдущих изданий, в новом варианте книги сделан более сильный акцент на моделировании. • Прочтя часть Концепции, читатели смогут понять, "почему вещи таковы, каковы они есть" в объектно-ориентированном мире. Многие люди до сих пор не имеют представления об эволюции концепций объектно-ориентированного проектирования. Впрочем, даже если читателю уже известны некоторые факты на эту тему, он не может отрицать значимости этой информации при первом изучении предмета. Третье издание имеет четыре основных отличий от предыдущих. 1. За прошедшее время язык UML 2.0 получил официальное признание. Эта система обозначений изложена в главе 5. Для того чтобы облегчить читате-
Предисловие 19 лю изучение этого языка, мы отделили его основные элементы от элементов повышенной сложности. 2. В новом издании рассмотрены новые предметные области (см. часть III). В частности, рассмотрены абстракции разного уровня, начиная системами с высокоуровневой архитектурой и заканчивая системами, основанными на использовании Web-технологии. 3. После выхода в свет последнего по времени издания язык C++ претерпел новые изменения, связанные с концепциями объектно-ориентированного программирования. По мнению читателей подчеркивать эту особенность языка C++ уже нет необходимости. Рынок переполнен книгами, посвященными объектно-ориентированному программированию, а также учебниками по языкам программирования, основанным на этой парадигме. По этой причине мы решили изъять из книги большинство фрагментов программ. 4. В заключение, в ответ на пожелания читателей, мы сосредоточили основное внимание на аспектах моделирования в рамках парадигмы OOAD. В третьей части книги, посвященной приложениям, продемонстрированы примеры использования языка UML, причем в каждой главе рассмотрен один из этапов жизненного цикла проекта. Цели Эта книга призвана служить практическим руководством по анализу и созданию объектно-ориентированных систем. Среди прочего следует выделить следующие конкретные задачи. • Помочь читателям понять основные концепции объектной модели и описать ее эволюцию. • Помочь читателям освоить систему обозначений и овладеть методами объектно-ориентированного анализа и проектирования. • Научить читателя практическому применению методов объектно-ориентированного анализа в различных предметных областях. Изложенные понятия имеют строгое теоретическое обоснование, но книга прежде всего призвана удовлетворить практические потребности и интересы разработчиков программного обеспечения: от архитекторов до программистов. Аудитория Книга предназначена как для профессионалов, так и для студентов. • Разработчикам практических систем и программного обеспечения мы покажем, как эффективно применять объектно-ориентированную технологию для решения реальных задач.
20 Предисловие • Аналитикам или архитекторам систем мы покажем, как использовать методы объектно-ориентированного анализа и проектирования на всем пути от постановки задачи до реализации системы. Мы научим читателей отличать "хорошую" объектно-ориентированную архитектуру от "плохой" и находить компромиссы, обеспечивающие живучесть системы в реальных условиях. И что еще более важно, мы предлагаем новые подходы к изучению сложных систем. • Менеджеру программного проекта мы подскажем, как распределить ресурсы в команде разработчиков, обеспечить качество программного обеспечения, оценить его и снизить риски, присущие сложному программному обеспечению. • Студенты найдут в книге начальные знания, позволяющие им приобрести навыки в науке и искусстве создания сложных систем. Книга может быть использована при чтении лекций на младших и старших курсах, а также для проведения профессиональных семинаров и самостоятельного изучения. Книга посвящена, в основном, методам разработки программного обеспечения, поэтому изложенный в ней материал идеально подойдет для курсов проектирования программ и для занятий по объектно-ориентированным языкам. Структура Книга состоит из трех больших частей — "Концепции", "Метод" и "Приложения" — и содержит значительное количество вспомогательного материала. Концепции Первая часть посвящена анализу сложности программного обеспечения, в частности, описанию путей, которыми эта сложность проявляется. В этой части описывается объектная модель, представляющая собой инструмент, позволяющий справиться со сложностью. В ней подробно рассматриваются основные элементы объектной модели: абстракция, инкапсуляция, модульность и иерархия, а также основные понятия, такие как класс и объект. Поскольку выявление осмысленных классов и объектов представляет собой главную задачу объектно-ориентированного проектирования, значительное место уделяется проблемам классификации. В частности, в книге рассматриваются подходы к классификации, принятые в других научных дисциплинах: биологии, лингвистике и психологии, а полученные выводы применяются для выявления классов и объектов, образующих программную систему.
Предисловие 21 Метод Вторая часть описывает метод построения сложных систем, основанный на объектной модели. Сначала вводится система графических обозначений (т.е. язык UML) для объектно-ориентированного анализа и проектирования, а затем рассматриваются основы обобщенного процесса разработки. Кроме того, в книге изучаются практические вопросы объектно-ориентированного проектирования, в частности, роль этого процесса в жизненном цикле программного обеспечения и его значение для управления проектами. Приложения Третья часть книги содержит пять нетривиальных примеров, охватывающих разные предметные области: архитектуру системы, системы управления, криптоанализ, сбор данных и разработку Web-приложений. Выбор этих приложений объясняется тем, что они являются типичными примерами сложных задач, с которыми может столкнуться разработчик программного обеспечения. Выбранные принципы можно было бы легко продемонстрировать на примере решения простых задач, но, поскольку мы нацелены на создание реальных систем, намного интереснее показать, как объектная модель позволяет разрабатывать сложные приложения. Разработку программных систем невозможно свести к набору рецептов, поэтому мы настаиваем на необходимости постепенного развития приложений на основе четких принципов и продуманных моделей. Вспомогательные материалы В текст книги вплетен значительный объем дополнительных сведений. В большинстве глав имеются специальные врезки, в которых содержится информация по отдельным важным темам. Кроме того, книга содержит приложение, посвященное основным свойствам объектно-ориентированных языков, глоссарий основных терминов и обширную библиографию, сгруппированную по темам, связанным с объектной моделью. Замечания об инструментах Читатели часто задают вопросы об инструментах, использованных для построения диаграмм, помещенных в книге. Мы использовали два инструмента для построения диаграмм: IBM Rational Software Architect и Sparx Systems Enterprise Architect. Почему мы не ограничились одной программой? Реальность такова, что на рынке программных средств нет ни одного инструмента, который решал бы абсолютно все задачи. По мере углубления в темы, связанные с применением принципов OOAD, читатели непременно столкнутся с задачей, которую не решает ни одна программа. (В таком случае вы можете обратиться к распространенным
22 Предисловие графическим редакторам, чтобы добиться желаемого результата.) Но не стоит придавать этим исключениям из правил слишком большое значение и отказываться от использования надежных средств 00 AD, упомянутых выше. Как читать книгу? Книгу можно читать последовательно или выборочно. Если вы стремитесь добиться глубокого понимания концепций объектной модели и принципов объектно- ориентированного проектирования, начните с главы 1 и читайте книгу последовательно. Если же вас в основном интересует система обозначений и процесс объектно-ориентированного анализа и проектирования, чтение следует начинать с глав 5 и 6. Менеджерам проектов, использующим объектно-ориентированный метод проектирования, будет особенно полезна глава 7. Если же читателей больше всего интересуют практические приложения объектно-ориентированной технологии в конкретных предметных областях, можно выбрать любую из глав 8-12.
БЛАГОДАРНОСТИ Книга посвящается моей жене Джен (Jan) в благодарность за ее любовь и поддержку. На протяжении всей работы над первым и вторым изданиями мои представления об объектно-ориентированном проектировании уточнялись под влиянием многих людей, которым я хотел бы выразить особую благодарность. В их число входят Сэм Адаме (Sam Adams), Майк Акроид (Mike Akroid), Гленн Андерт (Glenn Andert), Сид Байлин (Sid Bailin), Кент Бек (Kent Beck), Дейв Бернштейн (Dave Bernstein), Дэниел Боброу (Daniel Bobrow), Дик Больц (Dick Bolz), Дэйв Балман (Dave Bulman), Кэйван Кэран (Kayvan Carun), Дэйв Коллинз (Dave Collins), Дами- ан Конвэй (Damian Conway), Стив Кук (Steve Cook), Джим Коплиен (Jim Coplien), Брэд Кокс (Brad Сох), Уард Канингэм (Ward Cunningham), Том ДеМарко (Torn DeMarco), Майк Делвин (Mike Delvin), Ричард Гэбриел (Richard Gabriel), Вильям Генемерас (William Genemeras), Адель Голдьберг (Adele Goldberg), Ян Грэхем (Ian Graham), Тони Хоар (Топу Ноаге), Джон Хопкинс (Jon Hopkins), Майкл Джэксон (Michael Jackson), Ральф Джонсон (Ralph Johnson), Джеймс Кемпф (James Kempf). Норм Керт (Norm Kerth), Джордан Крейндлер (Jordan Kreindler), Дуг Ли (Doug Lea), Фил Леви (Phil Levy), Барбара Лисков (Barbara Liskov), Клифф Лонгмэн (Cliff Longman), Джеймс Макфарлэйн (James MacFarlane), Масуд Милани (Ма- soud Milani), Харлан Миллс (Harlan Mills), Роберт Мюррей (Robert Murray), Стив Нейс (Steve Neis), Джин Уйе (Gene Ouye), Дэйв Парнас (Dave Parnas), Билл Рид- дел (Bill Riddel), Мэри Бет Россон (Mary Beth Rosson), Кении Рубин (Kenny Rubin), Джим Рамбо (Jim Rumbaugh), Курт Шмукер (Kurt Schmucker), Эд Зайдевиц (Ed Seidewitz), Дэн Шифман (Dan Shiftman), Дэйв Стивенсон (Dave Stevenson), Бьерн Страуструп (Bjarne Stroustrup), Дэйв Томас (Dave Thomas), Майк Вило (Mike Vilot), Тони Вассерман (Tony Wasserman), Питер Вегнер (Peter Wegner), Айсел Байт (Iseult White), Джон Уильяме (John Williams), Ллойд Уильяме (Lloyd Williams), Марио Волчко (Mario Wolczko), Никлаус Вирт (Niklaus Wirth) и Эд Йордан (Ed Yourdon).
24 Предисловие Практические главы этой книги воплотили результаты моего участия в разработке сложных программных систем по всему миру для компаний Alcatel, Andersen Consulting, Apple, AT&T, Autotrol, Bell Northern Research, Boeing, Borland, Computer Sciences Corporation, Contel, Ericsson, Ferranti, General Electric, GTE, Holland Signaal, Hughes Aircraft Company, IBM, Lockheed, Martin Marietta, Motorola, NTT, Philips, Rockwell International, Shell Oil, Symantec, Taligent и TRW. Я имел возможность общаться с сотнями профессиональных программистов и менеджеров и благодарю их всех помощь, позволившую сделать эту книгу более близкой к проблемам реальной жизни. Особую благодарность я выражаю компании Rational за поддержку моей работы. Спасибо также Тони Холлу (Tony Hall), рисунки которого оживили довольно сухое техническое содержание книги. Наконец, благодарю трех моих кошек, Кэми (Сату), Энни (Annie) и Шэдоу (Shadow), составлявшим мне компанию в долгие часы ночной работы. Гради Буч (Grady Booch) Во-первых, я возношу хвалу Господу, без которого ничто не существовало бы. Я также благодарен своей семье, стойко переносившей часы разлуки, пока я работал на книгой. Благодарю своих родителей, приучивших меня честно работать. Спасибо Мэри Т. О'Брайен, предложившей мне принять участие в данной работе, а также Крису Гузиковскому (Chris Guzikowski), помогавшему мне довести дело до конца. Кроме того, я признателен моим соавторам, согласившимся принять меня в команду и упорно работавшими над этим проектом. В заключение, я хотел бы сказать, что сердечно благодарен Гради за его многолетнюю работу над созданием оригинальных и фундаментальных книг по объектно-ориентированному анализу и проектированию. Боб Максимчук (Bob Maksimchuk) Я хочу выразить мою признательность своей семье за их любовь и поддержку во всех моих начинаниях. Кроме того, я благодарен Гради за возможность внести свой вклад в третье издание его классической книги. В заключение, хочу сказать спасибо Бобу Максимчуку за помощь в работе над книгой. Майк Энгл (Mike Engle)
Предисловие 25 Я посвящаю мою работу памяти своей матери, Джин Смит (Jean Smith), вдохновившей меня принять участие в этом проекте. Кроме того, я хотела бы выразить мою любовь и признательность своей семье, Руссель (Russell), Алисе (Alyssa) и Логан (Logan), за их поддержку. Благодарю Боба Максимчука и Майка Энгле за возможность разделить вместе с ними радость работы над книгой. Бобби Дж. Янг (Bobbi J. Young) Я хотела бы выразить особую благодарность моему мужу Бобу (Bob) и двум моим детям Кэтрин (Katherine) и Райан (Ryan), чья любовь и поддержка вдохновляли меня. Кэлли А. Хьюстон (Kelli A. Houston) Благодарю рецензентов, особенно Дэвида Норриса (Davyd Norris) и Брайна Лионса (Brian Lyons), а также многих других сотрудников издательства Addison- Wesley, работавших над книгой, особенно Криса Зана (Chris Zahn), который воплотил в жизнь этот огромный проект.
ОБ АВТОРАХ Гради Буч получил всемирное признание за его новаторскую работу в области архитектуры, проектирования и моделирования программных систем. С момента создания компании IBM Rational в 1981 году, он работал ее ведущим научным сотрудником. В марте 2003 года Гради получил звание почетного сотрудника IBM (IBM Fellow). Гради — один из основоположников языка Unified Modeling Language (UML), а также автор нескольких оригинальных разработок компании Rational. Работая над многочисленными проектами, связанными с интенсивным программированием, Гради был не только архитектором программных систем, но и учил сотрудников принципам проектирования. Гради является автором шести бестселлеров, включая справочное руководство UML Users Guide и знаменитую книгу Object-Oriented Analysis with Applications. Гради опубликовал несколько сотен технических статей по проектированию программного обеспечения. В статьях, напечатанных в начале 1980-х годов, он заложил основы теории и практики объектно-ориентированного проектирования. Гради читает лекции и дает консультации по всему миру. Гради Буч является членом Ассоциации по вычислительной технике (Association for Computing Machinery (ACM)), Института инженеров по электротехнике и электронике (Institute of Electrical and Electronics Engineers (IEEE)), Американской ассоциации содействия развитию науки (American Association for the Advancement of Science (AAAS)), а также Общества специалистов по вычислительной технике, выступающих за социальную ответственность (Computer Professionals for Social Responsibility (CPSR)). Он является почетным сотрудником компании IBM, почетным членом ассоциации ACM Fellow, а также организаций World Technology Network Fellow и Software Development Forum Visionary. Гради — один из основателей компаний Agile Alliance, Hillside Group и Worldwide Institute of Software Architects. Кроме того, в качестве консультанта он сотрудничает с университетом Норсфейс (Northface University).
Предисловие 27 Гради получил степень бакалавра наук в Академии военно-воздушных сил США (United States Air Force Academy) в 1977 году, а степень магистра по электротехнике — в университете Калифорнии в г. Санта-Барбара (University of California at Santa Barbara) в 1979 году. Гради живет со своей женой и кошками в Колорадо. Он любит читать, путешествовать, петь и играть на губной гармошке. Роберт Α. Μаксимчук — руководитель научно-исследовательских работ (Research Director) в компании Unisys Chief Technology Office. В центре его научных интересов находятся новые технологии моделирования, разрабатываемые в среде Unisys 3D-Visual Enterprise. Боб сделал большой вклад в развитие методов проектирования систем, моделирования и анализа проектов в разных промышленных отраслях. Он соавтор книг UML for Mere Mortals и UML for Database Design, а также автор большого количества статей. Роберт путешествует по всему миру в качестве приглашенного лектора, выступая на многочисленных форумах и семинарах по языку UML и объектно-ориентированному проектированию. Боб является членом Института инженеров по электротехнике и электронике (Institute of Electrical and Electronics Engineers (IEEE)) и Международного совета по проектированию систем (International Council on Systems Engineering (INCOSE)). Майкл У. Энгл — главный инженер компании Lockheed Martin Corporation. Его технический и управленческий опыт работы в области проектирования систем достигает 26 лет. Майкл принимал участие в разработке систем на самых разных этапах их жизненного цикла — от начала проекта до сопровождения. Используя свой опыт системного инженера и архитектора, Майк применяет объектно-ориентированные методы для выработки новаторских подходов к проектированию сложных систем. Бобби Янг, доктор философии (Ph.D.) — руководитель научно-исследовательских работ (Director of Research) в компании Unisys Chief Technology Office. Она имеет многолетний опыт работы в области информационных технологий, в частности, в коммерческих компаниях и в Министерстве обороны США. Доктор Янг работала консультантом по подготовке менеджеров в области разработки программ, архитектуры предприятий, проектирования систем, а также объектно-ориентированного анализа и проектирования. В ходе своей карьеры она занималась процессами, протекающими на протяжении всего жизненного цикла программного обеспечения, вопросами методологии, а также архитектурой предприятий. Доктор Янг — обладательница научных степеней по биологии, компьютерным наукам и искусственному интеллекту. Степень доктора философии она получила в области управления информационными системами. Кроме того, Бобби Янг имеет воинское звание капитана 3-го ранга в отставке (Commander) Резерва военно- морского флота США (United States Naval Reserves). Джим Коналлен — разработчик программного обеспечения в команде Model Driven Development Strategy компании IBM Rational, в которой он активно при-
28 Предисловие меняет методы модельной архитектуры (Model Driven Architecture (MDA)), предложенные компанией Object Management Group (OMG), к инструментам моделирования компании IBM Rational. Кроме того, Джим много работает в области проектирования, основанного на активах (asset-based development), а также над спецификацией Reusable Asset Specification (RAS). Джим часто выступает на конференции и публикует статьи. В круг его интересов входит проектирование Web- приложений. Он разработал расширение языка UML Web Application Extension for UML (WAE), позволяющее разработчикам моделировать Web-архитектуры с помощью языка UML с достаточным уровнем абстракции и детализации. Эта работа стала основой методов IBM Rational Rose и Rational XDE Web Modeling. Джим — автор двух изданий книги Building Web Applications with UML, в которой впервые были рассмотрены технологии Active Server Pages компании Microsoft и J2EE. Свой жизненный опыт Джим получил, работая независимым консультантом в компании Rational, добровольцем Корпуса мира (Peace Corps), преподавателем в колледже и отцом трех мальчиков. Джим прослушал базовый курс и получил степень магистра в университете Виденер (Widener University) по проектированию компьютеров и программного обеспечения. Келли Хьюстон — консультант по информационным технологиям (Consulting IT Specialist) в компании IBM Rational. Она является архитектором методов и отвечает за интеграцию методов, предложенных компанией IBM. Кроме того, Келли руководит работой группы Rational Method Composer (RMC) Special Interest Group (SIG) в компании IBM и проводит консультации и обучение пользователей и внутренних консультантов компании IBM эффективному использованию системы RMC.
ОТ ИЗДАТЕЛЬСТВА Вы, читатель этой книги, и есть главный ее критик и комментатор. Мы ценим ваше мнение и хотим знать, что было сделано нами правильно, что можно было сделать лучше и что еще вы хотели бы увидеть изданным нами. Нам интересно услышать и любые другие замечания, которые вам хотелось бы высказать в наш адрес. Мы ждем ваших комментариев и надеемся на них. Вы можете прислать нам бумажное или электронное письмо, либо просто посетить наш Web-сервер и оставить свои замечания там. Одним словом, любым удобным для вас способом дайте нам знать, нравится или нет вам эта книга, а также выскажите свое мнение о том, как сделать наши книги более интересными для вас. Посылая письмо или сообщение, не забудьте указать название книги и ее авторов, а также ваш обратный адрес. Мы внимательно ознакомимся с вашим мнением и обязательно учтем его при отборе и подготовке к изданию последующих книг. Наши координаты: E-mail: info@williamspublishing.com WWW: http://www.williamspublishing.com Информация для писем из России: 127055, Москва, ул. Лесная, д. 43, стр. 1 из Украины: 03150, Киев, а/я 152
This empty page
ЧАСТЬ I Концепции
Сэр Исаак Ньютон по секрету признавался своим избранным друзьям, что знает, как проявляется гравитация, но не знает, как она действует! Лили Томлин, "Поиски признаков разумной жизни во Вселенной" На заре развития объектной технологии многие люди осваивали ее, изучая языки программирования. Они выясняли возможности этих языков и пытались применить их для решения практических задач. Со временем, по мере совершенствования языков программирования, а также изобретения новых методов и приемов проектирования была разработана формальная объектно-ориентированная методология. В настоящее время объектно-ориентированное проектирование является мощной и богатой идеями парадигмой. В этой части книги рассматриваются теоретические основы и описываются механизмы реализации объектно-ориентированной парадигмы.
ГЛАВА 1 СЛОЖНОСТЬ Врач, строитель и программист поспорили о том, чья профессия древнее. Врач заметил: "В Библии сказано, что Бог создал Еву из ребра Адама. Это мог сделать только хирург, поэтому моя профессия самая древняя в мире". Его перебил строитель: "Однако, как сказано в Книге Бытия, еще раньше Бог сотворил из хаоса сначала небо, а потом — землю. Это было первое и, несомненно, наиболее впечатляющее строительство. Следовательно, дорогой доктор, вы ошибаетесь. Именно моя профессия самая древняя в мире". Услышав это, программист откинулся на спинку кресла, улыбнулся и спросил доверительным тоном: "Ну а кто же, по-вашему, создал хаос?" "Чем сложнее система, тем она уязвимее" [5]. Трудно себе представить строителя, размышляющего, а не вырыть ли еще один подвальный этаж под уже построенным стоэтажным зданием. Такое мероприятие было бы слишком дорогим и опасным. Как ни странно, пользователи программного обеспечения, не задумываясь, просят делать аналогичные изменения в программах. Более того, он считают, что для программиста эта задача не представляет никаких трудностей. Наша неспособность справиться со сложностью, характерной для программного обеспечения, приводит к задержкам, дополнительным расходам и нарушениям технического задания. Такую ситуацию часто называют кризисом программного обеспечения, но, откровенно говоря, болезнь, длящуюся столь долго, следует называть нормальным состоянием. К сожалению, этот кризис уже привел в расточительному расходованию трудовых ресурсов — самого дорогого товара, — и многие возможности оказались упущенными. Для того чтобы создать новое программное обеспечение, необходимое пользователям, совершенно не достаточно просто собрать команду хороших программистов. Кроме того, во многих организациях большое количество персонала вынуждено отвлекаться на поддержку морально устаревших программ. Учитывая прямой и косвенный вклад, который
34 Часть I. Концепции вносит программное обеспечение в экономику наиболее развитых стран, а также огромные возможности, появляющиеся благодаря информатизации, следует признать, что мириться с такой ситуацией больше нельзя. 1.1 Структура сложных систем Как изменить эту мрачную картину? Поскольку источником всех проблем является сложность, присущая программному обеспечению, следует начать с изучения сложных систем, существующих в других научных дисциплинах. Действительно, если оглянуться вокруг, то можно обнаружить весьма успешно функционирующие системы, обладающие значительной сложностью. Некоторые из этих систем созданы человеком, например, космический корабль "Space Shuttle", туннель, соединяющий Англию и Францию, а также крупные корпорации. В природе существуют еще более сложные системы, такие как система циркуляции крови у человека и перец "хабанеро". Структура персонального компьютера Персональный компьютер — это устройство средней сложности. Большинство персональных компьютеров состоит из одних и тех же основных элементов: центрального процессора (central processor unit — CPU), монитора, клавиатуры и внешнего запоминающего устройства, как правило, CD- или DVD-дисковода и жесткого диска. Любой из этих компонентов можно, в свою очередь, разложить на более мелкие составляющие части. Например, центральный процессор обычно состоит из первичной памяти, арифметико-логического устройства (arithmetic/ logic unit — ALU) и шины, к которой присоединены периферийные устройства. Каждую из этих частей также можно разложить на компоненты: арифметико- логическое устройство состоит из регистров и схем произвольного управления (random control logic), которые в свою очередь состоят из еще более простых деталей: вентилей, инверторов и т.д. Этот пример демонстрирует иерархическую природу сложной системы. Нормальная работа персонального компьютера обеспечивается только взаимодействием всех его составных частей. Вместе взятые, эти отдельные части образуют логическое целое. Действительно, чтобы понять, как работает компьютер, необходимо разделить его на компоненты и рассмотреть их по отдельности. Следовательно, работу монитора и жесткого диска можно изучать независимо друг от друга. Точно так же можно изучать арифметико-логическое устройство, не обращая внимания на подсистему первичной памяти. Иерархия характерна не только для сложных систем, но и для абстракций. В рассмотренном выше примере компонентам персонального компьютера соответствуют определенные понятия, образующие уровни абстракции. Каждому
Глава 1. Сложность 35 из этих уровней соответствует совокупность устройств, взаимодействие которых обеспечивает функционирование компонентов более высокого уровня. Конкретный уровень абстракции можно выбирать, исходя из определенных заранее потребностей. Например, для исследования синхронизации первичной памяти целесообразно рассмотреть компьютер на уровне вентилей. В то же время этот уровень абстракции неприемлем, если требуется найти ошибку в электронной таблице. Структура растений и животных Ботаники стремятся понять сходство и различия между растениями, изучая их морфологию, т.е. форму и структуру. Растения — это сложные многоклеточные организмы, поведение которых, например, фотосинтез и испарение влаги, обеспечивается взаимодействием различных органов. Растения состоят из трех основных частей — корней, стеблей и листьев. Каждая из этих частей имеет особую структуру. Например, корень состоит из отростков, волосков, верхушки и чехлика. Аналогично, изучая срез листа, можно обнаружить эпидермис, мезофилл и сосудистую ткань. Каждая из этих структур, в свою очередь, представляет собой совокупность клеток. Внутри каждой клетки можно обнаружить новый уровень сложности, охватывающий хлоропласты, ядро и т.д. Как и компьютер, растение представляет собой иерархию определенных компонентов, каждый уровень которой характеризуется собственной сложностью. Все части, относящиеся к одному и тому же уровню абстракции, взаимодействуют вполне определенным образом. Рассматривая растение на высшем уровне абстракции, можно обнаружить следующую картину. Корни поглощают из почвы воду и минеральные вещества и передают их стеблям. Стебли доставляют эти вещества листьям, которые, в свою очередь, при помощи фотосинтеза производят из них необходимые питательные элементы. Между разными уровнями абстракции всегда существует четкая граница. Например, компоненты листа совместно обеспечивают его функционирование как единого целого и почти не взаимодействуют с элементами корней. Проще говоря, между частями, относящимися к разным уровням абстракции, существует четкое разделение функций. В компьютере вентили являются элементами как центрального процессора, так и жесткого диска. В разных частях растения также можно найти общие структурные элементы. Так Бог экономит средства выражения. Например, клетки служат основными строительными блоками всех структур растения. В конце концов, корни, стебли и листья растения состоят именно из клеток. Однако существует множество разновидностей клеток. Например, одни клетки содержат хлоропласты, а другие — нет, оболочки одних клеток пропускают воду, а другие — нет, кроме того, клетка может быть живой или мертвой.
36 Часть I. Концепции Изучая морфологию растения, невозможно выделить отдельные части, отвечающие за какую-то одну небольшую фазу единого крупного процесса, например, фотосинтеза. В растении не существует централизованных частей, непосредственно координирующих деятельность компонентов, относящихся к более низким уровням. Вместо этого в нем существуют отдельные части, действующие как независимые агенты, каждая из которых имеет довольно сложное поведение, являющееся частью функций более высокого уровня. Более высокий уровень функционирования растения обеспечивается только благодаря целенаправленному взаимодействию независимых агентов. В теории сложности это явление называется производным поведением (emergent behaviour): поведение целого сложнее, чем поведение суммы его составляющих [6]. Обратившись к зоологии, можно выяснить, что многоклеточные животные, как и растения, имеют иерархическую структуру: совокупности клеток формируют ткани, образующие органы, группы которых определяют систему (например, пищеварительную) и т.д. Здесь также проявляется экономия средств выражения, характерная для Бога. Основными кирпичиками, из которых состоят как животные, так и растения, являются клетки. Разумеется, клетки растений и животных отличаются друг от друга. Например, клетки растений заключены в жесткую целлюлозную оболочку, а клетки животных — нет. Несмотря на эти различия, обе эти структуры, несомненно, являются клетками. Это явление представляет собой пример общности разных организмов. Кроме того, в растениях и животных существует огромное количество механизмов надклеточного уровня. И растения, и животные используют сосудистую систему для транспортировки питательных веществ внутри организма, а между индивидуумами одного и того же вида существуют половые различия. Структура материи Исследования в таких разных областях, как астрономия и ядерная физика, дают много других примеров невероятно сложных систем. Эти научные дисциплины демонстрируют примеры иерархических систем нового типа. Астрономы изучают галактики, которые объединены в скопления. В свою очередь, галактики состоят из звезд, планет и других небесных тел. Специалисты по ядерной физике сталкиваются со структурной иерархией физических тел совершенно другого масштаба. Атомы состоят из электронов, протонов и нейтронов; электроны являются элементарными частицами, а протоны и нейтроны делятся на еще более мелкие компоненты — кварки. В этих сложных иерархиях вновь обнаруживаются универсальные механизмы. В частности, во Вселенной действуют всего четыре типа сил: гравитационное, электромагнитное, сильное и слабое взаимодействия. Многие законы физики, ка-
Глава 1. Сложность 37 сающиеся этих взаимодействий, например, закон сохранения энергии и импульса, носят универсальный характер, распространяясь как на галактики, так и на кварки. Структура общественных институтов В качестве последнего примера сложных систем обратимся к общественным институтам. Люди объединяются в группы для решения задач, которые не могут быть решены индивидуумами. Одни организации являются временными, другие существуют на протяжении нескольких поколений. Чем крупнее организация, тем отчетливее проявляется ее иерархическая структура. Например, транснациональные корпорации состоят из компаний, которые в свою очередь образуются подразделениями, включающими в себя филиалы, которым принадлежат местные офисы и т.д. Если организация проходит испытание временем, то границы между ее частями могут измениться, а затем может возникнуть новая, более устойчивая иерархия. Отношения между разными частями крупной организации напоминают отношения между компонентами компьютера, растения или галактики. В то же время, степень взаимодействия между сотрудниками одного офиса выше, чем между сотрудниками двух разных офисов. Почтовый служащий, например, как правило, не общается с исполнительным директором компании, а в основном контактирует со своими коллегами по почтовому отделению. Однако при этом разные уровни организации объединены общими механизмами. Так, работа служащего и директора оплачивается одной и той же финансовой организацией, причем они оба используют общее оборудование, в частности, телефонную систему компании. 1.2 Сложность, присущая программному обеспечению Звезда на грани коллапса, ребенок, который учится читать, белые клетки крови, атакующие вирус, — вот лишь некоторые из объектов физического мира, имеющих поистине удивительную сложность. Программное обеспечение тоже бывает очень сложным, однако эта сложность совершенно другого рода. Брукс (Brooks) пишет: "Эйнштейн полагал, что должно существовать простое описание природы, так как Бог не действует случайным образом. У программиста нет такого утешения: сложность, которую он должен преодолеть, носит произвольный характер" [1]. Определение сложности программного обеспечения Как известно, не все системы программного обеспечения являются сложными. Существует хорошо забытый класс приложений, проектируемых, разрабатываемых, сопровождаемых и используемых одним и тем же человеком, — либо начи-
38 Часть I. Концепции нающим программистом, либо профессионалом, работающим в одиночку. Это не значит, что такие системы плохо спроектированы и неэлегантны. Тем более, никто не ставит под сомнение квалификацию их создателей. Просто такие системы, как правило, имеют очень ограниченную область применения и очень недолго используются. Как правило, их проще заменить новыми программами, чем пытаться повторно использовать, переделывать или совершенствовать. Разработка таких приложений скорее утомительна, чем сложна, поэтому они не представляют для нас интереса. Предметом нашего исследования являются проблемы разработки промышленного программного обеспечения. В этой области можно найти программы, демонстрирующие самые разные виды поведения, например, системы с обратной связью, которые управляют или управляются событиями физического мира при ограниченных ресурсах времени и памяти; программы, поддерживающие целостность баз данных, содержащих сотни тысяч записей и обеспечивающих параллельное обновление и запросы; системы управления и контроля за реальными объектами, например, системы управления воздушными или железнодорожными перевозками. Такие системы обычно используются довольно долго, и со временем от их нормального функционирования начинают зависеть многие пользователи. В отрасли промышленного программирования также существуют средства, упрощающие создание приложений в конкретных предметных областях, а также программы, имитирующие некоторые аспекты человеческого интеллекта. Важнейшей особенностью промышленной программы является ее высокая сложность. Одному программисту не под силу решить все проблемы, связанные с проектированием такой системы. Грубо говоря, сложность промышленных программ превышает интеллектуальные возможности отдельного человека. Увы, это свойство является существенной характеристикой всех крупных систем программного обеспечения. Слово "существенная" означает, что со сложностью промышленных программ можно справиться, но игнорировать ее нельзя. Почему программному обеспечению присуща сложность? Брукс утверждает: "Сложность программного обеспечения является существенным, а не случайным свойством" [3]. Это объясняется четырьмя причинами: сложностью предметной области, трудностью управления разработкой программного обеспечения, необходимостью обеспечить гибкость программ, а также сложностью описания функционирования дискретных систем. Сложность предметной области Пытаясь решить проблемы с помощью программного обеспечения, мы неизбежно сталкиваемся с необходимостью удовлетворить множество различных, иногда взаимоисключающих требований. Рассмотрим требования, предъявляемые
Глава 1. Сложность 39 к электронной системе многомоторного самолета, коммутатору сотового телефона и автономного робота. Механизмы функционирования таких систем уже сами по себе довольно сложны для понимания, а если прибавить к этому дополнительные требования (часто неявные), такие как удобство, производительность, стоимость, устойчивость и надежность, то сложность задачи может стать произвольной, о чем и предупреждал Брукс. Эта внешняя сложность обычно порождается "недопониманием", существующим между пользователями системы и ее разработчиками, поскольку пользователям очень трудно выразить свои потребности в форме, понятной разработчикам. Иногда пользователь очень смутно представляет себе, что ему нужно от будущей системы программного обеспечения. Это нельзя назвать виной пользователей или разработчиков; просто каждая из этих групп испытывает недостаток знаний в предметной области другой группы. Пользователи и разработчики часто по-разному видят сущность проблемы и предлагают разные способы ее решения. На самом деле, даже если пользователь точно знает, что ему нужно, его требования очень трудно формализовать. Как правило, они описываются в многотомных документах, проиллюстрированных несколькими рисунками. Такие документы трудно понять, они допускают неоднозначную интерпретацию и очень часто содержат информацию, относящуюся скорее к проектированию, а не выражают основные требования заказчика. Требования, предъявляемые к системе программного обеспечения, в процессе разработки часто изменяются. Это еще больше повышает ее сложность. Как правило, техническое задание корректируется из-за того, что в процессе проектирования системы постановка задачи постепенно уточняется. Знакомясь с первыми результатами, описанными в проектной документации и реализованными в прототипах, а также используя систему после ее инсталляции, пользователи начинают лучше понимать и четче формулировать свои реальные потребности. В то же время, этот процесс позволяют разработчикам вникнуть в предметную область и ставить более точные вопросы, проясняющие темные места проектируемой системы. Поскольку крупная система программного обеспечения всегда связана с инвестированием средств, мы не можем позволить себе выбрасывать существующую систему при каждом изменении технического задания. Системы со временем эволюционируют, по плану или спонтанно. Иногда этот процесс по ошибке называют сопровождением программного обеспечения. Точнее говоря, сопровождением (maintenance) называется исправление выявленных ошибок, эволюцией (evolution) — реакция на изменение технических требований, а сохранением (preservation) — попытка всеми возможными средствами продлить функционирование устаревших и распадающихся частей программного обеспечения. К сожалению, как показывает опыт, значительная доля ресурсов, выделенных на разработку программных систем, тратится именно на сохранение.
40 Часть I. Концепции Задача группы проектировщиков — создать иллюзию простоты Трудности управления проектированием Основная задача разработчиков программного обеспечения — создать иллюзию простоты, чтобы защитить пользователей от огромной и часто произвольной сложности проекта. Очевидно, что крупный масштаб системы программного обеспечения не относится к ее основным достоинствам. Для уменьшения размеров программ изобретаются хитроумные и мощные методы, создающие иллюзию простоты и позволяющие повторно использовать существующие коды и проектные решения. Тем не менее требования, предъявляемые к системе, часто вынуждают проектировщиков либо создавать заново большое количество программ, либо использовать существующий код, адаптируя его к новым условиям. Всего несколько десятилетий назад программы объемом в несколько тысяч строк, написанные на ассемблере, поражали воображение. В настоящее время никого не удивляют системы программного обеспечения, размер которых исчисляется десятками тысяч или даже миллионами строк (причем на языках высокого уровня). Ни один человек никогда не сможет полностью понять такую систему. Даже если разложить ее на составные части, придется анализировать сотни, а иногда и тысячи отдельных модулей. Такой объем работ под силу лишь команде разработчиков, состав которой в идеале должен быть минимальным. Независимо от количества разработчиков, перед ними постоянно возникают сложные проблемы, связанные с коллективным проектированием. Чем больше разработчиков, тем сложнее связи между ними и тем труднее координировать их взаимодействие, особенно если участники работ географически удалены друг от друга, что происходит довольно часто. Таким образом, при коллективной разработке программного обеспечения главной задачей руководства является обеспечение единства и целостности проекта.
Глава 1. Сложность 41 Необходимость обеспечить гибкость программ Строительные компании обычно не имеют собственного лесного хозяйства, которое поставляло бы им лес для производства пиломатериалов, и не владеют металлургическими заводами, изготавливающими стальные балки для будущих зданий. Однако в программной индустрии такая практика получила широкое распространение. Программирование обладает предельной гибкостью и позволяет проектировщику выражать абстракции любого уровня. Эта гибкость весьма привлекательна, поскольку она побуждает разработчика самостоятельно создавать практически все базовые конструкции, из которых состоят абстракции более высоких уровней. В отличие от строительной промышленности, в которой существуют общепринятые требования к качеству материалов, в программной индустрии таких стандартов почти нет. В результате проектирование программного обеспечения остается трудоемким делом. Сложность описания дискретных систем Бросая мяч в воздух, мы можем точно предсказать его траекторию, потому что в нормальных условиях действуют определенные физические законы. Мы бы очень удивились, если бы, бросив мяч чуть сильнее, обнаружили, что на середине пути он неожиданно остановился и полетел вертикально вверх1. В недостаточно отлаженной программе моделирования полета мяча такая ситуация вполне возможна. Внутри крупного приложения могут существовать сотни и даже тысячи переменных, а также несколько потоков управления. Состояние прикладной программы в каждый момент времени описывается совокупностью всех переменных, их текущих значений, адресов и стеков вызова для каждого процесса. Так как программа выполняется на цифровых компьютерах, возникает система с дискретными состояниями. Аналоговые системы, такие как движение брошенного мяча, наоборот, являются непрерывными. Парнас (Parnas) утверждает: "Когда мы говорим, что система описывается непрерывной функцией, мы имеем в виду, что в ней нет скрытых сюрпризов. Небольшие изменения входных параметров всегда вызывают небольшие изменения результатов" [4]. С другой стороны, дискретные системы имеют конечное число возможных состояний. В крупных системах наблюдается так называемый комбинаторный взрыв, делающий это число очень большим. lipoma самом деле даже простые непрерывные системы могут иметь очень сложное поведение из-за наличия хаоса. Хаос привносит случайность, не позволяющую точно предсказать будущее состояние системы. Например, зная начальное положение двух капель воды, упавших в ручей, мы не можем точно предсказать, на каком расстоянии друг от друга они окажутся, достигнув дна. Хаос существует в разных системах, например, в атмосфере, химических реакциях, биологических системах и даже компьютерных сетях. К счастью, в хаотических системах существует скрытый порядок, проявляемый в виде так называемых аттракторов.
42 Часть I. Концепции ектируя системы, разработчики, как правило, разделяют их на компоненты так, чтобы одна часть как можно меньше влияла на другую. Однако переходы между дискретными состояниями невозможно моделировать с помощью непрерывных функций. Каждое событие, внешнее по отношению к системе, может перевести ее в новое состояние, и, более того, переход из одного состояния в другое не всегда является детерминированным. В худшем случае внешнее событие может повредить систему из-за того, что ее создатели не предусмотрели все возможные варианты. Если в программном обеспечении двигательной установки корабля возникнет переполнение памяти, вызванное некорректными входными данными (как это произошло однажды в действительности), последствия могут оказаться очень серьезными. Еще недавно в программном обеспечении систем управления метрополитеном, автомобилями, спутниками, воздушным движением, складами и т.д. наблюдался резкий рост количества сбоев. В непрерывных системах такое поведение было бы маловероятным, но в дискретных системах любое внешнее событие может повлиять на любую часть внутреннего состояния системы. Очевидно, это является основным стимулом для интенсивного тестирования систем программного обеспечения. Тем не менее, за исключением самых простых систем, исчерпывающее тестирование провести невозможно. В настоящее время нет ни математических инструментов, ни интеллектуальных возможностей для полноценного моделирования поведения больших дискретных систем. Следовательно, мы должны удовлетвориться приемлемым уровнем уверенности в их правильной работе. 1.3 Пять признаков сложной системы Изучая природу сложности, мы выделили пять признаков, присущих любой сложной системе. Иерархическая структура Следуя работе Саймона (Simon) и Эндо (Ando), Куртуа (Courtois) утверждает следующее. Часто сложность проявляется в виде иерархии, при этом сложные системы состоят из взаимозависимых подсистем, имеющих, в свою очередь, собственные подсистемы, и т.д., вплоть до самого низкого уровня, образованного элементарными компонентами. [7] Саймон отмечает: "Тот факт, что многие сложные системы имеют почти разложимую, иерархическую структуру, является главным фактором, позволяющим нам понять, описать и даже "увидеть" такие системы и их части" [8]. Действи-
Глава 1. Сложность 43 тельно, похоже на то, что можно понять лишь системы, имеющие иерархическую структуру. Важно отметить, что архитектура сложных систем зависит как от компонентов, так и от иерархических отношений между ними. "Все системы имеют подсистемы, и все системы являются частями более крупных систем... Сущность системы определяется отношениями между ее частями, а не частями как таковыми" [9]. Архитектура сложной системы зависит как от ее компонентов, так и от иерархических отношений между ними Относительность выбора элементарных компонентов Опыт исследования природы элементарных компонентов сложных систем показывает следующее. Как правило, наблюдатель произвольно решает, какие компоненты в данной системе считать элементарными. Элементарный компонент с точки зрения одного наблюдателя может оказаться на гораздо более высоком уровне абстракции с точки зрения другого. Разделение функций Саймон называет иерархические системы разложимыми (decomposable), поскольку их можно разделить на идентифицируемые части, и почти разложимыми
44 Часть I. Концепции (nearly decomposable), так как их составляющие не являются абсолютно независимыми друг от друга. Это приводит нас к следующему общему свойству всех сложных систем: Связи внутри компонентов обычно сильнее, чем связи между компонентами. Это обстоятельство позволяет отделить "высокочастотную" динамику компонентов, — относящуюся к их внутренней структуре, — от "низкочастотной" динамики, — относящейся к взаимодействию между компонентами" [10]. Это различие между внутри- и межкомпонентными взаимодействиями позволяет провести разделение функций (separation of concerns) между частями системы и изучать их по отдельности. Общая структура Как уже отмечалось, многие сложные системы реализуются с помощью экономных средств выражения. Это позволило Саймону утверждать следующее. "Иерархические системы обычно состоят из немногих типов подсистем, по-разному скомбинированных и организованных" [11]. Иначе говоря, сложные системы имеют общую структуру. Это может проявляться в виде повторного использования как мелких компонентов, например, клеток организма, так и более крупных структур, таких как сосудистые системы, имеющиеся и у растений, и у животных. Устойчивые промежуточные формы Как отмечалось выше, сложные системы эволюционируют во времени. В частности, считается, что "сложные системы развиваются из простых гораздо быстрее, если они имеют устойчивые промежуточные формы" [12]. Эту мысль можно выразить более эффектно. "Любая работоспособная сложная система является итогом эволюции более простой работоспособной системы... Сложная система, разработанная "с нуля", никогда не работает так как надо, и никакие "заплатки" не заставят ее работать правильно. Проектирование следует начинать с простой работоспособной системы" [13]. В процессе эволюции системы объекты, первоначально считавшиеся сложными, становятся элементарными компонентами, из которых создаются еще более сложные системы. Более того, правильные элементарные объекты невозможно создать сразу: сначала с ними необходимо поработать, получше изучить реальное поведение системы и лишь затем усовершенствовать.
Глава 1. Сложность 45 1.4 Организованная и неорганизованная сложность Выявление общих абстракций и механизмов значительно облегчает понимание сложных систем. Например, опытный пилот всего за несколько минут может разобраться в устройстве многомоторного реактивного самолета, на котором он до этого никогда не летал, и безопасно им управлять. Зная элементы, общие для всех подобных самолетов, такие как руль управления, элероны и дроссель, пилот может сосредоточиться лишь на отличительных особенностях конкретного самолета. Если пилот уже умеет летать на каком-то самолете, ему намного легче научиться управлять другим похожим самолетом. Каноническая форма сложной системы Рассмотренный пример наводит на мысль, что до сих пор мы использовали слишком общую интерпретацию термина иерархия. Наиболее интересные сложные системы содержат много разных иерархий. Например, самолет можно разделить на несколько систем: силовая установка, система управления полетом и т.д. Такое разделение дает структурную иерархию, основанную на отношении "является частью" ("part of). С другой стороны, устройство самолета можно анализировать совершенно иначе. Например, турбореактивный двигатель — это определенная разновидность реактивного двигателя, а двигатель "Pratt and Whitney TF30" — это конкретный тип турбореактивного двигателя. Иначе говоря, понятие "реактивный двигатель" обобщает свойства, характерные для всех реактивных двигателей, а понятие "турбореактивный двигатель" представляет собой уточнение вида реактивного двигателя, обладающего определенными свойствами, которые позволяют отличить его от других, например, от прямоточного воздушно-реактивного двигателя. Вторая иерархия основана на отношении "является" ("is-a"). Опыт показывает, что любую систему следует рассматривать с обеих точек зрения, изучая ее и как иерархию "целое/часть", и как иерархию "общее/частное". По причинам, которые станут ясными в следующей главе, мы назовем эти иерархии соответственно структурой классов (class structure) и структурой объектов (object structure)2. Для читателей, знакомых с объектной технологией, мы сделаем несколько уточнений. В данном случае, говоря о структуре классов и структуре объектов, мы не имеем в виду классы и объекты, создаваемые программистами. Мы имеем в виду более абстрактные классы и объекты, образующие сложную систему, 2В сложных системах программного обеспечения существуют и другие типы иерархий. Среди них особенно важными являются модульная структура, описывающая отношения между физическими компонентами системы, и иерархия процессов, описывающая отношения между динамическими компонентами.
46 Часть I. Концепции например, реактивный двигатель, корпус, сиденья, подсистема автопилота и т.д. Напомним, что выбор элементарных компонентов зависит от наблюдателя. На рис. 1.1 продемонстрированы две ортогональных иерархии одной системы: структура классов и структура объектов. Каждая иерархия является многоуровневой, причем на каждом уровне классы и объекты состоят из более простых компонентов. Выбор элементарных классов и объектов зависит от рассматриваемой задачи. Анализ любого уровня иерархии позволяет выявить новый уровень сложности, обусловленный тесным взаимодействием между его объектами. Рис. 1.1. Основные иерархии сложных систем Сопоставляя структуры классов и структуры объектов с пятью атрибутами сложных систем (иерархической организацией, наличием множества уровней абстракции, разделением функций, общей структурой и устойчивыми промежуточными формами), легко понять, что практически все сложные системы имеют одинаковую (каноническую) форму, показанную на рис. 1.2. В собирательном значении структура классов и структура объектов образуют архитектуру (architecture) системы. Отметим также, что структура классов и структура объектов не являются полностью независимыми друг от друга: каждый элемент структуры объектов представляет специфический экземпляр определенного класса. (Обратите внимание на классы СЗ, С5, С7 и С8 и количество экземпляров 03, 05, 07 и 08, показанные на рис. 1.2.) Как показано на рис. 1.2, количество объектов в сложной системе обычно намного превышает количество классов. Анализ обеих иерархий позволяет выявить избыточность рассматриваемой системы. В противном случае пришлось бы дублировать информацию о свойствах каждого компонента системы. Структура классов решает эту проблему, позволяя описать все общие свойства в единственном месте.
Глава 1. Сложность 47 Каноническая форма N&ift Рис. 1.2. Каноническая форма сложной системы Одна и та же структура классов допускает разные способы конкретизации и организации объектов. Ни одну архитектуру нельзя назвать единственно правильной. Это обстоятельство порождает основную проблему, связанную с архитектурой системы, — поиск баланса между множеством разных способов организации компонентов, пятью атрибутами сложных систем и потребностями пользователей. Как показывает опыт, наиболее успешными оказываются системы программного обеспечения, обладающие пятью атрибутами сложных систем и хорошо продуманными структурами классов и объектов. Для того чтобы подчеркнуть важность этого наблюдения, сформулируем эту мысль более категорично: очень редко встречаются системы программного обеспечения, разработанные вовремя, не выходящие за пределы сметы и удовлетворяющие требованиям заказчика, в которой бы не были учтены факторы, изложенные выше.
48 Часть I. Концепции Пределы человеческих возможностей Если известно, как следует проектировать сложные системы программного обеспечения, то почему при создании таких систем мы все еще сталкиваемся с серьезными проблемами? Дело в том, что концепция организованной системы программного обеспечения (основные принципы которой называются объектной моделью (object model)) появилась относительно недавно. Однако существует еще один фактор, имеющий решающее значение: физическая ограниченность возможностей человека при работе со сложными системами. Начиная анализировать сложную систему программного обеспечения, мы обнаруживаем множество составных частей, взаимодействующих друг с другом разными довольно запутанными способами, причем ни сами части системы, ни способы их взаимодействия не похожи друг на друга. Это — пример неорганизованной сложности. В процессе преодоления сложности системы на этапе ее проектирования и организации взаимодействия ее компонентов необходимо думать сразу о многом. Например, система управления воздушным движением должна одновременно контролировать состояние многих самолетов, учитывая, например, их местоположение, скорость и курс. Именно при анализе дискретных систем необходимо контролировать очень большие, сложные и не всегда детерминированные пространства состояний. К сожалению, один человек не может охватить все эти детали одновременно. Эксперименты психологов, например, Миллера (Miller), показывают, что максимальное количество порций информации, которыми человек может оперировать одновременно, приблизительно равно семи (плюс-минус две) [14]. Вероятно, это ограничение пропускной способности информационного канала связано с объемом краткосрочной памяти у человека. Саймон также отмечает, что ограничивающим фактором является также скорость обработки: на восприятие новой порции информации мозгу требуется около 5 секунд [15]. Итак, мы столкнулись с серьезной дилеммой. Сложность систем программного обеспечения возрастает, а способности справиться с этой сложностью остаются ограниченными. Как же выйти из этого логического тупика? 1.5 Упорядочение хаоса Очевидно, всегда найдутся гении, обладающие экстраординарными способностями, которых можно сравнить с Фрэнком Ллойдом Райтом (Frank Llotd Wright) или Леонардо до Винчи (Leonardo da Vinci). Именно эти люди необходимы для реализации архитектуры системы: они способны разработать новаторские идиомы, механизмы и структуры, которые можно использовать при создании других систем. Однако, как заметил один исследователь: "Гении встречаются редко. Нельзя рассчитывать на то, что среди программистов их достаточно много" [2]. Несмотря на то что каждому из нас приходилось встречать такого человека, в промышлен-
Глава 1. Сложность 49 ном программировании не следует рассчитывать на божественное вдохновение. Таким образом, необходимо найти более организованный способ, чтобы справиться со сложностью. Роль декомпозиции "Способ управления сложными системами известен с античных времен — divide et impera (разделяй и властвуй)" [16]. При проектировании сложной системы программного обеспечения необходимо разделять ее на все меньшие и меньшие части, каждую из которых можно уточнять независимо друг от друга. В этом случае мы не выйдем за пределы реальных возможностей человеческого мозга: для понимания любого уровня системы нам необходимо оперировать немногими ее частях (а не всеми). Действительно, как заметил Парнас (Parnas), разумная декомпозиция позволяет справиться со сложностью проектирования программного обеспечения путем деления пространства состояний системы [17]. Алгоритмическая декомпозиция Большинство из нас формально учили принципы структурного проектирования методом "сверху вниз", и поэтому мы считаем декомпозицию обычным алгоритмическим разделением, в котором каждый модуль системы выполняет один из этапов общего процесса. На рис. 1.3 в качестве примера приведена структурная схема, показывающая связи между различными функциональными элементами. Эта структурная схема иллюстрирует часть программы, обновляющей содержание основного файла. Она была автоматически построена на основе диаграммы Обновить файл Прочитать главную Прочитать отформатирован- Прочитать правильный zrvs Сопоставить Расширить Проверить) 1 ^реформатировать Прочитать старую запись Проверить контрольную! Редакти Прочитать следующую Прочитать Проверка обновленную последова- Обновить Записать несогласованный Записать отформатированный X Вывести новую главную запись Добавить контрольную! Вывести новую главную Рис. 1.3. Алгоритмическая декомпозиция
50 Часть I. Концепции потока данных с помощью специальной экспертной системы, реализующей правила структурного проектирования [18]. Объектно-ориентированная декомпозиция Предположим, что существует альтернативный способ декомпозиции этой задачи. На рис. 1.4 продемонстрирована декомпозиция системы, в качестве критерия выбраны основные абстракции проблемных областей. Вместо разделения системы на этапы, например, Прочитать отформатированное обновление к Добавить контрольную сумму, мы должны определить такие объекты, как Основной файл и Контрольная сумма, которые извлекаются непосредственно из словаря предметной области. Обновить Прочитать отформатированное обновление Прочитать переформатированный Проверить правильность, добавить Рис. 1.4. Объектно-ориентированная декомпозиция Несмотря на то что обе схемы решают одну и ту же задачу, они делают это разными способами. Во второй декомпозиции мир представляет собой совокупность автономных агентов, взаимодействующих друг с другом, обеспечивая более сложное поведение системы. Действие Прочитать отформатированное обновление больше не является независимым алгоритмом; это действие представляет собой операцию, связанную с объектом Файл обновлений. В результате выполнения этой операции возникает другой объект — Обновление карты. Таким образом, каждый объект в схеме реализует свое собственное поведение, и каждый из них моделирует некоторый объект реального мира. С этой точки зрения объект является материальной сущностью, обладающей определенным поведением. Получая сообщения, объекты выполняют определенные операции. Так как описанная декомпозиция основана на объектах, а не на алгоритмах, она называется объектно- ориентированной (object-oriented decomposition).
Глава 1. Сложность 51 Сравнение алгоритмической и объектно-ориентированной композиции Какой способ декомпозиции сложной системы правильнее — по алгоритмам или по объектам? Это некорректный вопрос, поскольку важны оба аспекта. Разделение по алгоритмам основано на порядке происходящих событий, а разделение по объектам акцентирует внимание на агентах, которые либо вызывают действие, либо выполняют его. Однако невозможно сконструировать сложную систему одновременно двумя способами, тем более, что они полностью ортогональны3. Сначала следует провести декомпозицию системы либо по алгоритмам, либо по объектам, а затем проанализировать полученную структуру с другой точки зрения. Опыт показывает, что декомпозицию следует начинать с объектов, поскольку она облегчает упорядочение сложных систем, таких как программное обеспечение, компьютеры, растения, галактики и крупные общественные институты. Как будет показано в главе 2, объектно-ориентированная декомпозиция имеет множество чрезвычайно важных преимуществ над алгоритмической. Объектно- ориентированная декомпозиция уменьшает размер систем за счет повторного использования общих механизмов, обеспечивая значительную экономию выразительных средств. Объектно-ориентированные системы являются более гибкими и легче эволюционируют со временем, поскольку их проектирование основано на устойчивых промежуточных формах. Действительно, объектно-ориентированная декомпозиция значительно снижает риск, возникающий при создании сложной программной системы, так как она создается из меньших по размеру систем, в которых мы уже уверены. Более того, объектно-ориентированная декомпозиция помогает справиться со сложностью, характерной для систем программного обеспечения, помогая правильно разделить большое пространство состояний. Преимущества объектно-ориентированной декомпозиции продемонстрированы в разделе Приложения, где описаны прикладные задачи из разных предметных областей. Кроме того, результаты сравнения объектно-ориентированного и других подходов приведены во врезке "Категории анализа и методы проектирования". Роль абстракции Выше уже упоминались эксперименты Миллера, в которых было установлено, что обычный человек может одновременно воспринять лишь 7 ± 2 порции 3Лэнгдон (Langdon) предполагает, что эта ортогональность изучалась с античных времен. Он пишет: "Ваддингтон (C.H.Waddington) отметил, что вопрос двойственности точек зрения занимал еще древних греков. С одной стороны существовала пассивная теория, предложенная Демокритом, который утверждал, что мир состоит из атомов. С точки зрения Демокрита, в центре внимания должны находиться вещи. С другой стороны, классическим представителем сторонников активной теории был Гераклит, который делал акцент на понятии процесса" [34].
52 Часть I. Концепции Категории анализа и методы проектирования Полезно разграничить понятия метод и методология. Метод — это строгая процедура создания совокупности моделей, описывающая разные аспекты системы программного обеспечения в ходе проектирования с помощью четко определенной системы обозначений. Методология — это совокупность методов, применяемых на протяжении жизненного цикла программного обеспечения, объединенных общими теоретическими принципами и практическими приемами. Методы важны по нескольким причинам. Во-первых, они дисциплинируют процесс создания сложных программных систем. Во-вторых, методы позволяют определить средства общения между членами группы разработчиков. В-третьих, с помощью методов можно определить календарный план, позволяющий измерить прогресс, достигнутый в ходе выполнения проекта, и оценить риск. Методы совершенствовались в ответ на растущую сложность систем программного обеспечения. На заре компьютерной эры больших программ просто не существовало, поскольку возможности электронно-вычислительных машин были очень ограничены. Основные ограничения касались аппаратного обеспечения: компьютеры имели маленький объем оперативной памяти, программы медленно считывали информацию со вспомогательных запоминающих устройств (магнитных лент), а тактовый цикл процессоров измерялся сотнями микросекунд. В 1960-70-е годы эффективность компьютеров резко возросла, цены на аппаратное обеспечение рухнули вниз, а мощность вычислительной техники, наоборот, увеличилась. В результате возникли благоприятные условия для автоматизации все более и более сложных приложений. На авансцену вышли языки программирования высокого уровня. Эти языки повысили производительность труда как отдельных программистов, так и групп разработчиков в целом, что по иронии судьбы в свою очередь стимулировало повышение уровня сложности систем программного обеспечения. В 1960-70-е годы было разработано много методов, помогающих справиться с растущей сложностью систем. Наибольшее распространение получил структурный подход по принципу сверху-вниз, известный под названием композиционное проектирование (composite design). На это непосредственно влияли свойства традиционных языков высокого уровня, таких как FORTRAN или COBOL. В этих языках основной базовой единицей декомпозиции является подпрограмма, и программа в целом имеет форму дерева, в котором одни подпрограммы в процессе работы вызывают другие подпрограммы. Это полностью соответствует структурному проектированию сверху-вниз, в котором разбиение большой задачи на более мелкие осуществляется с помощью алгоритмической декомпозиции. За прошедшее время возможности компьютеров значительно расширились. Несмотря на то что значение структурного подхода осталось прежним, как выяснил Стейн (Stein), "если объем программы превышает приблизительно 100000 строк, структурный подход перестает работать" [19]. Для преодоления очевидных недостатков структурного проектирования были предложены десятки методов. Наиболее интересные и удачные методы проектирования были разработаны Петер- сом (Peters) [20], Яу (Yau) и Цаи (Tsai) [21], а также фирмой Teledyne Brown
Глава 1. Сложность 53 Engineering [22]. Нет ничего удивительного в том, что большинство этих методов представляют собой вариации на одни и те же темы. Соммервилль (Sommerville) предложил разделить их на три основные группы [23]: • метод структурного проектирования сверху вниз; • информационное программирование; • объектно-ориентированное проектирование. Примеры структурного проектирования по принципу сверху-вниз приведены в работах Иордона (Yourdon) и Константина (Konstantine) [24], Майерса (Myers) [25] и Пейдж-Джоунса (Page-Jones) [26]. Основы этого метода изложены в работах Вирта (Wirth) [27, 28], Даля (Dahl), Дийкстры (Dijkstra) и Хоара (Ноаге) [29]; ценный вариант структурного подхода можно найти в работе Милса (Mills), Лингера (Linger) и Хевнера (Hevner) [30]. В каждом из этих вариантов применяется алгоритмическая декомпозиция. Большинство программного обеспечения было спроектировано с помощью одного из этих методов. Тем не менее структурный подход не решает проблем, связанных с абстрагированием данных и сокрытием информации, а также не обеспечивает средств для организации взаимной совместимости объектов (concurrency). Структурный метод не допускает масштабирования для создания очень сложных систем и, как правило, плохо сочетается с объектными и объектно- ориентированными языками программирования. Информационное программирование (data-driven design) яснее всего описано в ранней работе Джексона (Jackson) [31, 32], а также Орра [33]. В этом методе система рассматривается как отображение входных данных в выходные. Это обстоятельство непосредственно влияет на структуру программного обеспечения. Как и структурное проектирование, информационное программирование успешно применялось при решении многих сложных задач, в частности, для реализации систем управления информацией, в которых существуют прямые связи между входными и выходными данными системы и не возникают проблемы, связанные с быстродействием. Основной принцип объектно-ориентированного анализа заключается в том, что модель системы программного обеспечения рассматривается как совокупность взаимодействующих объектов, а каждый объект — как экземпляр определенного класса, входящего в определенную иерархию. Объектно-ориентированный анализ и проектирование отражает топологию языков программирования высокого уровня, таких как Smalltalk, Object Pascal, C++, Common Lisp Object System (CLOS), Ada, Eiffel, Python, Visual C# и Java. информации. Это число, по-видимому, не зависит от содержания информации. Как указывает Миллер: "Размер области мозга, управляющих абсолютными оценками (absolute judgment), и объем кратковременной памяти (immediate memory) накладывают жесткие ограничения на количество информации, которое мы можем воспринять, обработать и запомнить. Организуя поступление внешних раздражителей одновременно по нескольким различным каналам в виде последовательно-
54 Часть I. Концепции сти отдельных порций, мы можем прорвать... этот информационный затор" [35]. В современной терминологии этот процесс называется фрагментацией (chunking), или абстрагированием (abstraction). Вулф (Wulf) так описывает этот процесс: "Мы (люди) разработали чрезвычайно мощные способы преодоления сложности. Мы абстрагируемся от нее. Будучи не в состоянии полностью освоить сложный объект, мы просто игнорируем несущественные детали, заменяя его обобщенной, идеализированной моделью" [36]. Например, изучая процесс фотосинтеза в растениях, мы можем сконцентрировать внимание на химических реакциях в определенных клетках листа и проигнорировать все остальные части, например, корни и стебли. Несмотря на то что мы по-прежнему не в состоянии одновременно усвоить большое количество информации, благодаря абстракции мы используем порции информации с гораздо более существенным семантическим смыслом. Это особенно верно, если мы принимаем объектно-ориентированную точку зрения на мир, поскольку объекты как абстракции реальных сущностей представляют собой особенно компактные и связные блоки информации. В главе 2 понятие абстракции изучается более подробно. Роль иерархии Другим способом, позволяющим увеличить семантическое содержание порции информации, является выявление иерархий классов и объектов внутри системы. Объектная структура играет важную роль, поскольку она иллюстрирует схемы взаимодействия разных объектов друг с другом, которые называются механизмами (mechanisms). Структура классов не менее важна, так как она выделяет общую структуру и поведение внутри системы. Таким образом, вместо изучения фотосинтеза каждой клетки отдельного листа растения, достаточно изучить одну такую клетку, поскольку ожидается, что все остальные клетки функционируют аналогично. Несмотря на то что каждый объект определенного типа рассматривается как отдельная сущность, можно предположить, что его поведение не отличается от поведения других подобных объектов. Объединяя объекты в группы взаимосвязанных абстракций (например, отличая клетки растений от клеток животных), мы четко разделяем общие и уникальные свойства разных объектов, что в дальнейшем помогает нам справиться со свойственной им сложностью [37]. Идентифицировать иерархии в сложной программной системе часто нелегко, поскольку для этого необходимо выяснить шаблоны поведения многих объектов, функционирование каждого из которых может быть чрезвычайно сложным. Однако после выявления иерархий структура сложной системы и, в свою очередь, наши представления о ней значительно проясняются. Природа иерархий классов и объектов подробно рассматривается в главе 3, а приемы распознавания этих шаблонов описаны в главе 4.
Глава 1. Сложность 55 1.6 О проектировании сложных систем На практике любая техническая дисциплина — строительство, механика, химия, электротехника или программирование — сочетает элементы искусства и науки. По этому поводу очень красноречиво высказался Петроски (Petroski): "Для проектирования новой структуры необходим полет фантазии, а также синтез опыта и знаний, которые художник воплощает на холсте или бумаге. Сначала инженер должен стать художником и сформулировать свой замысел, а затем превратиться в ученого и тщательно проанализировать проект, применяя строгий научный метод" [38]. Эту точку зрения разделял Дейкстра (Dijkstra): "Программирование — это крупномасштабное упражнение по прикладному абстрагированию, требующее как математических способностей, так и знаний компетентного инженера" [39]. Инженерное дело как наука и искусство Когда разрабатывается совершенно новая система, роль инженера как художника приобретает огромную важность. Особенно ярко этот эффект проявляется при проектировании систем с обратной связью, а также систем управления и контроля, когда приходится разрабатывать совершенно нестандартное программное обеспечение, которое реализуется с помощью специально сконструированных процессоров. В других случаях, например, при создании интегрированных сред разработки, инструментов для исследований в области искусственного интеллекта или даже систем управления информацией, проектировщик имеет дело с точно определенными техническими заданиями, которые могут требовать выхода на новый уровень технологии. Например, проектировщикам могут предложить разработать систему, обладающую намного большим быстродействием и производительностью, или радикально расширенными функциональными возможностями. Во всех этих случаях в качестве основы, на которой строятся новые сложные системы, инженеры стараются использовать уже известные абстракции и механизмы ("устойчивые промежуточные формы" по Саймону). При наличии большой библиотеки повторно используемых компонентов, программист должен по-новому объединить эти части, чтобы выполнить все явные и неявные требования, предъявляемые к системе, точно так же, как художник или музыкант должен расширять возможности своего инструмента. Смысл проектирования В любой инженерной дисциплине под проектированием обычно понимается некий формальный метод, с помощью которого изобретается решение определенной проблемы, чем обеспечивается переход от технического задания к его
56 Часть I. Концепции реализации. В контексте проектирования программных систем Мостоу (Mostow) определил цель проектирования как конструирование системы, которая • "удовлетворяет заданной (возможно, неформальной) функциональной спецификации; • согласована с ограничениями среды; • удовлетворяет явным и неявным требованиям к производительности и потреблению ресурсов; • удовлетворяет явным и неявным критериям, предъявляемым к форме продукции; • удовлетворяет требованиям, предъявляемым к самому процессу разработки, таким, например, как ее продолжительность и стоимость, а также использование дополнительных инструментальных средств" [40]. Как предположил Страуструп: "Цель проектирования — создать ясную и относительно простую внутреннюю структуру, иногда называемую архитектурой... Проект — это окончательный продукт процесса проектирования" [41]. Проектирование подразумевает согласование противоречивых требований. Результатом проектирования являются модели, позволяющие нам понять структуру будущей системы, достичь компромисса между противоречивыми требованиями и наметить план их реализации. Важность моделирования Моделирование широко распространено во всех инженерных дисциплинах, в основном из-за того, что оно основано на принципах декомпозиции, абстракции и иерархии [42]. Каждая модель, включенная в проект, описывает конкретный аспект рассматриваемой системы. По мере возможности инженеры пытаются строить новые модели на основе старых, в правильной работе которых они уверены. Модели позволяют выявлять отказы системы в контролируемых условиях. Каждая модель оценивается как в обычных, так и в необычных ситуациях, а затем уточняется в случае нежелательного поведения. Для того чтобы выразить все особенности поведения сложной системы, необходимо использовать несколько моделей. Например, проектируя персональный компьютер, инженер-электронщик должен рассматривать систему как на уровне функциональных компонентов, так и на уровне микросхем. Анализ функциональных компонентов позволяет создать логическую схему проекта, позволяющую разобраться в тонкостях их взаимодействия. На уровне микросхем инженер анализирует проблемы, связанные с размещением аппаратных средств и ограничениями их размера, допустимой мощности и состава. На этом уровне инженер должен независимо оценивать такие факторы, как рассеяние тепла и сложность произ-
Глава 1. Сложность 57 водства. Проектировщик микросхем также должен рассматривать как динамические, так и статические особенности системы. Для этого инженер-электронщик использует диаграммы, иллюстрирующие статические связи между различными микросхемами, и временные диаграммы, отражающие изменение поведения этих элементов во времени. Затем для оценки корректности статической и динамической моделей инженер может применить осциллограф или цифровой анализатор. Элементы методологии проектирования программного обеспечения Очевидно, что не существует волшебной нити [43], которая безошибочно провела бы инженера-программиста по пути от технического задания к реализации сложной программной системы. Проектирование сложной программной системы отнюдь не сводится к совокупности готовых рецептов. Скорее, как указывалось ранее, проектирование представляет собой поступательный и итерационный процесс. Тем не менее, надежные методы проектирования вносят в процесс разработки программного обеспечения необходимую дисциплину. Разработчики программного обеспечения создали десятки различных методов, которые можно грубо разделить на три категории (см. врезку "Категории анализа и методы проектирования"). Несмотря на различия, все эти методы имеют нечто общее. В частности, их объединяют следующие свойства: • условные обозначения — язык для описания каждой модели; • процесс — действия, позволяющие правильно конструировать модели; • инструменты — средства, упрощающие процесс создания моделей и реализующие правила, позволяющие выявлять ошибки в процессе разработки. Надежный метод проектирования основывается на прочном теоретическом фундаменте и предоставляет программисту известную степень свободы самовыражения. Объектно-ориентированные модели Существует ли "наилучший" метод проектирования? На этот вопрос нет однозначного ответа. По сути дела это завуалированное повторение вопроса: "Какой метод декомпозиции сложной системы является наилучшим?" Повторим, что в ходе проектирования очень полезно создавать модели, заостряющие внимание на сущностях, характерных для исследуемой предметной области, и образующие то, что мы назвали объектно-ориентированной декомпозицией. Объектно-ориентированный анализ и проектирование приводят к объектно- ориентированной декомпозиции. Применяя объектно-ориентированное проекта-
58 Часть I. Концепции рование, можно создавать гибкие программы, написанные экономными средствами. При разумном разделении пространства состояний можно добиться большей уверенности в правильности разработанного программного обеспечения. В итоге уменьшается риск, характерный для разработки сложных программных систем. В этой главе приведены доводы в пользу применения объектно-ориентированного анализа и проектирования для преодоления сложности, связанной с разработкой систем программного обеспечения. Кроме того, в ней указан ряд фундаментальных преимуществ, достигаемых в результате применения такого подхода. Прежде чем перейти к описанию системы обозначений и процесса объектно- ориентированного проектирования, необходимо изучить принципы, на которых этот процесс основан: абстрагирование, инкапсуляцию, модульность, иерархию, контроль типов, параллелизм и персистентность. Резюме • Программному обеспечению присуща сложность, часто превосходящая возможности человеческого разума. • Задача разработчиков программных систем — создать иллюзию простоты. • Сложность часто выражается в виде иерархии; необходимо моделировать обе иерархии сложной системы: и "общее/частное", и "целое/часть". • Сложные системы обычно создаются на основе устойчивых промежуточных форм. • Познавательные способности человека ограничены и могут быть расширены с помощью декомпозиции, абстрагирования и идентификации иерархий. • Сложные системы можно исследовать, фокусируя внимание либо на объектах, либо на процессах; имеются веские основания для использования объектно-ориентированной декомпозиции, при которой мир рассматривается как осмысленная совокупность объектов, которые в процессе взаимодействия друг с другом определяют сложное поведение системы. • Объектно-ориентированный анализ и проектирование представляет собой метод, приводящий к объектно-ориентированной декомпозиции; объектно-ориентированный подход использует определенную систему условных обозначений и процедур для построения сложных систем программного обеспечения, предлагая богатый выбор логических и физических моделей, с помощью которых можно анализировать разные аспекты изучаемой системы.
ГЛАВА 2 ОБЪЕКТНАЯ МОДЕЛЬ Объектно-ориентированная технология покоится на солидной технической основе, элементы которой образуют так называемую объектную модель проектирования (object model of development), или просто объектную модель. К основным принципам этой модели относятся абстракция, инкапсуляция, модульность, иерархия, контроль типов, параллелизм и персистентность. Сами по себе эти принципы не новы, но в рамках объектной модели они существуют в синергическом единстве. Не подлежит никакому сомнению, что объектно-ориентированный анализ и проектирование в корне отличаются от традиционных методов структурного проектирования: они требуют совершенно иного подхода к декомпозиции и порождают архитектуру программного обеспечения, намного превосходящую возможности структурного программирования. 2.1 Эволюция объектной модели Объектно-ориентированная технология не выросла спонтанно на развалинах бесчисленных проектов, потерпевших крах из-за устаревшей технологии проектирования, и не является радикальным пересмотром предшествующих подходов. На самом деле она вобрала в себя наилучшие идеи более ранних методологий. В главе описывается эволюция средств проектирования. Это поможет читателям понять основы и причины появления объектно-ориентированной технологии. Оглядываясь на относительно недолгую, но яркую историю программирования, необходимо отметить две главные тенденции. 1. Перенос акцентов с детализированного на крупномасштабное программирование.
60 Часть I. Концепции 2. Эволюция языков программирования высокого уровня. Большинство современных промышленных систем программного обеспечения намного масштабнее и сложнее своих предшественников, созданных всего несколько лет тому назад. Возрастание сложности стимулировало многочисленные прикладные исследования по методологии проектирования программного обеспечения, особенно в области декомпозиции, абстракции и иерархии. Это способствовало также появлению более выразительных языков программирования. Поколения языков программирования Вегнер (Wegner) [1] выделил четыре поколения наиболее популярных языков программирования высокого уровня, положив в основу классификации новаторские языковые конструкции, впервые появившиеся в этих языках. (Разумеется, это далеко не исчерпывающий список всех языков программирования.) • Языки программирования первого поколения (1954-1958) FORTRAN I Математические формулы ALGOL-58 Математические формулы Flowmatic Математические формулы IPL V Математические формулы • Языки программирования второго поколения (1959-1961) FORTRAN II Подпрограммы, раздельная компиляция ALGOL-60 Блочная структура, типы данных COBOL Описание данных, работа с файлами Lisp Обработка списков, указатели, сборка мусора • Языки программирования первого поколения (1962-1970) PL/I FORTRAN+ALGOL+COBOL ALGOL-68 Ближайший наследник ALGOL-60 Pascal Простой наследник ALGOL-60 Simula Классы, абстракция данных • Разрыв преемственности (1970-1980) В этот период было изобретено много языков, но лишь немногие из них выдержали испытание временем. Среди них заслуживают упоминания следующие языки. С Эффективен; характеризуется малым размером исполняемых модулей FORTRAN 77 Прошел стандартизацию ANSI
Глава 2. Объектная модель 61 Продолжим классификацию Вегнера. • Бум объектно-ориентированного программирования (1980-1990, проверку временем прошли лишь несколько языков) Smalltalk 90 Чисто объектно-ориентированный язык C++ Происходит от языков С и Simula Ada83 Строгий контроль типов; сильное влияние языка Pascal Eiffel Происходит от языков Ada и Simula • Появление интегрированных сред (1990 и до настоящего времени) Visual Basic Облегченное проектирование графического пользовательского интерфейса (graphical user interface — GUI) для приложений в операционной среде Windows Java Наследник языка Oak; разрабатывался для мобильных устройств Python Объектно-ориентированный язык сценариев J2EE Интегрированная среда на базе языка Java для промышленного применения .NET Интегрированная объектно-ориентированная среда, разработанная компанией Microsoft Visual C# Конкурент языка Java для среды Microsoft .NET Visual Basic .NET Вариант языка Visual Basic для среды Microsoft .NET В каждом следующем поколении языков программирования механизмы абстракции изменялись. Языки первого поколения использовались, в основном, для научных и технических вычислений, и словарь этой предметной области был математическим. Такие языки, как FORTRAN I, позволяли программистам записывать математические формулы, освобождая их от сложностей, связанных с ассемблером или машинным кодом. Таким образом, первое поколение языков высокого уровня было шагом в направлении предметной области и отступало от технических деталей компьютеров. Языки программирования второго поколения перенесли акцент на алгоритмические абстракции. В то время мощность компьютеров все больше увеличивалась, а область их применения расширялась, особенно в экономической сфере. Основная задача заключалась в инструктировании машины: например, сначала прочитать анкеты сотрудников, затем упорядочить и после этого распечатать результаты на принтере. Языки программирования этого поколения продолжали отдаляться от компьютеров и приближаться к предметной области. В конце 1960-х годов, особенно после изобретения транзисторов и технологии интегральных схем, стоимость аппаратного обеспечения резко упала, а производительность компьютеров продолжала расти почти экспоненциально. Это позволяло
62 Часть I. Концепции решать еще более сложные задачи, но вынуждало программистов манипулировать более разнообразными видами данных. В результате возникли языки третьего поколения, такие как ALGOL-68 и Pascal, поддерживающие абстракцию данных. Теперь разработчики получили возможность описывать свои собственные виды данных (т.е. создавать пользовательские типы) и реализовывать проектные решения на языке программирования. Это поколение языков программирования еще больше удалилось от машинной архитектуры и приблизилось к предметной области. 1970-е годы ознаменовались бурным всплеском активности в области разработки языков программирования. В результате было создано несколько тысяч разных языков программирования и их вариантов. Со временем необходимость разрабатывать все более крупные программы сделала очевидной неадекватность старых языков. Многие механизмы новых языков программирования разрабатывались именно для того, чтобы преодолеть эти ограничения. Лишь немногие из этих языков прошли проверку временем (вы когда-нибудь видели современный учебник по языкам Fred, Chaos или Tranquil?). Однако многие из концепций, воплощенных в этих языках, были внедрены в новых версиях более ранних языков. Наибольший интерес представляет класс языков, называемых объектными (object-based) и объектно-ориентированными (object-oriented). Эти языки лучше всего поддерживают объектно-ориентированную декомпозицию программного обеспечения. Большинство объектно-новых языков этой категории (и объектно-ориентированных вариантов старых языков программирования) появились в 1980-х и начале 1990-х годов. После 1990-го года появилось немного объектно-ориентированных языков программирования, поддерживаемых поставщиками коммерческого программного обеспечения (например, языки Java и C++). Появление интегрированных сред (например, J2EE и .NET), предоставляющих в распоряжение программистов огромное количество компонентов и сервисов, которые упростили решение типичных и рутинных задач, резко увеличило производительность их труда и продемонстрировало преимущества повторного использования кода. Топология языков первого поколения и ранних языков второго поколения Рассмотрим структуру каждого поколения языков программирования. На рис. 2.1 продемонстрирована топология, характерная для большинства языков первого поколения и ранних языков второго поколения. Под топологией (topology) подразумеваются основные конструктивные блоки языка программирования и способы их взаимосвязи. Как показывает анализ рис. 2.1, в таких языках, как FORTRAN и COBOL, основным конструктивным блоком является подпрограмма (или параграф, если использовать терминологию языка COBOL).
Глава 2. Объектная модель 63 Данные^"^ I D Подпрограммы Рис. 2.1. Топология языков программирования первого поколения и первых языков второго поколения Программы, написанные на этих языках, имеют относительно простую структуру, состоящую только из глобальных данных и подпрограмм. Стрелки на рис. 2.1 иллюстрируют зависимость подпрограмм от данных. В процессе проектирования обычно удается провести логическое разделение между разнотипными данными, но ранние языки программирования очень слабо поддерживают такое проектное решение. Ошибка, допущенная в одной части программы, может оказать разрушительное влияние на остальную часть системы, так как глобальные структуры данных открыты для всех подпрограмм. При внесении изменений в крупную систему эти языки не гарантируют поддержку целостности данных. Даже после короткого периода эксплуатации программа, написанная на ранних языках, содержит большое количество перекрестных связей между подпрограммами, неявно подразумеваемых данных и запутанных потоков управления. Все это снижает надежность системы и уменьшает ясность проектного решения. Топология языков программирования позднего второго и раннего третьего поколения К середине 1960-х годов программисты осознали роль подпрограмм как важного промежуточного звена, обеспечивающего связь между задачей и компьютером [2]. "Первая программная абстракция, которую теперь называют процедурной, является непосредственным следствием прагматического взгляда на программное обеспечение... Подпрограммы появились еще до 1950 года, но в то время они не воспринимались как абстракции... Их сначала рассматривали скорее как средства, позволяющие экономить силы... Однако очень скоро подпрограммы стали восприниматься как абстрактные функции" [3]. Понимание того, что подпрограммы являются механизмом абстрагирования, привело к трем важным последствиям. Во-первых, были разработаны языки, под-
64 Часть I. Концепции держивавшие разнообразные механизмы передачи параметров. Во-вторых, были заложены основы структурного программирования, проявившиеся в поддержке вложенных подпрограмм и разработке теории управляющих конструкций и областей видимости. В-третьих, были изобретены методы структурного проектирования, позволившие разработчикам создавать крупные системы, используя подпрограммы в качестве конструктивных блоков. Нет ничего удивительно в том, что, как показано на рис. 2.2, топология языков программирования позднего второго и раннего третьего поколений оказалась вариантом топологии их предшественников. Эта топология устранила некоторые недостатки более ранних языков, в частности, усилила контроль над алгоритмическими абстракциями, но по-прежнему не позволяла создавать крупномасштабные системы. Подпрограммы Рис. 2.2. Топология языков программирования позднего второго и раннего третьего поколений Топология поздних языков третьего поколения В языке FORTRAN II и других поздних языках программирования третьего поколения для создания крупномасштабных систем был предложен новый важный механизм структуризации. Укрупнение программных проектов привело к разрастанию коллективов программистов и породило необходимость независимо разрабатывать отдельные части одной и той же программы. Для решения этой проблемы была предложена концепция отдельно компилируемого модуля, который на первых порах интерпретировался как произвольный контейнер, содержащий набор данных и подпрограмм (см. рис. 2.3). На практике такие модули не рассматривались как механизмы абстрагирования. Их использовали просто как наборы подпрограмм, которые чаще всего модифицировались одновременно. Большинство языков этого поколения поддерживало определенный вид модульной структуры, но практически не регламентировало семантическое согласование между интерфейсами модулей. Программист, сочиняющий подпрограмму
Глава 2. Объектная модель 65 Модули Рис. 2.3. Топология языков программирования позднего третьего поколения для одного из модулей, мог, например, предполагать, что она будет вызываться с тремя параметрами: действительным числом, массивом, состоящим из десяти элементов, и целым числом, представляющим собой булеву величину. В то же время в другом модуле эта подпрограмма могла по ошибке вызываться с фактическими параметрами, противоречащими этому предположению, например, с целым числом, массивом, состоящим из пяти элементов, и отрицательного числа. Аналогично, автор одного из модулей мог предполагать, что определенный блок общих данных может изменяться только внутри данного модуля, а программист, создающий другой модуль, мог нарушить это предположение, непосредственно обращаясь к этим данным. К сожалению, поскольку большинство языков очень слабо поддерживало абстракцию данных и строгий контроль типов, такие ошибки можно было выявить только во время выполнения программы. Топология объектных и объектно-ориентированных языков Абстракция данных играет важную роль в борьбе со сложностью. "Природа абстракций, обеспечиваемых процедурами, хорошо подходит для описания абстрактных операций, но не подходит для описания абстрактных объектов. Это серьезный недостаток, поскольку во многих приложениях основную сложность составляет необходимость манипулирования именно объектами" [4]. Осознание этого факта привело к двум важным последствиям. Во-первых, возникли методы информационного проектирования (data-driven design), систематизировавшие способы абстракции в алгоритмических языках. Во-вторых, стала разрабатываться теория типов данных, в результате воплотившаяся в таких языках, как Pascal.
66 Часть I. Концепции Естественным следствием этих идей стало появление языков Simula, Smalltalk, Object Pascal, C++, Ada, Eiffel и Java. По причинам, которые будут рассмотрены далее, эти языки называются объектными или объектно-ориентированными. Топология этих языков применительно к малым и средним по размеру приложениям представлена на рис. 2.4. Рис. 2.4. Топология малых и средних языков программирования объектных и объектно-ориентированных языков программирования Основным конструктивным элементом в этих языках является модуль (module), представляющий собой логически связанную совокупность классов и объектов, а не подпрограмм, как в более ранних языках. Иначе говоря, "если процедуры и функции — это глаголы, а данные — это существительные, то в основе процедурно-ориентированных программ лежат глаголы, а в основе объектно-ориентированных — существительные" [6]. По этой причине структура малых и средних по размеру объектно-ориентированных приложений изображается в виде графа, а не дерева, характерного для алгоритмических языков. Кроме того, в этих языках почти не используются или вообще исключены глобальные данные. Данные и операции объединяются таким образом, что основными логическими конструктивными элементами объектно-ориентированных систем теперь являются классы и объекты, а не алгоритмы. В настоящее время наблюдается большой прогресс в программировании больших и даже огромных систем. Оказалось, что для очень сложных систем классы, объекты и модули являются необходимыми, но все же не достаточными средствами абстракции. К счастью, объектная модель допускает масштабирование. В крупных системах существуют кластеры абстракций, образующие слои. На каждом уровне абстракции можно выделить совокупности объектов, взаимодействующих друг с другом для реализации поведения, относящегося к более высокому уров-
Глава 2. Объектная модель 67 ню абстракции. Если поинтересоваться устройством таких кластеров и заглянуть внутрь, можно обнаружить другой набор взаимодействующих абстракций. Именно эта организация сложности описана в главе 1. Соответствующая топология изображена на рис. 2.5. | DI , Л 1 °| 51 V ~^М' 1 Dl г Рис. 2.5. Топология крупных приложений, созданных с помощью объектных и объектно-ориентированных языков программирования 2.2 Основные положения объектной модели Методы структурного проектирования разрабатывались для того, чтобы помочь проектировщикам, создающим сложные системы из алгоритмов. Аналогично, методы объектно-ориентированного проектирования создавались, чтобы дать разработчикам мощные выразительные средства языков объектного и объектно- ориентированного программирования, в которых основными конструктивными элементами являются классы и объекты. На развитие объектной модели влияло большое количество факторов, а не только объектно-ориентированное программирование. Как показано во врезке
68 Часть I. Концепции "Основы объектной модели", объектный подход признан объединяющей концепцией компьютерной науки, которую можно применять не только в языках программирования, но также при разработке пользовательских интерфейсов, баз данных и даже компьютерной архитектуры. Причина такой универсальности заключается в том, что объектная ориентация позволяет справиться со сложностью, характерной для самых разных систем. Таким образом, объектно-ориентированный анализ и проектирование носят эволюционный, а не революционный характер. Они не отбрасывают достижений прежних методологий, а берут из них лучшее. К сожалению, большинство программистов плохо владеет методами объектно-ориентированного анализа и проектирования. Разумеется, многие инженеры успешно применяют методы структурного проектирования. Однако существуют пределы сложности, с которой можно справиться с помощью алгоритмической декомпозиции. Более сложные задачи можно решить только на основе объектно-ориентированной декомпозиции. Кроме того, пытаясь использовать такие языки, как C++ или Ada исключительно в качестве алгоритмических, программисты не только упускают большие возможности, но и получают менее эффективные программы по сравнению с программами, написанными на языках С или Pascal. Если дать мощную электродрель плотнику, который не знает о существовании электричества, то скорее всего он станет использовать ее в качестве молотка. В результате он согнет несколько гвоздей и разобьет пальцы, потому что электродрель — плохой молоток. К сожалению, поскольку объектная модель является наследником нескольких концепций, ее терминология довольно запутанна. Например, для обозначения одного и того же понятия в языке Smalltalk используется термин метод (method), в языке C++ — виртуальная функция-член (virtual function-member), а в языке CLOS — обобщенная функция (generic function). Программисты, работающие на языке Object Pascal, C# и Java говорят о приведении типов (type coersion, or cast), а на языке Ada — о преобразовании типов (type conversion). Для того чтобы прояснить ситуацию, необходимо уточнить, что считается объектно-ориентированным, а что — нет. Термин объектно-ориентированный используется так же легкомысленно и так же почтительно, как "материнство", "яблочный пирог" и "структурное программирование" [6]. Разумеется, можно согласиться с тем, что понятие объекта является центральным понятием в любой объектно-ориентированной теории. В предыдущей главе объектом называлась материальная сущность с четко определенным поведением. Стефик (Stefik) и Боброу (Bobrow) дали следующее определение объектов: "сущности, обладающие свойствами процедур и данных, поскольку они производят вычисления и сохраняют свое локальное состояние" [7]. Определение объекта как сущности в некоторой мере является спорным, но основная идея заключается в сочетании алгоритмических идей и абстракции данных. Джонс (Jones) уточнил это понятие следующим образом: "В объектной модели акцент пе-
Глава 2. Объектная модель 69 реносится на четкое описание компонентов физической или абстрактной системы, моделируемой с помощью программы... Объекты имеют некую "целостность", которая не должна — а, в действительности, не может — быть нарушена. Объект может только изменять состояние, выполнять действия, допускать манипуляции и взаимодействовать с другими объектами приемлемым способом. Иначе говоря, существуют инвариантные свойства, характеризующие объект и его поведение. Например, к числу инвариантных свойств лифта относится его способность передвигаться по шахте вверх и вниз... Любая модель лифта должна учитывать эти инварианты, поскольку они являются его неотъемлемым атрибутом" [26]. Объектно-ориентированное программирование Что же такое объектно-ориентированное программирование (object-oriented programming — OOP)? Наше определение выглядит следующим образом. Объектно-ориентированное программирование — это метод программирования, основанный на представлении программы в виде совокупности взаимодействующих объектов, каждый из которых является экземпляром определенного класса, а классы являются членами определенной иерархии наследования. Необходимо обратить внимание на следующие важные части этого определения: 1) объектно-ориентированное программирование использует в качестве основных логических конструктивных элементов объекты, а не алгоритмы (иерархия "целое/часть" определена в главе 1); 2) каждый объект является экземпляром (instance) определенного класса (class); 3) классы образуют иерархии (см. понятие об иерархии "общее/частное" в главе 1). Программа считается объектно-ориентированной, только если выполнены все три указанных требования. В частности, программирование, не использующее наследование, называется не объектно- ориентированным, а программированием с помощью абстрактных типов данных (programming with abstract data types). В соответствии с этим определением одни языки программирования являются объектно-ориентированными, а другие — нет. Страуструп (Stroustrup) полагает: "Если термин "объектно-ориентированный язык" вообще имеет смысл, то он должен относиться к языку, хорошо поддерживающему объектно-ориентированный стиль программирования... Поддержка такого стиля программирования считается хорошей, если средства языка обеспечивают удобное использование этого стиля. Язык не поддерживает объектно-ориентированное программирование, если написание программ в этом стиле требует особых усилий или опыта; в этом случае говорят, что язык просто позволяет программистам использовать объектно-ориентированный подход" [27]. С теоретической точки зрения существует возможность имитации объектно-ориентированного программирования с помощью
70 Часть I. Концепции Основы объектной модели Йонезава (Yonezawa) и Токоро (Tokoro) указывают: "Термин "объект" почти одновременно возник в начале 70-х годов в разных независимых друг от друга областях компьютерных наук. Этот термин означал разные, хотя и взаимосвязанные понятия, изобретенные для того, чтобы уменьшить сложность систем программного обеспечения. Объекты использовались для представления компонентов системы, допускающей разложение на модули или фрагменты представляемых знании" [8]. Леви (Levy) отметил, что на эволюцию объектно-ориентированных концепций оказали влияние следующие события. • Усовершенствование архитектуры компьютеров, включая повышение мощности систем и аппаратной поддержки операционных систем. • Развитие языков программирования, таких как Simula, Smalltalk, CLU и Ada. • Достижения методологии программирования, включая принципы модульности и сокрытия данных [10]. К этому еще следует добавить три момента, оказавшие влияние на становление объектного подхода: • развитие теории баз данных; • исследования в области искусственного интеллекта; • достижения философии и теории познания. Концепция объекта возникла более 20 лет назад при конструировании компьютеров с дескрипторной (descriptor-based) и мандатной (capability-baseds) архитектурой [10]. Эти разновидности архитектуры отличались от классической архитектуры фон Неймана и пытались преодолеть разрыв между высоким уровнем абстракций, присущих для языков программирования, и низким уровнем абстракций, характерных для компьютеров [11]. По мнению сторонников этих подходов преимущества новых разновидностей архитектуры позволяли лучше выявлять ошибки, повышали эффективность выполнения программ, сокращали количество инструкций, упрощали компиляцию и снижали объем требуемой памяти. Компьютеры тоже могут иметь объектно-ориентированную архитектуру. С объектно-ориентированной архитектурой тесно связаны объектно-ориентированные операционные системы. Работая над мультипрограммной системой THE, Дейкстра (Dijkstra) впервые ввел понятие строительных систем (building systems) как машин с многоуровневыми состояниями [12]. К первым объектно-ориентированным операционным системам относятся Plessey/System 250 (для мультипроцессора Plessey 250), Hydra (для компьютера C.mmp, разработанного компанией CMU), CALTSS (для компьютера CDC 6400), САР (для компьютера Cambridge CAP), UCLA Secure UNIX (для компьютеров PDP 11/45 и 11/70), StarOS (для компьютера Cm* компании CMU), Medusa (также для компьютера Cm*) и iMAX (для компьютера Intel 432) [13]. Вероятно, наиболее значительный вклад в объектную модель внесен объектными и объектно-ориентированными языками программирования. Впервые понятия
Глава 2. Объектная модель 71 классов и объектов появились в языке Simula 67. Система Flex и последовавшие за ней диалекты Smalltalk-72, -74, -76 и, наконец, последняя версия Smalltalk-80, приняв парадигму языка Simula, довели ее до логического завершения, реализовав все возможные сущности в виде экземпляров классов. В 1970-х годах был разработан ряд языков — Alphard, CLU, Euclid, Gypsy, Mesa и Modula, — поддерживающих идею абстракции данных. Последующие исследования привели к внедрению идей языков Simula и Smalltalk в традиционные языки высокого уровня. Объединение объектно-ориентированного подхода с концепциями языка С привело к появлению языков C++ и Objective С. Впоследствии для предотвращения наиболее распространенных ошибок, характерных для программ на языке C++, был разработан язык Java. Внедрение концепций объектно-ориентированного программирования в язык Pascal породило языки Object Pascal, Eiffel и Ada. Кроме того, появились диалекты языка LISP, инкорпорировавшие свойства языков Simula и Smalltalk. Более подробно особенности этих языков описаны в приложении 1. Первым, кто указал на важность построения систем в виде многоуровневых абстракций, был Дейкстра. Позднее Парнас (Parnas) ввел идею сокрытия информации [14]. В 1970-х годах ряд исследователей, главным образом Лисков (Liskov) и Жиль (Zilles) [15], Гуттаг (Guttag) [16], и Шоу (Shaw) [17], разработали механизмы абстрактных типов данных. Хоар (Ноаге) дополнил эти подходы теорией типов и подклассов [18]. Несмотря на то что технологии построения баз данных развивались независимо от языков программирования, они также внесли свой вклад в разработку объектного подхода [19], в основном с помощью идей подхода "сущность-отношение" (entity-relationship — ER) [20] к моделированию данных. В модели ER, предложенной Ченом (Chen) [21], моделирование происходит в терминах сущностей, их атрибутов и взаимоотношений. Свой вклад в развитие объектно-ориентированных абстракций внесли также исследователи в области искусственного интеллекта, разрабатывавшие методы представления знаний. В 1975 году Минский (Minsky) впервые выдвинул теорию фреймов (theory of frames) для представления реальных объектов в системах распознавания образов и естественных языков [22]. С тех пор фреймы стали использоваться в качестве архитектурной основы в различных интеллектуальных системах. В заключение отметим, что объектная модель стала предметом исследования философов и специалистов по когнитологии. Идея о том, что мир можно рассматривать как совокупность объектов или процессов, была выдвинута еще в Древней Греции. В XVII веке Декарт высказал мысль, что объектно-ориентированный взгляд на мир является вполне естественным [23]. В XX веке эту тему развивала Рэнд (Rand) в своей философии объективистской эпистемологии [24]. Позднее Минский (Minsky) предложил модель человеческого мышления, в которой разум человека рассматривается как совокупность различно мыслящих агентов [25]. Он утверждает, что только взаимодействие таких агентов порождает то, что мы называем интеллектом.
72 Часть I. Концепции обычных языков, таких как Pascal и даже COBOL или ассемблер, но это чрезвычайно трудно. Карделли (Cardelli) и Вегнер (Wegner) утверждают: "[А] Язык программирования является объектно-ориентированным тогда и только тогда, когда он удовлетворяет следующие условия. • Он поддерживает объекты, представляющие собой абстракции данных с интерфейсом в виде именованных операций и сокрытым локальным состоянием. • Объекты имеют ассоциированный с ними тип [класс]. • Типы [классы] могут наследовать атрибуты супертипов [суперклассов]". [28] Поддержка наследования в объектно-ориентированных языках означает возможность выражения отношения "is а" среди типов (например, красная роза — это цветок, а цветок — это растение). Если язык не поддерживает механизм наследования, то его нельзя считать объектно-ориентированным. Карделли и Вегнер предлагают называть такие языки объектными (object-based), а не объектно-ориентированными (object-oriented). Согласно этому определению языки Smalltalk, Object Pascal, C++, Eiffel, CLOS, C# и Java являются объектно-ориентированными, a Ada83 — объектным (позднее в язык Ada95 были добавлены объектно-ориентированные языки). Однако, поскольку объекты и классы являются элементами обеих групп языков, очень желательно и вполне возможно использовать объектно- ориентированные методы, работая на языках программирования как первой, так и второй группы. Объектно-ориентированное проектирование В программировании делается акцент на правильном и эффективном использовании механизмов конкретных языков программирования. В проектировании, наоборот, основное внимание уделяется правильному и эффективному структурированию сложных систем. Что же представляет собой объектно-ориентированное проектирование? Мы предлагаем следующее определение. Объектно-ориентированное проектирование — это метод проектирования, сочетающий процесс объектно-ориентированной декомпозиции и систему обозначения для представления логической и физической, а также статической и динамической моделей проектируемой системы. В данном определении обращают на себя внимание следующие две важные части: объектно-ориентированное проектирование 1) основывается на объектно- ориентированной декомпозиции и 2) использует разные системы обозначений для
Глава 2. Объектная модель 73 представления логических (классы и объекты) и физических (модули и процессы) моделей системы, а также ее статические и динамические аспекты. Именно объектно-ориентированная декомпозиция отличает объектно-ориентированное проектирование от структурного. В первом случае для выражения логической структуры системы используются классы и объекты, а во втором — алгоритмические абстракции. Иногда объектно-ориентированным проектированием называют любой метод, ведущий к объектной декомпозиции. Объектно-ориентированный анализ Объектная модель испытала влияние ранних моделей жизненного цикла программного обеспечения. Традиционные методы структурного анализа, прекрасно описанные в работах ДеМарко (DeMarko) [29], Йордона (Yordona) [30], Гейна (Gane) и Сарсона (Sarson) [31], а с приложением к системам реального времени — в работах Варда (Ward) и Меллора (Mellor) [32], а также Хатли (Hatley) и Пирб- хаи (Pirbhai) [33], основное внимание уделяют потокам данных внутри системы. Объектно-ориентированный анализ (object-oriented analysis — ООА) главный акцент делает на создании моделей реальной действительности на основе объектно- ориентированного мировоззрения. Объектно-ориентированный анализ — это метод анализа, исследующий требования к системе с точки зрения классов и объектов, относящихся к словарю предметной области. Как соотносятся между собой объектно-ориентированный анализ, проектирование и программирование? Результатами объектно-ориентированного анализа являются модели, лежащие в основе объектно-ориентированного проектирования, которое в свою очередь позволяет разработать схему полной реализации системы с использованием объектно-ориентированного программирования. 2.3 Составные части объектного подхода Дженкинс (Jenkins) и Глазго (Glasgow) утверждают: "Большинство программистов работают только на одном языке и придерживаются только одного стиля. Они принимают парадигму, обусловленную используемым языком программирования. Часто они даже не рассматривают альтернативные точки зрения на проблему, а, следовательно, им трудно выбрать стиль, лучше соответствующий решаемой задаче" [34]. Боброу и Стефик считают, что стиль программирования — "это способ создания программ с помощью определенных принципов программирования и подходящего языка, позволяющего писать ясные программы" [35]. По их мнению, существуют пять основных разновидностей стилей программирования. Они перечислены ниже вместе с используемыми абстракциями.
74 Часть I. Концепции 1. Процедурно-ориентированный Алгоритмы 2. Объектно-ориентированный Классы и объекты 3. Логико-ориентированный Цели, часто выраженные в терминах исчисления предикатов 4. Продукционный Правила "если, то" 5. Ориентированный на ограничения Инвариантные соотношения Не существует какого-то одного стиля программирования, который был бы наилучшим во всех возможных областях. Например, для проектирования баз знаний может оказаться наиболее удобным продукционный стиль, а для решения вычислительных задач — процедурно-ориентированный. Наш опыт подсказывает, что объектно-ориентированный стиль является наиболее приемлемым для самого широкого диапазона приложений. Действительно, эта парадигма часто служит архитектурным остовом, на котором реализуются другие парадигмы. Каждый стиль программирования имеет свою концептуальную основу и требует уникального подхода к решению задачи. Основой объектно-ориентированного стиля является объектная модель.Эта модель состоит из следующих четырех главных элементов. • Абстракция • Инкапсуляция • Модульность • Иерархия Термин главный элемент означает, что без любого из них модель не является объектно-ориентированной. Кроме главных, в этой модели существуют еще три дополнительных элемента. • Контроль типов • Параллелизм • Персистентность Термин дополнительный элемент означает полезный, но не существенный компонент объектной модели. Разумеется, программировать на таких языках, как Smalltalk, Object Pascal, C++, Eiffel или Ada можно, и не применяя объектную модель, но в этом случае проект будет напоминать программы, написанные на языках FORTRAN, Pascal или С. Выразительная мощность объектно-ориентированного языка будет либо утеряна, либо искажена. Кроме того, что еще более важно, в этом случае программисты вряд ли справятся со сложностью задачи.
Глава 2. Объектная модель 75 Абстрагирование Абстрагирование — один из основных методов, позволяющих справиться со сложностью. Даль (Dahl), Дейкстра (Dijkstra) и Хоар (Ноаге) утверждают: "Абстрагирование проистекает из распознавания сходства между определенными объектами, ситуациями или процессами в реальном мире, и является результатом решения сконцентрировать внимание на общих свойствах и проигнорировать различия" [36]. Шоу (Show) считает абстракцией "упрощенное описание, или спецификацию системы, выделяющую одни свойства и затеняющую другие, а хорошая абстракция подчеркивает значимые детали и отбрасывает несущественные на данный момент" [37]. Берзинс (Berzins), Грей (Gray) и Науман (Naumann) рекомендуют "признавать идею абстракцией только, если она может быть описана, понята и проанализирована независимо от механизма ее дальнейшей реализации" [38]. Суммируя эти разные точки зрения, приходим к следующему определению абстракции. Абстракция выделяет существенные характеристики некоторого объекта, отличающие его от всех других видов объектов и, таким образом, четко описывает его концептуальные границы с точки зрения наблюдателя. Абстракция концентрирует внимание на внешнем представлении объекта и позволяет отделить существенные особенности поведения от их реализации. Абель- сон (Abelson) и Суссман (Sussman) назвали такое разделение поведения от его реализации принципом минимальных обязательств (principle of least commitment) [39], в соответствии с которым интерфейс объекта должен обеспечивать только существенные аспекты его поведения и ничего больше [40]. Существует также дополнительный принцип наименьшего удивления (principle of least astonishment), согласно которому абстракция должна полностью описывать поведение объекта, ни больше и ни меньше, и не порождать сюрпризы или побочные эффекты, выходящие за пределы абстракции. Выбор правильной совокупности абстракций для заданной предметной области представляет собой главную задачу объектно-ориентированного проектирования. Поскольку эта тема чрезвычайно важна, ей целиком посвящена глава 4. "Существует целый спектр абстракций, начиная с объектов, почти точно соответствующих реалиям предметной области, и заканчивая совершенно излишними объектами" [41]. Перечислим абстракции в порядке убывания их полезности. • Абстракция сущности Объект, представляющий собой полезную модель некой сущности в предметной области • Абстракция действия Объект, состоящий из обобщенного множества операций, каждая из которых выполняет однотипные функции
76 Часть I. Концепции Абстракция концентрирует внимание на существенных свойствах объекта с точки зрения наблюдателя • Абстракция виртуальной Объект, группирующий операции, которые либо машины вместе используются на более высоком уровне управления, либо сами используют некоторый набор операций более низкого уровня • Произвольная абстракция Объект, включающий в себя набор операций, не имеющих друг с другом ничего общего Мы стараемся строить абстракции сущности, так как они прямо соответствуют сущностям предметной области. Клиентом (client) называется любой объект, использующий ресурсы другого объекта (называемого сервером (server)). Поведение объекта характеризуется услугами, которые он оказывает другим объектам, и операциями, которые он может выполнять над другими объектами. Такой подход концентрирует внимание на внешних проявлениях объекта и приводит к идее, которую Мейер (Meyer) назвал контрактной моделью (contract model) программирования [42]: внешнее проявление объекта определяет его контракт с другими объектами, подлежащий выполнению его внутренним устройством (часто во взаимодействии с другими объектами). Контракт фиксирует все предположения, которые объект-клиент может формулировать относительно поведения объекта-сервера. Иначе говоря, контракт определяет ответственность объекта, т.е. его обязательное поведение [43].
Глава 2. Объектная модель 77 Каждая операция, предусмотренная этим контрактом, однозначно определяется ее уникальной сигнатурой, состоящей из формальных параметров и типа возвращаемого значения. Полная совокупность операций, которые клиент может осуществлять над другим объектом, вместе с установленным порядком их вызова образуют протокол (protocol). Протокол указывает все возможные способы, которыми объект может действовать или реагировать на воздействие, полностью определяя внешнее статическое и динамическое представление абстракции. Главной идеей абстракции является концепция инварианта. Инвариант (invariant) — это логическое условие (истинное или ложное), которое должно выполняться всегда. Для каждой операции, ассоциированной с объектом, можно задать предусловия (инварианты, предполагаемые операцией) и постусловия (инварианты, которым удовлетворяет операция). Нарушение инварианта противоречит контракту, связанному с абстракцией. Если нарушается предусловие, то это значит, что клиент не соблюдает свои обязательства и сервер не в состоянии надежно функционировать. Аналогично, если нарушается постусловие, то свои обязательства не выполняет сервер, так что клиент больше не может ему доверять. Признаком нарушения некоего инварианта является исключительная ситуация. Некоторые языки позволяют объектам генерировать исключительные ситуации, чтобы отменить дальнейшую обработку данных и предупредить о возникшей проблеме другие объекты, которые в свою очередь могут перехватывать и обрабатывать исключения. Заметим, что понятия операция, метод и функция-член происходят из разных языков программирования (Ada, Smalltalk и C++ соответственно). По существу, они обозначают одно и то же и в дальнейшем будут использоваться как синонимы. Все абстракции обладают как статическими, так и динамическими свойствами. Например, файл как объект требует определенного объема памяти на конкретном запоминающем устройстве. Кроме того, у него есть имя и содержание. Все эти атрибуты являются статическими свойствами. Конкретные значения каждого из этих свойств носят динамический характер и зависят от жизненного цикла объекта. Например, файл можно увеличить или уменьшить, а также изменить его имя и содержимое. Суть всех программ, написанных в процедурном стиле, составляют действия, изменяющие динамические характеристики объектов. В таких программах события происходят только в результате вызова подпрограмм и выполнения операторов. С другой стороны, в программах, написанных в стиле, ориентированном на правила, события происходят только тогда, когда определенные условия приводят в действие установленные правила, которые, в свою очередь, активизируют другие правила, и т.д. В программах, написанных в объектно-ориентированном стиле, события связаны с воздействием на объекты (т.е. с передачей объектам определенных сообщений). Выполнение операции над объектом вызывает у него определенную реакцию. Поведение объекта полностью определяется операциями, которые над ним можно выполнять, и его реакцией на внешние воздействия.
78 Часть I. Концепции Примеры абстракций Проиллюстрируем сказанное несколькими примерами. Полное описание процесса выделения абстракций приведено в главе 4. В теплице, использующей гидропонику, растения выращиваются в питательном растворе, а не в почве. Обеспечение соответствующей окружающей среды — тонкая работа, зависящая как от сорта выращиваемой культуры, так и ее возраста. Для этого необходимо контролировать разнообразные факторы: температуру, влажность, освещение, кислотность и концентрацию питательных веществ. В больших хозяйствах широко используются автоматические системы, контролирующие и регулирующие эти факторы. Проще говоря, цель автоматизации — добиться соблюдения режима выращивания разнообразных растений при минимальном вмешательстве человека. Одна из ключевых абстракций в такой задаче — датчик. Существует несколько разновидностей датчиков. Все, что влияет на урожайность, должно быть измерено, поэтому необходимо иметь датчики температуры воды и воздуха, влажности, кислотности и концентрации питательного раствора и т.д. С точки зрения наблюдателя датчик температуры — это объект, предназначенный для измерения температуры в конкретном месте. Что такое температура? Это числовой параметр, изменяющийся в ограниченном диапазоне и измеряемый с определенной точностью по шкалам Фаренгейта, Цельсия или Кельвина. Что такое местоположение датчика? Это некоторое четко определенное место в теплице, температуру в котором нам необходимо измерить. Таких мест, как правило, немного. Для датчика температуры существенно, не где он расположен, а то, что он в принципе может быть размещен в конкретном месте, отдельно от других датчиков. Теперь выясним, что должен делать датчик температуры? Допустим, в соответствии с проектом датчик должен измерять температуру в точке своего размещения и сообщать ее по запросу. Уточним теперь, какие действия клиент может выполнять с датчиком? Пусть проектное решение предусматривает, что клиент может калибровать датчик и запрашивать у него текущее значение температуры. (См. рис. 2.6. Обратите внимание на то, что это представление похоже на представление класса в системе обозначений UML 2.0. Эта система обозначений будет рассмотрена в главе 5.) Описанная выше абстракция была пассивной: клиент должен попросить объект Temperature Sensor измерить температуру. Однако есть и другая вполне разумная абстракция, расширяющая возможности системы. В частности, датчик мог бы быть активным и самостоятельно сообщать другим объектам об изменении температуры в определенном месте на заданное количество градусов. Эта абстракция мало отличается от предыдущей, за исключением новой формулировки обязанностей объекта: теперь датчик должен самостоятельно сообщать об изменении температуры, а не по запросу. Какие новые операции нужны ему в связи с этим?
Глава 2. Объектная модель 79 Абстракция: Temperature Sensor Важные свойства: температура местоположение Обязанности: сообщать о текущей температуре калибровать Рис. 2.6. Абстракция Temperature Sensor Новая абстракция лишь ненамного сложнее первой (см. рис. 2.7). Клиент этой абстракции может изменять пороговое значение датчика температуры. Обязанность датчика — сообщать об изменении текущей температуры, когда ее текущее значение становится выше или ниже порогового. При вызове этой функции датчик сообщает свое местоположение и текущую температуру, снабжая клиента требуемой информацией. Абстракция: Active Temperature Sensor Важные свойства: температура местоположение пороговое значение Обязанности: сообщать о текущей температуре калибровать установить пороговое значение Рис. 2.7. Абстракция Active Temperature Sensor Способ выполнения обязательств абстракции Active Temperature Sensor зависит от ее внутреннего представления и не должен интересовать внешних клиентов. Эта информация является секретом класса и реализуется его закрытой частью совместно с определениями функций-членов. Рассмотрим теперь другую абстракцию. Для каждой культуры должен существовать производственный план, описывающий изменение во времени температуры, освещения, подкормки и ряда других факторов, обеспечивающих максимально высокий урожай. Этот план также можно абстрагировать, поскольку он является частью предметной области.
80 Часть I. Концепции Производственный план должен предусматривать средства контроля всех необходимых действий по выращиванию растений и содержать их временное расписание. Например, для некоторой культуры на 15-е сутки роста план может требовать в течение 16 часов поддерживать температуру на уровне 25°С, причем 14 часов из них — с освещением, а затем понизить температуру до 18°С на остальное время суток. Кроме того, план может предусматривать внесение дополнительных удобрений в середине дня, чтобы поддержать слабую кислотность. С точки зрения внешнего наблюдателя клиент должен иметь возможность составлять план, модифицировать его и запрашивать его содержание, как показано на рис. 2.8. (Обратите внимание на то, что эта абстракция также эволюционирует с течением времени. По мере конкретизации деталей такая обязанность, как "задать план", может быть разделена на множество обязанностей, например, "установить температуру", "установить кислотность" и т.д. Вполне закономерно, что по мере уточнения потребностей клиента проект достигает зрелости и проектировщик начинает рассматривать разные подходы к его реализации.) Абстракция: Growing Plan Важные свойства: имя Обязанности: задать план изменить план аннулировать план Рис. 2.8. Абстракция Growing Plan Проектное решение заключается в том, что в обязанности абстракции плана не входит выполнение самого плана, — это будет обязанностью другой абстракции (например, Plan Controller). Таким образом, можно разделить понятия (separation of concerns) между разными частями системы, уменьшив концептуальный размер каждой отдельной абстракции. Например, объект может предусматривать взаимодействие человека и компьютера, допуская ручное изменение плана. Объект, содержащий детали плана выращивания, должен уметь изменять состояние объекта Growing Plan. Кроме того, должен существовать объект, выполняющий план. Для этого он должен иметь возможность прочитать план в определенный момент времени. Как следует из описанного примера, ни один объект не изолирован от других. Все объекты взаимодействуют друг с другом для обеспечения определенного
Глава 2. Объектная модель 81 Объекты взаимодействуют между собой, обеспечивая требуемое поведение поведения1. Проектное решение, регламентирующее взаимодействие между объектами, определяет границы абстракций и протокол каждого объекта. Инкапсуляция Несмотря на то что абстракция Growing Plan описана как отображение время-действие (time/action mapping), она не обязательно должна быть реализована как таблица или ассоциативный массив (тар). Действительно, выбор способа реализации абстракции Growing Plan не имеет никакого отношения к контракту клиента, пока ее представление соответствует контракту. Проще говоря, абстракция объекта должна предшествовать решению о ее реализации. Как только решение о реализации принято, оно должно рассматриваться как секрет абстракции и скрываться от большинства клиентов. Абстракция и инкапсуляция дополняют друг друга. В центре внимания абстракции находится наблюдаемое поведение объекта, а инкапсуляция сосредоточена на реализации, обеспечивающей заданное поведение. Как правило, инкапсуляция осуществляется с помощью сокрытия информации (а не просто сокрытия данных), т.е. утаивания всех несущественных деталей объекта. Обычно скрываются как структура объекта, так и реализация его методов. "Никакая часть сложной системы не должна зависеть от внутреннего устройства какой-либо другой ча- 1 Иначе говоря, перефразируя поэта Джона Донна (John Donne), объект — не остров (хотя понятие острова можно абстрагировать в виде объекта).
82 Часть I. Концепции Инкапсуляция скрывает детали реализации объекта сти" [44]. В то время как абстракция "помогает людям думать о том, что они делают", инкапсуляция "позволяет легко перестраивать программы" [45]. Инкапсуляция определяет четкие границы между разными абстракциями и позволяет, таким образом, провести ясные различия между понятиями. Рассмотрим, например, структуру растения. Для того чтобы изучить механизм фотосинтеза, оставаясь на верхнем уровне абстракции, можно игнорировать такие детали, как функции корней растения или химические свойства стенок клеток. Аналогично, при проектировании баз данных принято писать программы так, чтобы они зависели не от физического представления данных, а от логической структуры данных [46]. В обоих случаях объекты, расположенные на одном уровне абстракции, защищены от деталей реализации объектов, относящихся к более низкому уровню. "Для того чтобы абстракция работала, ее реализация должна быть инкапсулирована" [47]. На практике это означает, что каждый класс должен состоять из двух частей: интерфейса и реализации. Интерфейс класса фиксирует лишь внешнее представление объекта, описывая абстракцию поведения всех объектов данного класса. Реализация класса содержит как представление абстракции, так и механизмы достижения требуемого поведения объекта. Интерфейс класса содержит все предположения, которые клиент может сформулировать относительно объектов класса, а реализация скрывает от других объектов все детали, не имеющие отношения к процессу — все, что не касается предположений клиента. Итак, инкапсуляцию можно определить следующим образом. Инкапсуляция — это процесс разделения элементов абстракции, определяющих ее структуру и поведение; инкапсуляция предназначена для изоляции контрактных обязательств абстракции от их реализации.
Глава 2. Объектная модель 83 Бриттон (Britton) и Парнас (Parnas) назвали инкапсулированные детали "секретами абстракции" [48]. Примеры инкапсуляции Для иллюстрации принципа инкапсуляции вернемся к примеру гидропонного тепличного хозяйства. Одной из важнейших абстракций данной предметной области является обогреватель. Обогреватель представляет собой абстракцию низкого уровня, поэтому существуют только три целесообразных действий с этим объектом: включение, выключение и запрос состояния. Разделение понятий Абстракция Heater не должна поддерживать постоянную температуру. Эту обязанность следует возложить на другую абстракцию (например, Heater Controller), которая должна взаимодействовать с датчиком температуры и обогревателем, обеспечивая поведение более высокого уровня. Это поведение относится к более высокому уровню, потому что оно основывается на простой семантике обогревателя и датчика, добавляя к ним дополнительные свойства, в частности, гистерезис предотвращает слишком быстрое включение и выключение нагревателя, когда температура приближается к критической. Разделив ответственность, мы делаем каждую абстракцию более цельной. Интерфейс доступа (т.е. функции, которые класс может выполнить по требованию клиента, как показано на рис. 2.9) — это все, что клиенту следует знать о классе Heater. Обращаясь к внутреннему представлению класса Heater, можно обнаружить совершенно другую картину. Предположим, что проектировщики решили разместить управляющие компьютеры вне теплицы (возможно, чтобы избежать слишком суровых климатических условий) и соединить их с датчиками и исполнительными механизмами с помощью линии последовательной передачи. Класс Heater естественно реализовать с помощью электромеханических реле, управляющих мощностью, поступающей на каждый обогреватель и получающих сообщения по линиям последовательной передачи. Например, для включения обогревателя можно передать специальную командную строку, номер обогревателя и индикатор включения. Предположим, что по какой-либо причине проектировщики изменили решение и вместо последовательных линий передачи решили использовать для управления запоминающее устройство. Интерфейс класса Heater останется прежним, но его реализация кардинально изменится. В этом случае клиенты, которым доступен только интерфейс класса Heater, не обнаружат никаких изменений. Это главная особенность инкапсуляции. Фактически, клиента не должна интересовать реализация класса, пока класс Heater удовлетворяет его требованиям.
84 Часть I. Концепции Абстракция: Heater Важные свойства: местоположение состояние Обязанности: включить выключить сохранять состояние Рис. 2.9. Абстракция Heater Рассмотрим теперь реализацию класса Growing Plan. Как указывалось ранее, временное расписание, по существу, является отображением времени в действие. Вероятно, наиболее эффективной реализацией такого отображения является словарь пар время/действие с открытой хеш-таблицей. Нет никакой необходимости хранить список действий для каждого часа, поскольку события не происходят настолько часто. Вместо этого можно хранить только моменты времени, в которых должны выполняться действия, изменяющие состояние системы, интерполируя реализацию между этими моментами времени. Таким образом, реализация класса инкапсулирует два секрета: использование открытой хеш-таблицы (которая относится к словарю проектных решений, а не предметной области) и использование интерполяции для уменьшения требований к объему памяти (в противном случае пришлось бы хранить список пар время/ действие для всего сезона). Клиентам этой абстракции совершенно не обязательно знать об этом решении, поскольку оно никак не влияет на внешнее представление класса. Разумная инкапсуляция должна локализовать проектные решения, которые могут измениться. По мере эволюции системы ее разработчики могут обнаружить, что какие-то операции выполняются недопустимо долго, а какие-то объекты занимают слишком много памяти. В таких ситуациях внутреннее представление объекта, как правило, изменяется, чтобы реализовать более эффективные алгоритмы или оптимизировать использование памяти, заменяя хранение данных их вычислением. Возможность изменения представления абстракции без ведома клиентов является важным преимуществом инкапсуляции. Сокрытие информации является относительным понятием. То, что скрыто на одном уровне абстракции, может оказаться открытым на другом уровне. В принципе, реализацию объектов можно раскрыть. Правда, в большинстве случаев это происходит в соответствии с явным замыслом разработчика абстракции и толь-
Глава 2. Объектная модель 85 ко если разработчики классов-клиентов согласны на увеличение сложности. Инкапсуляция не способна предотвратить ошибочные решения. Как отметил Стра- уструп, "Инкапсуляция защищает от случайностей, но не от жульничества" [49]. Разумеется, ни один язык программирования не способен полностью закрыть доступ к реализации класса, хотя операционная система может перекрыть доступ к конкретному файлу, содержащему реализацию класса. Модульность "Разделение программы на модули до некоторой степени позволяет уменьшить ее сложность... Однако гораздо важнее тот факт, что при этом в модульной программе возникает множество хорошо определенных и документированных интерфейсов. Эти интерфейсы неоценимы для понимания программы" [50]. В некоторых языках программирования, например в Smalltalk, модулей нет, и единственной физической единицей декомпозиции является класс. Во многих других языках, включая Object Pascal, C++ и Ada, модуль — это самостоятельная языковая конструкция, позволяющая создавать комплексы отдельных проектных решений. В этих языках логическую структуру системы образуют классы и объекты. Она помещается в модули, из которых состоит физическая структура системы. Это свойство особенно полезно в крупных системах, состоящих из многих сотен классов. "Модульность — это разделение программы на фрагменты, которые компилируются по отдельности, но связаны между собой". В соответствии с определением Парнаса (Parnas): "Связи между модулями — это их предположения о работе друг друга" [51]. В большинстве языков, поддерживающих принцип модульности как самостоятельную концепцию, интерфейс модуля отделен от его реализации. Таким образом, можно утверждать, что модульность и инкапсуляция тесно связаны между собой. Правильный выбор модулей для решения поставленной задачи является почти такой же сложной задачей, как выбор правильного набора абстракций. Зельковиц (Zelkowitz) был абсолютно прав, утверждая: "Поскольку в начале работы над проектом решение может быть неясным, декомпозиция на более мелкие модели может вызвать затруднения. Для традиционных приложений (например, разработки компиляторов) этот процесс можно стандартизировать, но для новых задач (например, оборонительных систем или систем управления космическими кораблями) задача может оказаться довольно трудной" [52]. Модули служат физическими контейнерами, содержащими классы и объекты, возникающие при логическом проектировании системы. Точно такая же ситуация возникает у проектировщиков материнских плат компьютеров. Требуемую логику можно создать с помощью элементарных схем типа НЕ-И (NAND), НЕ-ИЛИ (NOR), HE (NOR), но эти вентили необходимо упаковать в стандартные интеграль-
86 Часть I. Концепции ные схемы. Однако программист обладает намного большей свободой, как если бы электротехник имел в своем распоряжении кремниевую мастерскую с неограниченными возможностями. Разработчик, решающий небольшие задачи, может описать все классы и объекты в одном модуле. Однако при создании большинства программ (кроме самых простых) лучше объединить логически связанные классы и объекты, оставив открытыми лишь те элементы, которые нельзя скрывать от других модулей. Такой способ разбиения на модули хорош, но его можно довести до абсурда. Рассмотрим, например, программу, которая выполняется на многопроцессорном компьютере и использует механизм передачи сообщений. В больших системах, например, в системах управления, как правило, происходит обмен несколькими сотнями и даже тысячами видов сообщений. Было бы наивным определять каждый класс сообщения в отдельном модуле. Это крайне неудачное проектное решение. Оно не только чрезвычайно запутает документирование программы, но и усложнит поиск класса, необходимого пользователю. Более того, если потребуется изменить проект, то придется модифицировать и перекомпилировать сотни модулей. Этот пример показывает, что сокрытие информации имеет обратную сторону [53]. Произвольное разделение программы на модули иногда гораздо хуже, чем отсутствие модульности вообще. Модульность позволяет упаковать абстракции в отдельные единицы программы В традиционном структурном проектировании модульность, как правило, проявляется в группировке подпрограмм по логическим группам на основе критериев связности и целостности. В объектно-ориентированном программировании модульность имеет несколько иной характер, поскольку она предусматривает фи-
Глава 2. Объектная модель 87 зическую упаковку классов и объектов, существенно отличающихся от подпрограмм. Существует несколько эмпирических приемов и правил, позволяющих обеспечить разумную модульность. Бриттон (Britton) и Парнас (Parnas) утверждают: "Конечной целью декомпозиции программы на модули является снижение затрат на программирование, благодаря независимому проектированию и тестированию... Структура каждого модуля должна быть достаточно простой для понимания, допускать независимую реализацию других модулей и не влиять на поведение других модулей, а также позволять легкое изменение проектных решений" [54]. На практике эти принципы реализуются лишь частично. Повторное компилирование тела отдельного модуля не требует больших затрат, поскольку остальные модули остаются неизменными, а обновляются только связи между ними. Однако стоимость повторной компиляция интерфейса модуля относительно велика. В языках программирования со строгим контролем типов приходится повторно компилировать интерфейс и тело модифицированного модуля, затем все зависимые модули и т.д. В итоге для очень больших программ повторная компиляция может оказаться очень долгой (если только среда разработки не поддерживает инкрементную компиляцию), что явно нежелательно. Очевидно, руководитель проекта не должен допускать слишком частую повторную компиляцию. По этой причине интерфейс модуля должен быть как можно более узким (обеспечивая, тем не менее, необходимые связи с другими модулями). Правильный стиль программирования требует как можно больше скрывать реализацию модуля. Постепенный перенос описаний из реализации в интерфейс гораздо безопаснее, чем удаление излишнего интерфейсного кода. Таким образом, проектировщик должен балансировать между двумя противоположными тенденциями: желанием инкапсулировать абстракции и необходимостью открыть доступ к тем или иным абстракциям для других модулей. "Изменяемые детали системы следует скрывать в отдельных модулях. Открытыми следует оставлять лишь элементы, обеспечивающие связь между модулями, вероятность изменения которых крайне мала. Все структуры данных в модуле должны быть закрыты. Они могут оставаться доступными для процедур внутри модуля, но должны быть недоступными для всех внешних подпрограмм. Доступ к информации, хранящейся внутри модуля, должен осуществляться с помощью вызова процедур данного модуля" [55]. Иначе говоря, следует создавать цельные (объединяющие логически связанные между собой абстракции) и слабо связанные между собой модули. Таким образом, можно сформулировать следующее определение. Модульность — это свойство системы, разложенной на цельные, но слабо связанные между собой модули.
88 Часть I. Концепции Итак, принципы абстракции, инкапсуляции и модульности являются синерге- тическими. Объект позволяет определить четкие границы отдельной абстракции, а инкапсуляция и модульность создают барьеры между абстракциями. Разделение системы на модули имеет два дополнительных аспекта. Во-первых, поскольку модули, как правило, являются элементарными и неделимыми структурными элементами программного обеспечения и могут использоваться в приложениях неоднократно, разделение программы на модули должно допускать повторное использование кода. Во-вторых, многие компиляторы создают отдельные сегменты кода для каждого модуля. Следовательно, могут возникнуть физические ограничения на размер модуля. Динамика вызовов подпрограмм и размещение объявлений внутри модулей могут существенно влиять на локальность ссылок и на управление страницами виртуальной памяти. Вызовы между несмежными сегментами приводят к "промахам кэша" (cashe miss) и порождают режим интенсивной подкачки страниц памяти (trashing), что в итоге тормозит работу всей системы. Разбиение на модули должно учитывать дополнительные факторы, не носящие технического характера. Как правило, распределение работы между участниками проектной группы осуществляется по модульному принципу. Следовательно, систему необходимо разделять на модули так, чтобы минимизировать количество связей между участниками проекта. Опытные программисты обычно отвечают за разработку интерфейсов модулей, а менее опытные — за их реализацию. Аналогичная ситуация наблюдается в более крупном масштабе в отношениях между субподрядчиками. Распределение абстракций должно облегчать быстрое согласование интерфейсов модулей между компаниями, участвующими в проекте. Изменения интерфейсов, уже согласованных между компаниями, обычно сопровождаются воплями и зубовным скрежетом — помимо огромного расхода бумаги, — поэтому проектирование интерфейса является крайне консервативным делом. Кроме того, модуль служит отдельной единицей документации и администрирования. Десять модулей требуют в десять раз больше описаний, чем один, и поэтому, к сожалению, иногда на декомпозицию проекта влияют (как правило, негативно) побочные соображения, связанные с составлением проектной документации. На модульность проекта может влиять его секретность. Например, большая часть кода может считаться открытой, а остальная часть — секретной. В таком случае секретную часть размещают в отдельных модулях. Согласовать эти противоречивые требования довольно трудно, но следует помнить главное: выявление классов и объектов, с одной стороны, и организация их в виде отдельных модулей, с другой стороны, — это практически независимые проектные решения. Идентификация классов и объектов представляет собой часть логического проектирования системы, а идентификация модулей — часть ее физического проектирования. Разумеется, невозможно полностью осуществить
Глава 2. Объектная модель 89 логическое проектирование системы до реализации физического проектирования, и наоборот. Два этих процесса носят итеративный характер. Примеры модульности Исследуем модульность гидропонной теплицы. Предположим, что проектировщик решил использовать для управления ее работой коммерческую рабочую станцию. С помощью этой рабочей станции оператор может создавать новые планы выращивания, модифицировать старые планы и контролировать их исполнение. Так как основной абстракцией в системе является план выращивания, необходимо создать модуль, содержащий все классы, связанные с отдельными планами выращивания (например, FruitGrowmingPlan, GrainGrowingPlan). В этом модуле можно собрать все классы, относящиеся к абстракции GrowingPlan. Кроме того, можно создать модуль, в котором будут собраны все функции, реализующие пользовательский интерфейс. Проект, вероятно, будет содержать много других модулей. В конце концов необходимо определить главную программу, которая будет вызываться для запуска приложения. В объектно-ориентированном проектировании выбор главной программы часто является наименее важным решением, в то время как в традиционном структурном проектировании главная программа является краеугольным камнем, на который опирается весь проект. Объектно-ориентированный подход является более естественным. Мейер (Meyer) утверждает: "Реальные системы программного обеспечения естественно описывать как системы, предлагающие некоторый набор услуг. Сводить их к одной функции, в принципе, можно, но не естественно... Реальные системы не имеют крыши" [56]. Иерархия Абстракция — вещь полезная, но их количество всегда, кроме самых тривиальных приложений, намного превышает человеческие возможности. Инкапсуляция позволяет справиться со сложностью, скрыв внутреннее представление абстракций. Модульность также упрощает понимание проблемы, позволяя объединить логически связанные абстракции в группы. Определим иерархию следующим образом. Иерархия — это ранжирование, или упорядочение абстракций. Наиболее важными видами иерархии в сложных системах являются структура классов (иерархия "общее/частное") и структура объектов (иерархия "целое/ часть"). Примеры иерархии: одиночное наследование Как указывалось выше, наследование представляет собой одну из наиболее важных иерархий, основанных на отношении "является" ("is а"). Оно лежит в ос-
90 Часть I. Концепции нове многих объектно-ориентированных систем. Наследование означает такое отношение между классами, когда один класс заимствует структуру или поведение одного или нескольких других классов (одиночное и множественное наследование соответственно). Иначе говоря, наследование создает иерархию абстракций, в которой подклассы заимствуют свойства одного или нескольких суперклассов. Обычно подкласс наращивает или переопределяет существующую структуру и поведение суперкласса. С семантической точки зрения, наследование описывает отношение типа "является". Например, медведь — это разновидность млекопитающего ("is a" kind of mammal"), дом — это разновидность материальных активов ("is a" kind of tangible asset), а метод быстрой сортировки — это разновидность алгоритма сортировки ("is a" kind of sorting algorithm). Таким образом, наследование порождает иерархию обобщения/специализации, в которой подкласс конкретизирует более общую структуру или поведение своего суперкласса. Действительно, существует безошибочный тест для наследования: если класс В не является разновидностью класса А, то класс В не должен быть наследником класса А. Рассмотрим разные планы выращивания растений в гидропонной теплице. В предыдущем разделе описана абстракция очень общего плана выращивания растений. Однако разные культуры требуют разных планов выращивания. Например, планы выращивания всех фруктов похожи друг на друга, но отличаются от планов выращивания овощей или цветов. Учитывая эту кластеризацию абстракций, целесообразно определить стандартный план выращивания фруктов, а именно расписание поливов и уборки урожая. План FruitGrowingPlan можно считать разновидностью плана GrowingPlan. Это означает, что план FruitGrowingPlan является разновидностью плана GrowingPlan. To же самое можно сказать о планах GrainGrowingPlan или VegetableGrowingPlan. В этом случае класс GrowingPlan является суперклассом, а остальные — подклассами. По мере эволюции иерархии наследования структура и поведение, общие для разных классов, имеют тенденцию мигрировать в наиболее общий суперкласс. Именно поэтому наследование часто называют иерархией обобщение/специализация. Суперклассы представляют обобщенные абстракции, а подклассы — специализации, в которые добавляются, модифицируются и даже скрываются поля и методы из суперклассов. Наследование позволяет экономить выражения при описании абстракций. Пренебрежение иерархиями "общее/частное" может привести к громоздким проектным решениям. "Без наследования каждый класс представляет собой изолированную структурную единицу и должен разрабатываться "с нуля". Разные классы теряют общность, поскольку каждый программист реализует их методы по-своему. В этом случае согласованность классов системы может быть обеспечена только за счет дисциплинированности программистов.
Глава 2. Объектная модель 91 Наследование позволяет создавать новые программы точно так же, как вводятся новые понятия — сравнивая новое с уже известным" [57]. Между принципами абстракции, инкапсуляции и иерархии существует здоровая конкуренция. "Абстракция данных создает непроницаемый барьер, скрывающий методы и состояние объекта. Принцип наследования требует открыть доступ и к состоянию, и к методам объекта, не прибегая к абстракции" [58]. У любого класса обычно существуют два вида клиентов: объекты, выполняющие операции над экземплярами данного класса, и подклассы, наследующие свойства класса. Дисков (Liskov) отмечает, что существуют три способа нарушения инкапсуляции с помощью наследования: "подкласс может получить доступ к переменным экземпляра своего суперкласса, вызвать закрытую функцию и, наконец, обратиться напрямую к суперклассу своего суперкласса" [59]. Разные языки программирования по-разному согласовывают наследование с инкапсуляцией. Наиболее гибкими в этом отношении являются C++ и Java. В частности, интерфейс класса может состоять из трех частей: закрытой (private), доступной только самому классу; защищенной (protected), в которой объявляются члены, доступные только для класса и его подклассов; и открытую (public), доступную всем клиентам. Примеры иерархии: множественное наследование В предыдущем примере продемонстрировано одиночное наследование: подкласс FruitGrowingPlan имел только один суперкласс GrowingPlan. Иногда полезно реализовать наследование от нескольких суперклассов. Предположим, например, что требуется определить класс, представляющий разновидности растений. Анализ предметной области показывает, что цветы, фрукты и овощи имеют свои особые свойства, существенные для технологии их выращивания. Например, для абстракции цветов важно знать периоды цветения и созревания семян. Аналогично, для абстракций фруктов и овощей важен момент сбора урожая. Исходя из этих соображений, можно создать два новых класса — Flower и FruitVe- getable — наследники суперкласса Plant. Какую же модель следует выбрать, если растение и цветет, и плодоносит? Например, флористы часто используют для составления букетов цветки яблони, вишни и сливы. Для этой абстракции придется создать третий класс FlowerFruitVegetable — наследник классов Flower и FruitVegetablePlant. Чтобы наилучшим образом выразить новую абстракцию и не допустить ошибку, следует создать классы, независимо друг от друга описывающие уникальные свойства цветов, а также фруктов и овощей соответственно. Эти два класса не имеют суперкласса. Они называются классами-примесями (mixin classes), поскольку смешиваются вместе с другими классами, создавая новые подклассы. Например, можно описать класс Rose (см. рис. 2.10), наследующий свойства классов Plant и FlowerMixin. Таким образом, экземпляры подкласса Rose наследуют структуру и поведение классов Plant и FlowerMixin.
92 Часть I. Концепции Рис. 2.10. Класс Rose — наследник нескольких суперклассов Точно так же можно определить класс Carrot, продемонстрированный на рис. 2.11. В обоих случаях подкласс образуется путем наследования свойств двух суперклассов. Рис. 2.11. Класс Carrot — наследник нескольких суперклассов Определим теперь класс, описывающий свойства вишни, которая цветет и плодоносит (рис. 2.12). CherryTree FruKVegetabMHIixIn Рис. 2.12. Класс CherryTree — наследник нескольких суперклассов
Глава 2. Объектная модель 93 Несмотря на то что множественное наследование представляет собой довольно простую концепцию, оно создает некоторые сложности для языков программирования — конфликты имен между различными суперклассами и повторное наследование. Конфликты имен возникают, когда в двух или большем числе суперклассов определены поля или операции с одинаковыми именами. Повторное наследование возникает, когда несколько суперклассов наследуют свойства общего суперкласса. В таких ситуациях возникает ромбическая структура наследования, и проектировщик должен решить, сколько копий полей должен унаследовать класс самого нижнего уровня у суперкласса самого верхнего уровня — одну или две (см. рис. 2.13). В некоторых языках повторное наследование запрещено, в других конфликт разрешается однозначно, а в языке С++ решение должен принять сам программист. В языке C++ для запрещения дублирования повторяющихся структур используются виртуальные базовые классы, иначе в подклассе могут появиться дубликаты (для которых потребуется явное указание происхождения каждой). Общий суперкласс Суперклассы одного уровня ????? Подкласс В Подкласс D Рис. 2.13. Повторное наследование Множественным наследованием часто злоупотребляют. Например, сладкая вата — это разновидность сладости, но никак не ваты. К этой ситуации можно применить описанный ранее критерий: если класс В не является разновидностью класса А, то он не должен быть наследником класса А. Часто плохо продуманные структуры множественного наследования следует свести к одному суперклассу, по возможности используя агрегацию других классов подклассами.
94 Часть I. Концепции Примеры иерархии: агрегация Если иерархии "общее/частное" определяют отношение "обобщение/специализация", то иерархии "целое/часть" описывают отношения агрегации. Рассмотрим, например, абстракцию огорода. Можно утверждать, что огород — это совокупность растений и план их выращивания. Иначе говоря, растения и план выращивания — это части огорода. Это отношение "является частью" называется агрегацией (aggregation). Агрегация есть во всех объектно-ориентированных проектах и языках программирования. Действительно, любой язык программирования, имеющий структуры, подобные записям, поддерживает агрегацию. Однако в сочетании с наследованием агрегация создает мощный инструмент: она позволяет физически объединить логически связанные структуры, а наследование — без труда повторно использовать эти общие группы в разных абстракциях. Анализируя иерархии, подобные рассмотренным выше, часто говорят об уровнях абстракции, концепцию которых впервые предложил Дейкстра [60]. В терминах иерархии "общее/частное" абстракция верхнего уровня является обобщенной, а абстракция нижнего уровня — специализированной. Следовательно, можно сказать, что класс Flower относится к более высокому уровню абстракций, чем класс Plant. В терминах иерархии "целое/часть" класс относится к более высокому уровню абстракции по сравнению с любыми классами, входящими в его реализацию. Таким образом, класс Garden относится к более высокому уровню абстракции, чем класс Plant, на основе которого он создается. Кроме того, агрегация поднимает проблему владения. Абстракция огорода допускает, что на огороде одновременно растет много растений, но вследствие замены одного растения другим огород не становится другим огородом, а уничтожение огорода не обязательно означает уничтожение всех растений (ведь их можно пересадить в другое место). Иначе говоря, жизненные циклы огорода и растений не зависят друг от друга. И наоборот, проектное решение предусматривает, что объект GrowingPlan неразрывно связан с объектом Garden и не существует независимо от него. Следовательно, план выращивания может храниться в каждом экземпляре класса Garden и уничтожается вместе с ним. Контроль типов Понятие типа происходит из теории абстрактных типов данных. Дейч (Deutsch) утверждает: "Тип — это точная характеристика структуры и поведения, присущих некоторой совокупности объектов" [61]. В дальнейшем будем считать, что тер-
Глава 2. Объектная модель 95 мины тип и класс являются синонимами2. Несмотря на сходство понятий типа и класса, контроль типов следует обсудить как отдельный элемент объектной модели, поскольку концепция типа позволяет взглянуть на абстракцию с совершенно другой точки зрения. Контроль типов — это правила использования объектов, не допускающие или ограничивающие взаимную замену объектов разных классов. Контроль типов заставляет проектировщиков выражать свои абстракции так, чтобы язык программирования, используемый для реализации системы, поддерживал принятые проектные решения. Конкретный язык программирования может иметь сильный или слабый контроль типов, и даже совсем не иметь такого свойства, оставаясь объектно-ориентированным. Например, язык Eiffel предусматривает строгий контроль типов: операция не может быть применена к объекту, если ее точная сигнатура не содержится в его классе или суперклассе. Основным понятием контроля типов является соответствие (conformance). Рассмотрим, например, абстракцию физической единицы измерения [63]. Если разделить расстояние на время, мы получим число, означающее скорость, а не вес. Аналогично, деление единицы силы на температуру бессмысленно, а деление единицы силы на массу — нет. Эти примеры относятся к строгому контролю типов, поскольку правила исследуемой предметной области четко определены и регламентируют допустимые сочетания абстракций. Строгий контроль позволяет использовать язык программирования для поддержки определенных проектных решений и позволяет справиться с нарастающей сложностью систем. Однако у строгого контроля типов есть обратная сторона. На практике она порождает семантические зависимости, при которых небольшое изменение интерфейса в базовом классе вынуждает повторную компиляцию всех его подклассов. Существуют два общих решения этих проблем. Во-первых, можно использовать контейнерный класс, обладающий типовой безопасностью (type-safe). Это подход позволяет решить первую проблему, избегая смешивания объектов разных типов. Во-вторых, можно использовать идентификацию типов на этапе выполнения программы. Это позволяет решить вторую проблему, определяя тип объекта в определенный момент. Однако идентификацию типов на этапе выполнения про- 2Тип и класс не вполне одно и то же. В некоторых языках эти два понятия отличаются друг от друга. Например, в ранних версиях языка Trellis/Owl объект может иметь тип и принадлежать классу. Даже в языке Smalltalk объекты классов Smalllnteger, LargeNegativelnteger, Large- Positivelnteger относятся к одному типу Integer, но к разным классам [62]. Большинству смертных совершенно не обязательно различать типы и классы. Достаточно сказать, что класс реализует некий тип.
96 Часть I. Концепции Строгий контроль типов предотвращает смешение абстракций граммы следует использовать только, если для этого есть непреодолимая причина, поскольку ослабляется инкапсуляция. Как будет показано в следующем разделе, вместо идентификации типов на этапе выполнения программы можно (но не всегда) использовать полиморфные операции. Как указывает Теслер (Tesler), языки программирования со строгим контролем типов имеют ряд преимуществ. • В отсутствие контроля типов работа программ в большинстве языков может завершиться непредсказуемо. • В большинстве систем цикл редактирование-компиляция-отладка настолько утомителен, что раннее обнаружение ошибок крайне желательно. • Объявление типов облегчает документирование программ. • Многие компиляторы способны генерировать более эффективный объектный код, если типы объявлены явно [64]. Языки, в которых контроль типов отсутствует, обладают большей гибкостью, но и в этом случае, по мнению Борнинга (Borning) и Ингаллса (Ingalls), "программисты практически всегда знают, какие объекты ожидаются в качестве аргументов
Глава 2. Объектная модель 97 сообщения и какие подлежат возвращению" [65]. На практике безопасность, обеспечиваемая языками программирования со строгим контролем типов, с лихвой компенсирует потерю гибкости, присущей языкам без контроля типов, особенно при проектировании крупномасштабных систем. Примеры контроля типов: статический и динамический Сильный (strong) и слабый (weak) контроль типов, с одной стороны, и статический (static) и динамический (dynamic) контроль типов, с другой стороны, — это разные вещи. Строгий контроль типов означает соответствие типов (type consistency), а статический контроль типов (иначе называемый статическим, или ранним связыванием (static, or early binding)), определяет момент времени на этапе компиляции, в который фиксируется тип переменных или выражений. Динамический контроль типов (называемый также поздним связыванием (late binding)) означает, что типы переменных и выражений до момента выполнения программы остаются неизвестными. Язык программирования может одновременно предусматривать сильный и статический контроль типов (Ada), сильный и динамический контроль типов (C++, Object Pascal), или не предусматривать контроль типов, но допускать динамическое связывание (Smalltalk). Наследование и динамическое связывание порождают полиморфизм (polymorphism). Эта концепция теории типов позволяет одним именем (например, одним объявлением переменной) обозначать объекты, относящиеся к разным классам, но связанные с общим суперклассом. Любой объект, обозначенный таким именем, может обладать общим набором операций [66]. Противоположностью полиморфизма является мономорфизм (monomorphism), присущий всем языкам программирования, предусматривающим сильный и статический контроль типов. Полиморфизм является одним из наиболее мощных свойств объектно-ориентированных языков программирования, уступая по степени важности лишь поддержке абстракции. Именно полиморфизм отличает объектно-ориентированное программирование от традиционного программирования с абстрактными типами данных. Как будет показано в следующих главах, полиморфизм является центральным понятием в объектно-ориентированном проектировании. Параллелизм Существуют задачи, решая которые, автоматические системы должны обрабатывать много разных событий одновременно. Кроме того, решение некоторых задач требует вычислительной мощности, превышающей ресурсы одного процессора. В таких случаях естественно рассмотреть возможность использования сети распределенных компьютеров или перейти в многозадачный режим. Отдельный процесс — это источник независимого динамического действия внутри системы. Каждая программа имеет по крайней мере один поток управления, но в парал-
98 Часть I. Концепции дельной системе имеется много таких потоков: как кратковременные, так и долгосрочные. Реальная параллельность достигается только на многопроцессорных системах, а системы с одним процессором могут лишь имитировать параллельность за счет алгоритма разделения времени. Параллелизм позволяет различным объектам действовать одновременно Кроме того, следует различать "тяжеловесный" (heavyweight) и "легковесный" (lightweight) параллелизм. Тяжеловесные процессы обычно управляются операционной системой независимо от других и могут иметь свое собственное адресное пространство. Легковесные процессы совместно существуют в рамках отдельной операционной системы, используя одно и то же адресное пространство. Связь между тяжеловесными процессами, как правило, реализуется посредством межпроцессорного взаимодействия, которое является слишком затратным. Связь между легковесными процессами требует меньшего расхода ресурсов и часто реализуется с помощью общего набора данных. Создание крупного программного обеспечения — довольно трудная задача сама по себе, а разработка параллельной системы, в которой существуют несколько потоков управления, — еще сложнее, поскольку необходимо решать задачи, связанные с взаимной блокировкой (deadlock), активными тупиками (livelock), зависанием процессов (starvation), взаимным исключением доступа (mutual exclusion) и конкуренции между процессами (race condition). "На высшем уровне абстракции объектно-ориентированное программирование может ослабить проблему параллельности для большинства программистов, скрыв ее внутри повторно используемых абстракций" [67]. Блэк (Black) и соавторы развили эту мысль, заявив, что "объектная модель вполне приемлема для распределенных систем, поскольку
Глава 2. Объектная модель 99 неявно она определяет 1) единицы распределения и движения и 2) взаимосвязанные сущности" [68]. В то время как объектно-ориентированное программирование сосредоточивает внимание на абстракции, инкапсуляции и наследовании данных, параллелизм делает акцент на абстракции и синхронизации процессов [69]. Объект — это понятие, объединяющее две точки зрения: каждый объект (построенный на основе абстракции реального мира) может представлять собой отдельный поток управления (абстракцию процесса). Такой объект называется активным (active). Система, построенная на основе объектно-ориентированного проектирования, может быть представлена как совокупность взаимодействующих объектов, часть из которых является активной и независимой от других. Следуя этому подходу, можно сформулировать такое определение параллелизма. Параллелизм — это свойство, отличающее активные объекты от пассивных. Примеры параллелизма Рассмотрим датчик ActiveTemperatureSensor, который периодически измеряет температуру и сообщает клиенту о том, что она отклонилась от установленного значения на определенное количество градусов. Несмотря на то что реализация этого класса пока неизвестна, очевидно, что здесь требуется параллелизм. Существуют три подхода к параллелизму в объектно-ориентированном проектировании. Во-первых, параллелизм — это внутреннее свойство некоторых языков программирования, имеющих механизмы параллельности и синхронизации. В данном случае можно создать активный объект, выполняющий некий процесс параллельно с другими объектами. Во-вторых, можно использовать библиотеку классов, реализующих какую-нибудь разновидность легковесных процессов. Естественно, такая реализация сильно зависит от платформы, хотя интерфейс библиотеки может быть универсальным. В этом случае параллелизм не является частью языка программирования (благодаря этому он не перегружает непаралелльные системы), а лишь выглядит таким, поскольку присутствует в стандартных классах. В-третьих, параллелизм можно имитировать с помощью прерываний. Разумеется, для этого необходимы определенные знания низкоуровневого аппаратного обеспечения. Например, в реализации класса ActiveTemperatureSensor можно предусмотреть аппаратный таймер, периодически прерывающий выполнение приложения для того, чтобы все датчики измерили текущую температуру и активизировали свои функции обратного вызова. Независимо от выбранного подхода включение параллелизма порождает проблему синхронизации работы как активных, так и последовательных объектов.
100 Часть I. Концепции Например, если два объекта пытаются послать сообщения третьему, необходимо использовать определенный механизм взаимной блокировки, гарантирующий, что объект, на который направлено действие, не будет разрушен при одновременной попытке двух активных объектов изменить его состояние. Для решения этой проблемы необходимо использовать идеи абстракции, инкапсуляции и параллелизма. В параллельных системах недостаточно определить методы объекта — необходимо также принять меры для сбережения семантики этих методов в присутствии нескольких потоков управления. Персистентность Любой программный объект занимает определенный объем памяти и существует определенное время. Аткинсон (Atkinson) и соавторы считают, что множество способов существования объектов неисчерпаемо: от промежуточных объектов, возникающих лишь во время вычисления выражений, до постоянных баз данных, существующих даже после завершения работы программы. Персистентность 3 объектов может проявляться в разном виде. Промежуточные результаты вычисления выражений. • Локальные переменные в вызове процедур. • Собственные переменные (как в ALGOL-60), глобальные переменные и динамические данные, экстент (extent) которых не совпадает с их областью видимости. • Данные, сохраняющиеся между разными сеансами выполнения программы. • Данные, сохраняющиеся при переходе от одной версии программы к другой. • Данные, существующие после исчезновения программы [70]. Первые три вида персистентности характерны для традиционных языков программирования, а последние — для баз данных. Этот конфликт технологий иногда приводит к неожиданным архитектурным решениям: программисты разрабатывают специальные схемы для хранения объектов, состояние которых должно сберегаться в период между запусками программы, а конструкторы баз данных вынуждены использовать свою технологию для управления промежуточными объектами [71]. 3 Слово persistence очень многозначно, поэтому часто переводится по-разному — то как устойчивость, то как сохраняемость. И то, и другое не совсем верно, поскольку в первом случае возникает иллюзия, что речь идет о прочности объектов, а во втором — о возможности его сохранения на запоминающих устройствах. Данное в тексте определение абсолютно точно указывает на то, что это слово означает сохранение эффекта после устранения вызвавшей его причины. Это явление называется персистентностью. — Примеч. ред.
Глава 2. Объектная модель 101 Объекты, которые Аткинсон и его соавторы назвали "данными, существующими дольше программы", нашли интересное применение при создании Web- приложений, которые могут не иметь связи с источником данных, используемых на протяжении всего периода выполнения транзакции. Какие изменения могут произойти с данными, предоставленными клиентскому приложению или Web- сервису, не имеющими связи с источником данных, и как решить эту задачу? Для реализации таких распределенных и несвязных сценариев были разработаны особые технологии, такие как ActiveXData Object для среды .NET (ADO .NET) компании Microsoft. Сочетание параллелизма и объектов привело к созданию параллельных объектно-ориентированных языков программирования. Точно также внедрение принципа персистентности в объектную модель привело к появлению объектно-ориентированных баз данных. На практике подобные базы данных создаются с помощью проверенных временем технологий — последовательных, индексированных, иерархических, сетевых или реляционных моделей, но наряду с этим программисты могут использовать абстракцию объектно-ориентированного интерфейса, позволяющего выполнять запросы к базе данных и другие операции над объектами объектов, время жизни которых превосходит время жизни отдельной программы. Такое сочетание разных подходов значительно упрощает разработку отдельных видов приложений. В частности, это позволяет применить одни и те же методы проектирования к сегментам программы, одни из которых связаны с базами данных, а другие — нет. Некоторые объектно-ориентированные языки программирования непосредственно поддерживают персистентность. Например, язык Java поддерживает технологии Enterprise Java Beans (EJBs) и Java Data Objects. В языке Smalltalk существуют протоколы для записи объектов на диск и считывания их с диска. Однако записывать объекты в обычные файлы довольно наивно. Этот способ плохо масштабируется. Иногда персистентность обеспечивается за счет коммерческих объектно-ориентированных баз данных [72]. Однако намного чаще для этого используются объектно-ориентированные оболочки реляционных баз данных. Объектно- реляционные базы данных могут создавать также индивидуальные разработчики. Однако это очень непростая задача. Для облегчения ее решения появились специальные интегрированные среды, такие как Hibernate, распространяемые с открытым текстом [76]. Персистентность относится не только к продолжительности существования данных. В объектно-ориентированных базах данных после завершения работы сохраняются не только объекты, но и классы, чтобы все программы могли интерпретировать сохраненное состояние единообразно. Очевидно, что это затрудняет поддержку целостности базы данных по мере ее увеличения, особенно если класс объекта необходимо изменить.
102 Часть I. Концепции Персистентность — это свойство сохранять состояние и класс объекта во времени и пространстве До сих пор персистентность рассматривалась как способ существования объектов во времени. Это объясняется тем, что в большинстве систем однажды созданный объект занимает постоянный объем памяти, пока не будет уничтожен. Однако в распределенных системах персистентность можно рассматривать как способ существования объектов в пространстве. В таких системах полезно рассматривать объекты, которые могут перемещаться с одной машины на другую, изменяя свое представление. Итак, можно сформулировать следующее определение персистентности. Персистентность — это способность объекта преодолевать временные рамки (т.е. продолжать свое существование после исчезновения своего создателя) или пространственные пределы (т.е. выходить за пределы своего первоначального адресного пространства). 2.4 Применение объектной модели Как указывалось ранее, объектная модель принципиально отличается от традиционных методов структурного анализа, проектирования и программирования. Это не означает, что объектная модель отбрасывает все испытанные временем
Глава 2. Объектная модель 103 принципы и накопленный опыт. Скорее, она обогащает существующие модели новыми элементами. Таким образом, объектная модель обеспечивает ряд существенных преимуществ, которые невозможно достичь в рамках других моделей. Наиболее важно то, что объектная модель позволяет создавать системы, у которых есть пять признаков хорошо структурированных сложных систем, перечисленных в главе 1: иерархическая структура, относительность выбора элементарных компонентов (например, несколько уровней абстракций), разделение функций, общая структура и устойчивые промежуточные формы. Опыт показывает, что объектная модель имеет еще пять практических преимуществ. Преимущества объектной модели Во-первых, объектная модель позволяет эффективно использовать выразительные возможности объектных и объектно-ориентированных языков программирования. Страуструп (Stroustrup) утверждает: "Не всегда понятно, как наилучшим образом использовать преимущества такого языка, как C++. Существенно повысить эффективность и качество кода можно просто за счет использования C++ в качестве "улучшенного С" с элементами абстракции данных. Однако гораздо более значительным достижением является использование иерархии классов в процессе проектирования. Именно это называется объектно-ориентированным проектированием и именно здесь язык C++ позволяет достичь наибольших результатов" [73]. Опыт показывает, что отказ от объектной модели приводит к игнорированию или неправильному использованию наиболее мощных средств таких языков программирования, как Smalltalk, C++ и Java. Во-вторых, использование объектного подхода стимулирует повторное использование не только кода, но и проектных решений [74]. Объектно-ориентированные системы компактнее, чем их традиционные эквиваленты. Компактность означает не только уменьшение размера программ, но и удешевление и ускорение проекта за счет повторного использования проектных решений. Однако повторное использование кода, как правило, не возникает само по себе, если оно не было основной целью проекта. Кроме того, первоначальная разработка кода, предназначенного для повторного использования, может оказаться более дорогой, чем обычно. Однако эти первоначальные затраты впоследствии будут компенсированы за счет экономии средств и времени при использовании в новых проектах. В-третьих, использование объектной модели приводит к созданию систем с устойчивыми промежуточными формами, что упрощает их изменение. Это позволяет улучшать систему со временем, не прибегая к ее полной переделке при первой же серьезной модификации. В-четвертых, как показано в главе 7, объектная модель уменьшает риски, связанные с проектированием сложных систем. Прежде всего, этому способствует то, что процесс объединения компонентов системы в одно целое растягивается на
104 Часть I. Концепции весь период ее разработки, а не является единовременным событием. Объектный подход к проектированию подразумевает разумное разделение функций, что также уменьшает степень риска и повышает уверенность в правильности принимаемых решений. Наконец, объектная модель учитывает особенности процесса познания. Робсон (Robson) утверждает: "Многие люди, не имеющие представления о работе компьютера, считают объектно-ориентированные системы вполне естественными" [75]. Нерешенные вопросы Для того чтобы эффективно использовать объектный подход, необходимо ответить на следующие вопросы. • Что такое классы и объекты? • Как правильно идентифицировать классы и объекты, относящиеся к конкретному приложению? • Как выбрать правильную систему обозначений для описания проекта объектно-ориентированной системы? • Как создать хорошо структурированные объектно-ориентированные системы? • Как организовать управление объектно-ориентированным проектом? Резюме • Развитие технологии привело к созданию методов объектно-ориентированного анализа, проектирования и программирования, позволяющих создавать крупномасштабное программное обеспечение. • Существует несколько парадигм программирования: процедурно-ориентированная, объектно-ориентированная, логико-ориентированная, ориентированная на правила и ориентированная на ограничения. • Абстракция выделяет существенные характеристики объекта, отличающие его от всех других видов объектов и, таким образом, проводит четкие концептуальные границы объекта с точки зрения наблюдателя. • Инкапсуляция — это процесс выделения элементов абстракции, образующих ее структуру и поведение; инкапсуляция позволяет отделить контрактный интерфейс абстракции от ее реализации. • Модульность — это свойство системы, разложенной на целостные и слабо связанные между собой модули.
Глава 2. Объектная модель 105 • Иерархия — это ранжирование или упорядочение абстракций. • Контроль типов — это система правил, предотвращающих или сильно ограничивающих взаимную замену объектов разных классов. • Параллелизм — это свойство, отличающее активные объекты от пассивных. • Персистентность — это способность объекта преодолевать временные или пространственные пределы.
ГЛАВА 3 КЛАССЫ И ОБЪЕКТЫ Как инженер, так и художник должны хорошо знать материал, с которым они работают. Масляные и акварельные краски, сталь и алюминий, болты и гвозди, объекты и классы — предназначение этих материалов сходно между собой (например, болты и гвозди являются крепежными средствами), но каждый из них имеет свои особенности и способы использования. Архитектор может не знать, как правильно забивать гвозди (это относится к сфере компетенции плотника), но он должен понимать, когда следует использовать гвозди, а когда — болты, клей или сварку. Попытка игнорировать эти фундаментальные правила может привести к катастрофическим результатам. Основными конструктивными элементами в объектно-ориентированном анализе и проектировании сложных систем программного обеспечения являются классы и объекты. Поскольку в предыдущих главах приведено лишь неформальное определение этих двух элементов, настало время подробно изучить природу классов и объектов, взаимоотношения между ними, а также сформулировать несколько эмпирических правил проектирования качественных абстракций и механизмов. 3.1 Природа объектов Способностью распознавать физические объекты человек овладевает с самого раннего возраста. Ярко окрашенный мяч привлекает внимание младенца, но, если спрятать мяч, ребенок, как правило, не пытается его искать: как только предмет покидает его поле зрения, он перестает существовать для него. Только в возрасте около года у ребенка появляется понятие о предмете (object concept): навык, чрезвычайно важный для развития его познавательных способностей в будущем. Покажите мяч годовалому ребенку и спрячьте его: скорее всего, ребенок начнет
Глава 3. Классы и объекты 107 поиски, даже не видя мяча. Следовательно, ребенок осознает, что объект обладает постоянством и отличительными особенностями независимо от действий, выполняемых над этим предметом [1]. Что является и что не является объектом? В предыдущей главе объект был неформально определен как материальная сущность, демонстрирующая четко определенное поведение. С точки зрения познавательных способностей человека, объектом может быть одна из следующих сущностей. • Материальный и (или) видимый предмет. • Сущность, поддающаяся осмыслению. • Сущность, на которую направлена мысль или действие. Таким образом, неформальное определение объекта дополняется идеей о том, что объект является частью реального мира и, следовательно, существует во времени и пространстве. В программировании термин объект впервые был применен в языке Simula и применялся для моделирования определенных аспектов реальности [2]. Объекты реального мира — не единственная разновидность объектов, представляющих интерес при проектировании систем программного обеспечения. На этапе проектирования возникают и другие важные типы объектов, взаимодействие между которыми лежит в основе механизмов, реализующих более сложное поведение [3]. Якобсон (Jucobson) и соавторы дали следующее определение управляющих объектов (control objects): "Это объекты, объединяющие в одно целое потоки событий и обеспечивающие связь между другими объектами" [43]. Более точное определение сформулировано Смитом (Smith) и Токи (Tockey): "Объект представляет собой конкретный идентифицируемый предмет, элемент или сущность, реальную или абстрактную, играющий четко определенную роль в данной предметной области" [4]. Представим себе фабрику, выпускающую композитные материалы для производства разных изделий, например, велосипедных рам и крыльев самолетов. Фабрики часто разделяются на цеха: механический, химический, электрический и т.д. Цеха подразделяются на участки, на каждом из которых установлены штампы, прессы, станки. На производственных линиях можно обнаружить множество емкостей с исходными материалами, из которых с помощью химических процессов создаются блоки композитных материалов. Затем с помощью прессов и штампов из них производятся рамы велосипедов, крылья самолетов и другие предметы. Каждый материальный предмет, упомянутый выше, может рассматриваться как объект. Токарный станок имеет четко определенные границы, отличающие его от обрабатываемых на нем композитных блоков. В свою очередь, рама велосипеда
108 Часть I. Концепции имеет четкие границы, отличающие ее от производственного участка, на котором она изготовляется. Некоторые нематериальные объекты, представляющие собой события или процессы, также имеют ярко выраженные концептуальные границы. Например, химический процесс на фабрике можно интерпретировать как объект, поскольку он имеет ясную концептуальную границу, взаимодействует с другими объектами посредством упорядоченного и распределенного во времени набора операций и демонстрирует хорошо определенное поведение. Аналогично, в системе CAD/CAM, предназначенной для моделирования твердых тел, линия пересечения сферы и куба может иметь нерегулярный характер. Несмотря на то что эта линия пересечения не существует отдельно от сферы и куба, она является самостоятельным объектом с четко определенными концептуальными границами. Объект имеет состояние, демонстрирует точно определенное поведение и обладает уникальными особенностями Некоторые материальные объекты могут иметь нечеткие физические границы. В частности, к ним относятся реки, туман или толпы людей 1. Подобно тому, как человек, взявший в руки молоток, видит вокруг одни гвозди, проектировщик ]Это утверждение верно только на достаточно высоком уровне абстракции. Человек, идущий через полосу тумана, не может отличить "свой туман" от "чужого тумана". Однако, если посмотреть на карту погоды, то можно увидеть, что полосы тумана в Сан-Франциско и в Лондоне представляют собой совершенно разные объекты.
Глава 3. Классы и объекты 109 с объектно-ориентированным мышлением начинает понимать, что мир состоит из объектов. Разумеется, такой взгляд немного наивен, поскольку совершенно очевидно, что некоторые сущности объектами не являются. К их числу относятся, например, атрибуты, такие как красота или цвет, а также эмоции, например, любовь или гнев. С другой стороны, потенциально все перечисленные сущности являются свойствами объектов. Например, можно говорить о том, что некий человек (объект) любит свою жену (другой объект), или что конкретный кот (еще один объект) имеет серую масть. Таким образом, объект — это нечто, имеющее четко определенные границы, но этого недостаточно, чтобы отделить один объект от другого или судить о качестве абстракции. Таким образом, можно дать следующее эмпирическое определение объекта. Объект обладает состоянием, поведением и индивидуальностью. Структура и поведение схожих объектов определяется в общем для них классе. Термины экземпляр и объект являются синонимами. Рассмотрим понятия состояния, поведения и индивидуальности объекта. Состояние Рассмотрим торговый автомат, отпускающий безалкогольные напитки. Как правило, после того как покупатель бросит монету и нажмет кнопку, такой объект выдает выбранный напиток. Что произойдет, если покупатель сначала нажмет кнопку выбора напитка, а потом опустит монету? Большинство автоматов при этом просто возвращают монету и ничего не делают, так как пользователь нарушил основные правила их работы. Иначе говоря, автомат находился в определенном состоянии (ожидал монету), которое пользователь проигнорировал (нажав кнопку выбора в неподходящий момент). Предположим теперь, что покупатель не обратил внимание на предупреждающий сигнал "Без сдачи" и опустил в автомат лишнюю монету. В большинстве случаев автоматы недружелюбны к покупателям и с удовольствием проглатывают лишние деньги. В каждой из таких ситуаций на поведение объекта влияет его предыстория, т.е. последовательность совершаемых над ним действий. Такая зависимость поведения от событий и времени объясняется тем, что объект имеет внутреннее состояние. Например, одно из основных состояний торгового автомата определяется суммой денег, опущенных покупателем до нажатия кнопки выбора. Другое важное свойство автомата определяется количеством сдачи и напитков, имеющихся в его распоряжении. Этот пример позволяет сформулировать следующее определение.
no Часть I. Концепции Состояние объекта характеризуется перечнем всех (как правило, статических) свойств данного объекта и текущими (как правило, динамическими) значениями каждого из этих свойств. Одним из свойств торгового автомата является способность принимать монеты. Это статическое (фиксированное) свойство, т.е. оно представляет собой существенную характеристику торгового автомата. С другой стороны, этому свойству соответствует динамическое значение, характеризующее количество монет, принятых в данный момент времени. Эта сумма увеличивается, когда покупатель опускает монеты в автомат, и уменьшается, когда кассир забирает деньги из автомата. В некоторых случаях значения свойств объекта могут быть статическими, поэтому в определении использован термин "как правило, динамическими". Например, заводской номер торгового автомата является как статическим свойством, так и статическим значением. Свойствами объекта называются отличительные характеристики, черты, качества или особенности, обеспечивающие его уникальность. Например, для лифта характерным является то, что он перемещается только вверх и вниз, а не в горизонтальном направлении. Свойства, как правило, являются статическими, поскольку они образуют неизменяемую природу объекта. Оговорка "как правило" означает, что в некоторых ситуациях свойства объекта могут изменяться. Рассмотрим в качестве примера автономный робот, обладающий возможностью самостоятельного изучения окружающей среды. Сначала он рассматривает объект как фиксированный барьер, а затем, после самообучения, обнаруживает, что это дверь, которую можно открыть. В этом случае по мере получения новых знаний концептуальная модель мира, создаваемая роботом, приобретает новые свойства. Все свойства имеют значения, которые могут быть простыми количественными характеристиками или обозначать другой объект. Например, состояние лифта может описываться числом 3, означающим номер текущего этажа. С другой стороны, состояние торгового автомата описывается в терминах других объектов, например, имеющихся в наличии безалкогольных напитков. Конкретные напитки, по существу, являются самостоятельными объектами. Их свойства отличаются от свойств торгового автомата (например, запас напитков может закончиться, а автомат не прекращает свое существование). Кроме того, над напитками и торговым автоматом выполняются разные операции. Таким образом, объекты и простые значения отличаются друг от друга: простые количественные характеристики (например, число 3) "не зависят от времени, не изменяются и не принимают других значений", тогда как объекты "существуют во времени, изменяются, имеют состояние, принимают разные значения, а также могут создаваться, уничтожаться и использоваться совместно" [6].
Глава 3. Классы и объекты 111 Тот факт, что каждый объект имеет состояние, означает, что любой объект занимает определенный объем пространства (физического или в памяти компьютера). Все объекты в системе инкапсулируют некое состояние, и все состояния в системе инкапсулируются объектами. Инкапсуляция состояния объекта — это необходимое, но не достаточное условие полного описания предназначения абстракции, выявленной на этапе проектирования (см. пример 3.1). Пример 3.1. Рассмотрим абстракцию досье на сотрудника. На рис. 3.1 показана абстракция, описанная в виде класса с помощью унифицированного языка моделирования UML. (Подробное описание системы обозначений UML изложено в главе 5.) Social Seturtty Number Department Salary Рис. 3.1. Основные иерархии сложных систем Каждый компонент абстракции обозначает конкретное свойство досье сотрудника. Эта абстракция не является объектом, поскольку она не представляет собой конкретный экземпляр досье. Конкретизируя эту абстракцию, можно создать два разных объекта, например, Тот и Kaitlyn, занимающих определенный объем памяти (см. рис. 3.2). Каждый из этих объектов занимает свою собственную область памяти, хотя они очень похожи. Следовательно, их состояния имеют общее представление. Employ.. Name, ^Tom Social Security Number Department Salary- Name - Kaitlyn Social Security Number Department Salary Рис. З.2. Объекты Tom и Kaitlyn На практике принято инкапсулировать состояние объекта, а не открывать его для всех сущностей. С учетом сказанного изменим абстракцию (класс) следующим образом (см. рис. 3.3). Эта абстракция ненамного сложнее предыдущей, но по ряду соображений гораздо предпочтительнее. В частности, ее внутренняя реализация скрыта от внешних клиентов (т.е. защищена, что обозначается символом #). Если представление
112 Часть I. Концепции Employee # Nemo # Social Security Number \U Department # Salary l· Get employee Name() ■ι Get Employee Social Security Number() [■» Get Employee Department!) Рис. З.З. Класс Employee с защищенными атрибутами и открытыми операциями абстракции будет изменено, то придется повторно скомпилировать часть кода, но, с семантической точки зрения, на внешних клиентов это изменение никак не повлияет (иначе говоря, существующий код останется неизменным). Кроме того, в данном представлении решена проблема занимаемой объектом памяти за счет явного определения операций (обязанностей), которые клиенты могут выполнять над объектами данного класса. В частности, все клиенты имеют право узнать имя, номер карточки социального обеспечения и место работы сотрудника (открытые операции обозначены символом +). Средства доступа к компонентам абстракции (т.е. открытые, защищенные, закрытые и упакованные разделы и пакет) рассматриваются далее. Поведение Ни один объект не существует в изоляции от других. Все объекты либо подвергаются воздействию, либо сами воздействуют на другие объекты. Таким образом, можно дать следующее определение. Поведение — это действия и реакции объекта, выраженные через изменения состояния объекта и передачу сообщений. Иначе говоря, поведение объекта — это его видимая извне деятельность. Операцией называется определенное воздействие одного объекта на другой с целью вызвать некую реакцию. Например, клиент может активизировать операции append и pop, чтобы увеличить или уменьшить объект-очередь. Кроме того, выполнив операцию length, клиент может определить размер очереди, но не может изменить ее состояние. В языке Java операции, которые может выполнить клиент, называются методами. Используя терминологию языков, являющихся наследниками процедурно- ориентированных языков программирования, например, языка C++, говорят, что один объект вызывает функцию-член другого. В чистых объектно-ориентированных языках, таких как Smalltalk, это явление описывается как передача сообщений между объектами. Сообщение — это операция, которую один объект выполняет над другим, хотя механизмы диспетчеризации сообщений и операции отличают- '"■ к Операции (обязанности)
Глава 3. Классы и объекты 113 ся друг от друга. В дальнейшем будем считать термины операция и сообщение синонимами. Передача сообщений — это лишь часть уравнения, описывающего поведение объекта, поскольку оно зависит и от его состояния. Вернемся к торговому автомату. Покупатель может сделать выбор, нажав кнопку, но реакция автомата будет зависеть от его состояния. Если клиент не опустит в него достаточную сумму, то автомат, вероятнее всего, никак не отреагирует. Если же денег достаточно, то автомат примет оплату и выполнит заказ (изменив тем самым свое состояние). Таким образом, поведение объекта зависит как от выполняемых над ним операций, так и от его состояния, причем некоторые операции косвенно изменяют состояние объекта. Концепция побочного действия позволяет сформулировать следующее определение. Состояние объекта представляет собой суммарный результат его поведения. Наиболее интересными являются объекты, не имеющие статичного поведения: их состояние описывается значениями, доступными для модификаций и запросов. Рассмотрим теперь понятие операции, ее связь с предназначением объекта и способы реализации обязанностей объекта с помощью операций. Операции Операция — это услуга, которую класс оказывает своим клиентам. На практике клиент обычно совершает над объектами операции пяти видов2. Ниже перечислены три наиболее распространенных вида операции. • Модификатор: операция, изменяющая состояние объекта. • Селектор: операция, имеющая доступ к состоянию объекта, но не изменяющая его. • Итератор: операция, обеспечивающая доступ ко всем частям объекта в строго определенном порядке. Два остальных вида операций носят общий характер. Они образуют инфраструктуру, необходимую для создания и уничтожения экземпляров класса. • Конструктор: операция, создающая объект и/или инициализирующая его состояние. • Деструктор: операция, стирающая состояние объекта и/или уничтожающая сам объект. 2Липпман (Lippman) предложил несколько иную классификацию: функции управления, функции реализации, вспомогательные функции (все виды модификаторов) и функции доступа (эквиваленты селекторов) [6].
114 Часть I. Концепции В языке C++ конструктор и деструктор являются частью определения класса, а в языке Java есть конструкторы, но нет деструкторов. В языке Smalltalk эти операции обычно образуют часть протокола метакласса (т.е. класса классов). Роли и обязанности Совокупность всех методов, связанных с конкретным объектом, образует его протокол. Таким образом, протокол объекта описывает поведение объекта и содержит все его статические и динамические свойства. Работая со сложными абстракциями, полезно разделять протокол на логические группы свойств. Эти свойства описывают роли, которые может исполнять объект. Роль — это маска, которую носит объект [7]. Она определяет контракт абстракции с ее клиентами. Объекты могут играть несколько ролей "Обязательства объекта выражают смысл его предназначения и место в системе. Обязательства — это совокупность всех услуг, предусмотренных во всех контрактах" [8]. Иначе говоря, можно сказать, что состояние и поведение объекта совместно определяют исполняемые им роли, а те, в свою очередь, обеспечивают выполнение обязанностей данной абстракции. Действительно, подавляющее большинство интересных объектов исполняют на протяжении своего существования самые разные роли. Рассмотрим следующие примеры [9]:
Глава 3. Классы и объекты 115 • Банковский счет может играть роль денежного актива, а его владелец может класть деньги на счет и снимать деньги со счета. С другой стороны, для налоговой инспекции этот счет может играть роль некоей сущности, которая должна каждый год отчитываться о начисленных дивидендах. • Для фондового брокера пакет акций представляет собой сущность, которую можно купить или продать, а для адвоката — это юридический инструмент, предоставляющий определенные права. • В течение дня один и тот же человек может играть роль матери, врача, садовника и кинокритика. Роли объекта носят динамический характер, но могут быть и взаимоисключающими. Например, роли пакета акций немного перекрываются, но по отношению к клиенту они являются статическими. Роли людей являются динамическими и со временем могут изменяться. На протяжении своего существования объекты могут играть несколько ролей
116 Часть I. Концепции Как будет показано в следующих главах, анализ часто начинается с изучения разных ролей, которые играет объект. Во время проектирования они уточняются с помощью конкретных операций, реализующих обязанности, связанные с каждой ролью. Объекты как автоматы Наличие внутреннего состояния объектов означает, что порядок выполнения операций имеет большое значение. Это обстоятельство наводит на мысль представить объект в качестве маленького независимого автомата [10]. Действительно, для ряда объектов временное расписание событий настолько важно, что наилучшим способом их формального описания является эквивалентный конечный автомат. В главе 5 будет введена система обозначений для описания иерархических конечных автоматов, с помощью которой можно выразить соответствующую семантику. Продолжая аналогию, можно разделить объекты на активные и пассивные. Активный объект имеет собственный поток управления, в отличие от пассивного. Активные объекты обычно автономны, т.е. могут демонстрировать определенное поведение без воздействия со стороны других объектов. Пассивные объекты, наоборот, могут изменять свое состояние только под воздействием других объектов. Таким образом, активные объекты системы — это источники управляющих воздействий (roots of control). Если в системе существуют несколько потоков управления, то в ней обычно действуют несколько активных объектов. С другой стороны, в последовательных системах в каждый момент времени существует, как правило, только один активный объект, например, диспетчер, распределяющий сообщения. В таких архитектурах все остальные объекты являются пассивными, а их поведение изменяется только тогда, когда они получают сообщение от активного объекта. В последовательных архитектурах другого типа (например, в системах обработки транзакций) нет явного центра активности, и управление распределено среди пассивных объектов системы. Индивидуальность Хошафян (Khoshafian) и Коуплэнд (Copeland) предложили следующее определение индивидуальности: "Индивидуальность — это свойство объекта, отличающее его от всех других объектов" [11]. Они отмечают, что "в большинстве языков программирования и языков, ориентированных на работу с базами данных, для различения временных объектов используются имена переменных, что приводит к смешению адресуемости и индивидуальности. Большинство баз данных постоянные объекты различают по ключам, что приводит к смешению значения и индивидуальности". Невозмож-
Глава 3. Классы и объекты 117 ность отличить имя объекта от самого объекта является источником множества ошибок в объектно-ориентированном программировании. Важность поддержки индивидуальности создаваемых объектов и легкость ее невозвратимой утери демонстрируется в примере 3.2. Пример 3.2. Рассмотрим класс, описывающий экранный объект. Это абстракция довольно типична для систем с графическим интерфейсом (GUI). Она является базовым классом для всех объектов, которые можно отображать в окне, и описывает поведение всех таких объектов. Клиенты обычно рисуют, выбирают и перемещают объекты, а также запрашивают их состояние и местоположение. Предположим, что в программе создано несколько экземпляров класса Display Item, как показано на рис. 3.4 а. В частности, будем считать, что четыре экземпляра класса расположены в четырех разных местах памяти, имеющих имена iteml, item2, item3, item4. Пусть iteml — имя объекта класса Dis- playltem, а три других — указатели на объект класса Displayltem, причем указатели item2 и item3 действительно указывают на разные объекты класса Displayltem (так как их объявление сопровождается размещением объекта Displaltem в памяти), а указатель item4 не ссылается на реальный объект. Более того, объекты, на которые ссылаются указатели item2 и item3, являются безымянными, так что на них можно ссылаться только косвенно — с помощью разыменования указателей. Уникальная индивидуальность (но не обязательно уникальное имя) каждого объекта сохраняется на протяжении всего периода его существования, даже если его состояние изменяется. Это напоминает вопрос Зенона (Zenon) о реке: изменяется ли река каждый день, даже если в ней никогда не течет одна и та же вода? Попробуем переместить, например, объект iteml. Мы можем обратиться к объекту item2, определить его местоположение и переместить объект iteml на то же самое место. Точно так же, присвоив указателю item4 значение указателя item3, можно ссылаться на объект, на который ранее ссылался указатель item3, с помощью указателя item4. Используя указатель item4, этот объект можно переместить в новое место, например, X = 38, Υ = 100. Результат показан на рис.3.4 б. Как видим, объект iteml и объект, на который ссылается указатель item2, имеют одинаковые состояния, а указатели item3 и item4 ссылаются на один и то же объект. Обратите внимание на то, что мы говорим "объект, на который ссылается указатель item2", а не "объект item2". Первое выражение более точно, хотя иногда эти фразы используются как синонимы. Несмотря на то что объект iteml и объект, на который ссылается указатель item2, имеют одинаковое состояние, они остаются разными объектами. Кроме того, состояние объекта, на который ссылается указатель item3, было изменено с помощью его нового косвенного имени item4. Эта ситуация называется струк-
118 Часть I. Концепции а) item 2 item3 item 4 item 1 X=0 Y=0 X=75 Y=75 X=100 Y=100 6) item 2 item3 item 4 item 1 X=75 Y=75 X=75 Y=75 X=38 Y=100 в) item 2 item3 item 4 item 1 X=75 Y=75 X=75 Y=75 X=38 Y=100 Рис. З.4. Индивидуальность объекта турным разделением (structural sharing) и означает, что объект может именоваться по-разному. Иначе говоря, объект может иметь псевдонимы. Структурное разделение порождает много проблем в объектно-ориентированном программировании. Трудность распознавания побочных эффектов при обращении к объекту через псевдонимы часто приводит к "утечкам памяти", нарушению правил доступа к памяти, и, что еще хуже, непредсказуемому изменению состояния. Например, если уничтожить объект, на который ссылается указатель item3, то значение указателя item4 окажется бессмысленным. Такая ситуация называется висячей ссылкой (gangling reference). Рассмотрим рис. 3.4 в, иллюстрирующий результат изменения значения указателя item2 так, чтобы он ссылался на объект item2. Теперь указатель item2 ссылается на объект iteml. К сожалению, при этом произошла утечка памяти — объект, на который первоначально ссылался указатель item2, больше не именуется ни прямо, ни косвенно, и его индивидуальность потеряна. В таких языках
Глава 3. Классы и объекты 119 программирования, как Smalltalk и Java, память, выделенная для подобных объектов, уничтожается механизмом "сборки мусора". В языках типа C++ утерянная память не освобождается, пока не завершится программа, создавшая объект. Такие утечки памяти могут вызвать и простое неудобство, и крах, особенно если программа должна непрерывно работать длительное время3. 3.2 Отношения между объектами Сами по себе объекты совершенно не интересны. Поведение системы определяется лишь взаимодействием между объектами. "Вместо процессоров, бесцеремонно расхватывающих структуры данных, мы имеем дело с благонравными объектами, вежливо просящими друг друга об услугах" [12]. Рассмотрим, например, объектную структуру самолета, представляющего собой "совокупность элементов, стремящихся упасть на землю и не падающих на нее лишь благодаря постоянным усилиям и контролю" [13]. Только взаимодействие между компонентами самолета позволяет ему летать. Отношения между двумя объектами основываются на взаимных предположениях о допустимых операциях и ожидаемом поведении. Особый интерес для объектно-ориентированного анализа и проектирования представляют два типа отношений между объектами: • связи; • агрегация. Связи Термин связь (link) заимствован из работы Рамбо (Rumbaugh) и соавторов, определивших его как "физическое или концептуальное соединение между объектами" [14]. Объект сотрудничает с другими объектами, используя связи с ними. Иначе говоря, связь — это конкретное соединение, через которое объект (клиент) запрашивает услугу у другого объекта (сервера) или управляет им. На рис. 3.5 продемонстрированы несколько разных связей. Линия, соединяющая две пиктограммы, которые соответствуют объектам, обозначает существование связи между ними и передачу сообщений от одного к другому. Сообщение изображается в виде маленькой стрелочки, указывающей направление передачи, с меткой, представляющей собой его содержание. Например, на рис. 3.5 показан фрагмент упрощенной схемы управления потоком жидкости в заводской трубе. 3Представьте себе утечку памяти в программе управления спутником или кардиостимулятором. Перезапуск компьютера на спутнике в нескольких миллионах километров от Земли очень неудобен. Аналогично, непредсказуемая сборка мусора в программе, управляющей кардиостимулятором, может оказаться смертельной для пациента. В таких случаях разработчики систем реального времени предпочитают воздерживаться от динамического распределения памяти.
120 Часть I. Концепции Как видим, объект FlowController имеет связь с объектом Valve. В свою очередь, объект Valve имеет связь с объектом DisplayPanel, отражающим его состояние. Передача сообщений может осуществляться только в направлении связи. 1 у**» 1 td)Urt J FlcwCemelUr ] *****} Рис. 3.5. Связи Передача сообщений между объектами обычно носит односторонний характер, хотя иногда она бывает двусторонней. В нашем примере объект Flow- Controller выполняет операции над объектами Valve (чтобы изменить его настройки) и DisplayPanel (чтобы изменить текст, который он отображает). Однако оба эти объекта не воздействуют на объект FlowController. Это разделение обязанностей является довольно типичным для хорошо структурированных объектно-ориентированных систем. Несмотря на то что сообщение создается клиентом (FlowController) и направляется серверу (Valve), данные могут передаваться в обоих направлениях связи. Например, объект FlowController выполняет над объектом Valve операцию adjust и данные (т.е. изменяемая настройка) передаются от клиента к серверу. Однако, если объект FlowController выполнит над объектом Valve операцию isClosed, то результат (т.е. индикатор закрытого положения трубы) будет передан от сервера к клиенту. Участвуя в связи, объект может выполнять одну из следующих трех ролей: • Контроллер (controller). Этот объект может выполнять операции с другими объектами, но сам никогда не подвергается воздействию других объектов. В некоторых предметных областях термины активный объект (active object) и контроллер являются синонимами. • Сервер (server). Этот объект не выполняет операций с другими объектами, а лишь подвергается воздействию со стороны других объектов. • Агент (proxy). Такой объект может выполнять операции над другими объектами и подвергаться воздействию с их стороны. Как правило, агенты создаются для представления реальных объектов, существующих в предметной области конкретного приложения. На рис. 3.5 объект FlowController действует как контроллер, объект DisplayPanel — как сервер, а объект Valve — как агент. В примере 3.3 показано распределение обязанностей в группе взаимодействующих объектов.
Глава 3. Классы и объекты 121 Пример 3.3. Во многих промышленных процессах требуется обеспечить пилообразное изменение температуры: поднять ее до заданного значения, выдержать в течение фиксированного периода, а затем понизить до нормального уровня. Разные процессы имеют разные профили температуры. Некоторые объекты (например, зеркало телескопа) следует охлаждать медленно, а другие (например, сталь) — быстро. Эта абстракция температурного профиля имеет четкие характеристики и может быть реализована в виде класса TemperatureRamp (рис. 3.6). Рис. 3.6. Агрегация На самом деле поведение этой абстракции представляет собой нечто большее, чем зависимость температуры от времени. Например, через 60 мин температура должна достичь уровня 250Т, а через 180 мин — 150°F. Возникает вопрос: какой должна быть температура на 120-й минуте? Для того чтобы ответить на этот вопрос, необходимо выполнить линейную интерполяцию, так что поведение абстракции должно предусматривать эту операцию. Рассмотренная абстракция не предусматривает управления нагревателем, обеспечивающего требуемый профиль температуры. Вместо этого осуществляется более глубокое разделение обязанностей, обеспечиваемых путем взаимодействия трех объектов: температурного профиля, нагревателя и контроллера (см. рис. 3.6). На первый взгляд, единственное предназначение описанной абстракции — инкапсулировать функциональную декомпозицию внутри класса, чтобы имитировать объектно-ориентированный стиль. Операция schedule опровергает это предположение. Объекты класса TemperatureController имеют достаточно информации, чтобы определить график нагрева, поэтому эту операцию можно считать дополнительным поведением абстракции. В некоторых энергоемких технологиях (например, в металлургии) нагревание представляет собой очень дорогой процесс, поэтому наряду с остыванием автоматического нагревателя необходимо учитывать остаточное тепло от предыдущей плавки. Благодаря операции schedule, клиент может поручить объекту TemperatureController определить оптимальный момент для включения нагревателя, чтобы обеспечить требуемый температурный режим.
122 Часть I. Концепции Видимость Рассмотрим два объекта А и В, между которыми существует связь. Для того чтобы объект А мог послать сообщение объекту В, необходимо, чтобы объект А имел доступ к нему. В ходе анализа задачи видимость объектов, чаще всего, можно игнорировать, но при разработке конкретной реализации системы необходимо обеспечить доступ связанных объектов друг к другу. Синхронизация Когда один объект посылает сообщение другому по линии связи, говорят, что эти объекты синхронизируются. В последовательном приложении синхронизация объектов представляет собой обычный вызов метода. Однако в многопоточных системах объекты нуждаются в более изощренных схемах передачи сообщений, чтобы разрешить проблемы взаимного исключения, типичные для параллельных систем. Как уже отмечалось, активные объекты имеют свои собственные потоки управления, поэтому другие активные объекты на их семантику, как правило, не влияют. Однако если активный объект имеет связь с пассивным, возможны три варианта синхронизации. • Последовательная (sequential). Семантика пассивного объекта в каждый момент времени обеспечивается в присутствии только одного активного процесса. • Защищенная (guarded). Семантика пассивного объекта обеспечивается в присутствии многих потоков управления, но активные клиенты должны взаимодействовать, реализуя взаимное исключение. • Параллельная (concurrent). Семантика пассивного объекта обеспечивается в присутствии многих потоков управления, причем взаимное исключение гарантируется сервером. Агрегация В то время как связи обозначают равноправные или "клиент-серверные" отношения между объектами, агрегация описывает иерархию "целое/часть" и позволяет переходить от целого (агрегата) к его компонентам. В этом смысле агрегация является частным случаем ассоциации. Например, как показано на рис. 3.6, объект TemperatureController представляет собой нечто целое, а объект Heater является его частью. Обозначения отношений агрегирования рассматриваются в главе 5. Подразумевается, что объект, представляющий собой часть другого объекта, имеет связь со своим агрегатом. Используя эту связь, агрегат может посылать сообщения своим частям. Например, объект TemperatureCont roller может посылать сообщения объекту Heater. Для того чтобы перейти от объекта Heater
Глава 3. Классы и объекты 123 к объекту, который его содержит (контейнеру), необходимо, чтобы информация о контейнере (container) была частью состояния объекта Heater. Агрегация не всегда означает, что один объект буквально включает в себя другой объект. Например, самолет физически состоит из крыльев, двигателей, шасси и прочих частей. С другой стороны, отношение акционера с его акциями — это агрегация, не означающая физическое включение. Акционер единолично владеет своими акциями, но не состоит из них. Эти отношения целое/часть носят абстрактный, а не физический характер. Между связями или агрегацией существует явный компромисс. Агрегация иногда предпочтительнее, поскольку инкапсулирует части целого, скрывая их от внешних клиентов. В других случаях, наоборот, предпочтительнее связи, поскольку они позволяют ослабить взаимоотношения между объектами. Разумное проектное решение требует тщательного анализа этих двух факторов. 3.3 Природа класса Понятия класса и объекта настолько тесно связаны, что невозможно говорить об объекте, не упоминая его класс. Однако между этими понятиями существуют важные различия. Что такое класс В то время как объект обозначает конкретную сущность, определенную во времени и в пространстве, класс представляет собой лишь абстракцию существенных свойств объекта. Таким образом, можно говорить о классе Mammal, описывающем характеристики, общие для всех млекопитающих. Для указания на конкретного представителя млекопитающих необходимо сказать "это млекопитающее" или "то млекопитающее". В словаре Webster's Third New International Dictionary дано следующее определение класса: "Группа, множество или разновидность сущностей, обладающих общими свойствами или отличающихся от других уровнем качества, степенью компетентности или состоянием" [15]. В контексте объектно-ориентированного анализа используется следующее определение класса. Класс — это множество объектов, обладающих общей структурой, поведением и семантикой. Отдельный объект является просто экземпляром класса. Что же нельзя назвать классом? Например, объект не является классом. Объекты, не имеющие общей структуры и поведения, нельзя объединить в класс, поскольку по определению они ничем не связаны между собой.
124 Часть I. Концепции Класс описывает совокупность объектов, обладающих общей структурой и одинаковым поведением Следует подчеркнуть, что класс — как определено в большинстве языков программирования — необходимый, но недостаточный инструмент декомпозиции сложных систем. Иногда абстракции так сложны, что не могут быть выражены с помощью одного описания класса. Например, на достаточно высоком уровне абстракции графический интерфейс пользователя, база данных или система учета являются объектами, которые не могут быть экземплярами одного класса4. Лучше считать их некими совокупностями классов, экземпляры которых взаимодействуют между собой, обеспечивая требуемую структуру и поведение. Страуструп (Stroustrup) называет такие кластеры компонентами [16]. Интерфейс и реализация Мейер (Meyer) [17] и Снайдер (Snyder) [18] утверждают, что программирование представляет собой "составление контракта". Большие задачи разделяются на множество мелких подобно тому, как крупный заказ распределяется среди суб- 4Разумеется, можно попытаться выразить такие абстракции с помощью одного класса, но такая детализация является слишком грубой для обеспечения повторного использования и модификации кода. Громоздкий интерфейс очень неудобен, так как большинство клиентов использует только небольшую его часть. Более того, изменение одной части огромного интерфейса требует обновления каждого из клиентов, даже если модификация интерфейса на них не влияет. Вложенные классы не решают этих проблем, а лишь откладывают их.
Глава 3. Классы и объекты 125 подрядчиков. Нигде эта идея не проявляется так очевидно, как в проектировании классов. В то время как отдельный объект является конкретной сущностью, играющей некую роль в общей системе, класс описывает структуру и поведение, общую для всех родственных объектов. Таким образом, класс — это контракт, связывающий между собой абстракцию и ее клиентов. Реализуя эти решения в интерфейсе класса, языки программирования со строгим контролем типов позволяют выявить нарушения этого контракта во время компиляции. Концепция контракта порождает различия между внешним и внутренним представлениями класса. Внешний вид класса реализуется интерфейсом, который подчеркивает абстрактный характер класса, скрывая структуру и особенности его поведения. Интерфейс, как правило, состоит из объявлений операций, применимых к его объектам, а также объявлений других классов, констант, переменных и исключительных ситуаций, необходимых для полного описания абстракции. Внутреннее представление обеспечивает реализация класса, скрывающая секретные особенности его поведения. Реализация состоит, в основном, из описания всех операций, объявленных в интерфейсе класса. Интерфейс класса можно разделить на четыре части. 1. Открытый раздел (public) — объявления, доступные всем клиентам. 2. Защищенный раздел (protected) — объявления, доступные самому классу и его подклассам. 3. Закрытый раздел (private) — объявления, доступные только самому классу. 4. Пакет (package) — объявления, доступные только классам, входящим в один и тот же пакет. В разных языках программирования используется разная семантика этих форм доступа. Константы и переменные, образующие представление класса, называются по-разному. Например, в языке Smalltalk используется термин переменная экземпляра (instance variable), в языке Object Pascal и Java — поле (field), а в языке C++ — данные-члены (data member). В дальнейшем эти термины будут использоваться как синонимы. Состояние объекта должно иметь определенное представление в соответствующем классе. Как правило, оно выражается с помощью объявлений констант и переменных, помещенных в защищенном или закрытом разделе интерфейса класса. Таким образом, представление, общее для всех экземпляров класса, инкапсулировано в нем, а его изменения не влияют на функциональные свойства всех внешних клиентов.
126 Часть I. Концепции Видимость и дружественность Разные языки программирования по-разному используют смесь открытых, защищенных и закрытых разделов, а также пакетов, устанавливая разные права доступа к интерфейсу класса и осуществляя контроль над тем, что клиент может видеть, а что нет (т.е. реализуя концепцию видимости). В частности, язык C++ позволяет программисту провести четкое различие между всеми четырьмя перечисленными уровнями доступа5. Механизм дружественных функций и классов в языке C++ позволяет классу объявлять определенные классы привилегированными, открывая им доступ к своим защищенным и закрытым разделам. Концепция дружественных классов нарушает принцип инкапсуляции, поэтому, как и в жизни, друзей надо выбирать осмотрительно. В языке Java этого механизма нет. Вместо этого язык Java реализует аналогичный тип видимости, называемый па- кетным доступом (package access). При этом все классы, входящие в один и тот же пакет, имеют доступ друг к другу. Помимо этого все остальные уровни доступа в языке Java (открытый, защищенный и закрытый) реализуются точно так же, как и в языке C++. В противоположность этому, язык Ada допускает лишь открытые и закрытые разделы, но не предусматривает защищенных. В языке Smalltalk все переменные экземпляров являются закрытыми, а все методы остаются открытыми. В языке Object Pascal все поля и операции открыты, а значит, инкапсуляция не осуществляется. Жизненный цикл класса Поведение простого класса можно понять, изучая семантику, описанную с помощью операций, объявленных в открытом разделе. Однако поведение более сложных классов (например, перемещение объекта класса Displayltem или составление расписания для экземпляра класса TemperatureControl ler) предусматривает взаимодействие разных операций, входящих в каждый из них. Как уже отмечалось, объекты таких классов действуют как маленькие автоматы. Поскольку все такие объекты ведут себя одинаково, для описания их общей семантики, упорядоченной по времени и событиям, можно использовать класс. Динамику поведения некоторых интересных классов можно описать, используя конечные автоматы (см. главу 5). 5Понятие структуры (struct) в языке C++ представляет собой особый случай в том смысле, что сущность, объявленная с помощью ключевого слова struct, является разновидностью класса, в котором доступ ко всем его элементам является открытым.
Глава 3. Классы и объекты 127 3.4 Отношения между классами Рассмотрим сходства и различия между следующими классами: цветы, ромашки, красные розы, желтые розы, лепестки и божьи коровки. Мы можем заметить следующее: • Ромашка — это цветок. • Роза — это (другой) цветок. • Красная и желтая розы — это розы. • Лепесток — это часть обоих видов цветов. • Божьи коровки питаются определенными вредителями, поражающими некоторые цветы. Из этого простого примера следует, что классы, как и объекты, не существуют изолированно. В конкретной проблемной области, как правило, ключевые абстракции взаимодействуют друг с другом, образуя структуру класса [19]. Отношения между классами устанавливаются по двум причинам. Во-первых, классы могут обладать общими свойствами. Например, ромашки и розы — это разновидности цветов, т.е. они имеют ярко окрашенные лепестки, благоухают и т.д. Во-вторых, между классами может существовать семантическая связь. Например, красные розы больше похожи на желтые розы, чем на ромашки, но в то же время у роз и ромашек больше общего, чем у цветов и лепестков. Кроме того, между цветами и божьими коровками существует симбиотическая связь: божьи коровки защищают цветы от некоторых вредителей, а сами растения служат источником пищи для божьих коровок. Существует три основных типа отношений между классами [20]. Первый тип — "обобщение/специализация" (generalization/specialization), или "is а". Например, розы — это цветы, т.е. розы являются специализированным подклассом более общего класса "цветы". Второй тип — "целое/часть" (whole/part), или "part of". Так, лепестки являются частью цветов. Третий тип — ассоциация, т.е. семантическая зависимость между классами, которые больше никак не связаны друг с другом, например, между божьими коровками и цветами. Другой пример ассоциации представляет собой отношение между розами и свечами, которые можно одновременно использовать для украшения стола. Ассоциация Среди указанных типов отношений ассоциация — наиболее абстрактное и наиболее слабое отношение. Идентификация ассоциаций между классами часто проводится на этапе анализа и ранних стадиях проектирования, когда необходимо обнаружить общие зависимости между абстракциями. На последующих этапах
128 Часть I. Концепции проектирования и реализации системы эти слабые ассоциации часто уточняются и воплощаются в виде одного из более конкретных отношений между классами. Семантические зависимости Как следует из примера 3.4, ассоциация лишь обозначает семантическую зависимость, но не указывает ее направления (по умолчанию подразумевается двухсторонняя связь) и не объясняет, как классы связаны друг с другом (их семантику можно только подразумевать, указав роли классов в этих отношениях). Однако на этапе анализа проблемы, когда требуется лишь выявить такие зависимости, этой семантики вполне достаточно. Создавая ассоциации, проектировщик фиксирует участников семантических отношений, а также их роли и количество. Пример 3.4. В описании средства передвижения основными абстракциями являются "транспортное средство" (vehicle) и "колеса" (wheels). Как показано на рис. 3.7, между классом Wheel и классом Vehicle существует простая ассоциация. (Вероятно, более точным было бы отношение агрегации.) По умолчанию эта ассоциация является двусторонней. Экземпляр класса Wheel должен однозначно идентифицировать соответствующий объект класса Vehicle, и наоборот. Рис. 3.7. Ассоциация Это пример ассоциации "один-множество" (one-to-many). Каждый экземпляр класса Wheel связан с одним экземпляром класса Vehicle, но, в свою очередь, каждый экземпляр класса Vehicle может содержать несколько объектов класса Wheel (на рис. 3.7 они обозначены звездочкой). Множественность В предыдущем примере рассмотрена ассоциация "один-множество", означающая, что каждый экземпляр класса Vehicle может содержать несколько экземпляров класса Wheel или не содержать ни одного (например, лодка, являющаяся транспортным средством, не имеет колес), в то время как каждый экземпляр класса Wheel связан только с одним экземпляром класса Vehicle. Это свойство называется множественностью ассоциации. На практике существует три разновидности множественности. 1. Взаимно-однозначная зависимость (one-to-one). 2. Зависимость "один-множество" (one-to-many). 3. Зависимость "множество-множество" (many-to-many).
Глава 3. Классы и объекты 129 Взаимно-однозначное отношение обозначает очень узкую ассоциацию. Например, в розничном телемаркетинге существует взаимно-однозначное отношение между классом Sale и классом CreditCardTransaction: каждая продажа соответствует только одной транзакции с данной кредитной карточкой, а каждая транзакция соответствует только одной продаже. Отношения "множество- множество" также распространены довольно широко. Например, каждый покупатель, т.е. экземпляр класса Customer может инициировать транзакцию с несколькими экземплярами класса Saleperson, т.е. с разными продавцами, а каждый продавец может взаимодействовать с несколькими покупателями. Как показано в главе 5, существуют разновидности указанных зависимостей. Наследование С семантической точки зрения, наследование, вероятно, является наиболее интересным среди отношений типа "обобщение/специализация". Однако опыт показывает, что одного наследования недостаточно для того, чтобы выразить все богатство отношений, существующих между основными абстракциями в исследуемой предметной области. Альтернативой наследованию является делегирование (delegation), означающее, что объект поручает реализацию своего поведения другим объектам. Пример 3.5. Находящиеся в полете космические зонды посылают на наземные станции информацию о состоянии своих основных систем (например, источников энергоснабжения и двигателей) и показания датчиков (таких как датчики радиации, масс-спектрометры, телекамеры, детекторы столкновений с микрометеоритами и т.д.). Вся совокупность передаваемой информации называется теле- метрическими данными. Как правило, они передаются в виде потока двоичных сигналов, состоящего из заголовка (включающего временные метки и ключи для идентификации последующих данных) и нескольких пакетов данных, полученных от подсистем и датчиков. Таким образом, возникает очевидная агрегация разных видов данных. Телеметрические данные необходимо защитить. В противном случае ничто не мешает клиенту изменить важные значения, например, временную метку timeStamp или значение текущей мощности currentPower. Кроме того, представление телеметрических данных открыто, так что если потребуется его изменить (например, добавить новые элементы или изменить настройку существующих), то это затронет каждого клиента. Как минимум, приходится заново компилировать все ссылки на данную структуру. Еще важнее то, что эти изменения могут не соответствовать предположениям клиентов о представлении телеметрических данных и тем самым могут разрушить логику программы. Наконец, предположим, что анализ системы выявил потребность в нескольких сотнях разновидностей телеметрических данных, включая электрические пара-
130 Часть I. Концепции Подкласс может наследовать структуру и поведение своего суперкласса метры, перечисленные выше, и результаты замеров напряжения во многих контрольных точках. Описание такого количества дополнительных структур может оказаться чрезмерно избыточным с учетом повторяемости структур и наличия общих функций обработки. Ненамного лучше было бы объявить отдельный класс для каждого вида телеметрических данных. Это позволило бы скрыть представление каждого класса и установить связь между данными и его поведением. Однако этот подход не решает проблему избыточности. Следовательно, значительно лучше построить иерархию классов, в которой специализированные классы наследуют структуру и поведение, определенные в более обобщенных классах. Класс ElectricalData наследует структуру и поведение класса Teleme- tryData. При этом он вносит добавления в структуру суперкласса (дополнительные измерения напряжения), а также уточняет (функция transmit, передающая дополнительные данные) и даже расширяет его поведение (функция current- Power, передающая величину текущей мощности). Одиночное наследование Наследование — это отношение между классами, в котором один класс повторяет структуру и поведение одного (одиночное наследование) или нескольких
Глава 3. Классы и объекты 131 Рис. 3.8. Класс ElectricalDa- ta наследует свойства суперкласса TelemetryData (множественное наследование) классов. Класс, структура и поведение которого наследуются, называется суперклассом (superclass). В примере 3.5 класс TelemetryData является суперклассом для класса Electrical Data. Класс, производный от суперкласса, называется подклассом (subclass). Следовательно, наследование устанавливает между классами иерархию "общее/частное", в которой подкласс наследует свойства одного или нескольких суперклассов. Этот признак — необходимое условие наследования. Рассмотрим два класса А и В. Если класс А не является разновидностью класса В, то класс А не может быть подклассом класса В. В этом смысле класс ElectricalData является специализированной разновидностью более общего класса TelemetryData. Способность языка поддерживать этот вид наследования отличает объектно-ориентированные языки программирования от объектных. Подкласс обычно либо расширяет, либо ограничивает существующую структуру и поведение своего суперкласса. Подкласс, дополняющий свойства своего суперкласса, использует наследование для расширения. Например, подкласс GuardedQueue может расширить поведение суперкласса Queue, дополнив его операциями защиты класса в многопоточной среде. И наоборот, подкласс Un- selectableDisplayltem ограничивает поведение своего суперкласса Display I tern, запрещая выбор объекта на экране. На практике иногда трудно понять, расширяет подкласс свой суперкласс или ограничивает. Как правило, происходит и то, и другое. На рис. 3.9 продемонстрированы отношения одиночного наследования от суперкласса TelemetryData. Стрелки обозначают отношения "is а". Например, класс Cameradata представляет собой разновидность класса SensorData, который в свою очередь является разновидностью класса TelemetryData. Аналогичный тип иерархии характерен для семантических сетей, которые часто используются специалистами по распознаванию образов и искусственному
132 Часть I. Концепции интеллекту для организации баз знаний [21]. Как показано в главе 4, правильная организация иерархии абстракций — это вопрос разумной классификации. -1 J^T Рис. 3.9. Одиночное наследование Некоторые классы, изображенные на рис. 3.9, могут иметь экземпляры. Например, наиболее вероятным является образование объектов самых специализированных классов (листьев, или конкретных классов), таких как Electrical- Data и SpectrometerData, а наименее вероятным — образование экземпляров более общих классов, занимающих промежуточное положение (SensorData и TelemetryData). Классы, экземпляры которых не создаются, называются абстрактными (abstract classes). Абстрактные классы создаются с расчетом на то, что подклассы дополнят их структуру и поведение с помощью конкретной реализации не полностью описанных методов. Между наследованием и инкапсуляцией существуют серьезные противоречия. Использование механизма наследования в значительной мере открывает подклассу секреты реализации суперкласса. На практике это означает, что понять, как работает конкретный класс, можно лишь разобравшись, как устроены его суперклассы. Наследование подразумевает, что подклассы повторяют структуры их суперклассов. В примере 3.5 экземпляры класса ElectricalData содержат данные- члены суперкласса (такие как id и time St amp), а также члены, которые наследуются более специализированными классами (такие как f uelCelllVoltage, fuelCell2Voltage, fuelCelllAmperes и fuelCell2Amperes). Подклассы также наследуют поведение суперклассов. Например, экземпляры класса ElectricalData могут выполнять операции currentTime (унаследована от его суперкласса), currentPower (определена в самом классе) и transmit (переопределена в подклассе). Полиморфизм Функция transmit, определенная в классе TelemetryData, может передавать идентификатор потока телеметрической информации и его временную мет-
Глава 3. Классы и объекты 133 ку. Та же самая функция в классе ElectricalData может вызывать функцию transmit из класса TelemetryData, передавая дополнительно величину напряжения и значения силы тока. Такое поведение обеспечивается полиморфизмом, а операции называются полиморфными (polymorphic). Полиморфизм — это концепция теории типов, согласно которому одно и то же имя может обозначать экземпляры разных классов, связанных с общим суперклассом. Таким образом, любой объект с этим именем может по-разному выполнять общий набор операций. Используя полиморфизм, одну и ту же операцию можно по-разному реализовывать в классах, образующих иерархию. В результате подкласс может расширять возможности суперкласса или замещать базовые операции, как это делал класс ElectricalData, представленный на рис. 3.5. Впервые идею полиморфизма описал Стрейчи (Strachey) [22], имея в виду возможность переопределять смысл символов, таких как "+". Эта концепция называется перегрузкой (overloading). В языке C++ можно объявить несколько функций с одним и тем же именем, которые при вызове различаются по своим сигнатурам, состоящим из различного количества и типов аргументов (в языке C++, в отличие от языка Ada, тип возвращаемого значения частью сигнатуры не считается). В противоположность этому язык Java не допускает перегрузки операторов. Кроме того, Стрейчи писал о параметрическом полиморфизме, который в настоящее время называется просто полиморфизмом. Код программы, не использующей полиморфизм, содержит множество операторов многовариантного выбора6. Без полиморфизма невозможно создать иерархию классов для разных типов телеметрических данных. В этом случае проектировщику пришлось бы создавать единую монолитную вариантную запись, содержащую все свойства, связанные со всеми типами данных. Для того чтобы отличать один вариант от другого, пришлось бы проверять дескриптор, связанный с записью. Для того чтобы создать новый тип телеметрических данных, необходимо модифицировать эту вариантную запись, добавляя новый тип в каждый оператор case в каждом экземпляре записи. Это увеличивает вероятность ошибок и делает проект неустойчивым. Наследование позволяет разделять разные виды абстракций, поэтому необходимость в монолитных типах исчезает. Каплан (Kaplan) и Джонсон (Johnson) отмечают: "Полиморфизм наиболее полезен в тех случаях, когда несколько классов имеют один и тот же протокол" [23]. Полиморфизм позволяет обойтись без 6Этот факт является тестом на полиморфизм. Присутствие оператора многовариантного выбора действий в зависимости от типа объекта часто является признаком того, что проектировщик неэффективно применяет полиморфное поведение.
134 Часть I. Концепции операторов многовариантного выбора, поскольку каждый объект неявно сам знает свой тип. Наследование без полиморфизма возможно, но не очень полезно. Полиморфизм тесно связан с механизмом позднего связывания. При полиморфизме связь метода и имени определяется только в процессе выполнения программы. В языке C++ программист имеет возможность выбирать между ранним и поздним связыванием имени с членом-функцией. В частности, если метод объявлен как виртуальный, то реализуется позднее связывание, а функция считается полиморфной. Если объявление виртуальной функции отсутствует, то используется раннее связывание и метод уточняется на этапе компиляции. В языке Java позднее связывание не требует использования ключевого слова virtual. Подробности выбора конкретного метода описаны во врезке "Вызов метода". Множественное наследование При одиночном наследовании каждый подкласс имеет только один суперкласс. Однако, как указали Влиссидес (Vlissides) и Линтон (Linton), несмотря на очевидную полезность, "одиночное наследование часто вынуждает программиста выбирать наследование от одного из двух одинаково привлекательных классов. Это ограничивает применение предопределенных классов, поэтому часто приходится дублировать код. Например, нельзя создать графический элемент, который был бы одновременно окружностью и рисунком; приходится наследовать свойства либо одного, либо другого класса, добавляя необходимые функциональные возможности отвергнутого класса" [28]. Предположим, необходимо организовать учет различных активов — сберегательных счетов, недвижимости, акций и облигаций. Банки обычно управляют двумя видами активов: текущими и сберегательными счетами. Таким образом, оба этих счета можно считать разновидностью банковских счетов, которые, в свою очередь, являются разновидностью активов. Акции и облигации отличаются от банковских счетов — они представляют собой разновидности ценных бумаг, которые также относятся к активам. С другой стороны, существует много других удобных классификаций сберегательных счетов, недвижимости, акций и облигаций. Например, в некоторых ситуациях полезно отличать активы, которые можно застраховать, например, недвижимость или определенные банковские счета (которые в США частично гарантируются Федеральной корпорацией по страхованию депозитов (Federal Deposit Insurance Corporation)). В других ситуациях иногда полезно уметь идентифицировать активы, приносящие дивиденды или процентный доход, такие как сберегательные и текущие счета, а также некоторые виды акций и облигаций. К сожалению, выразительные средства одиночного наследования не позволяют достаточно полно описать это разнообразие отношений, поэтому необходи-
Глава 3. Классы и объекты 135 Вызов метода В традиционных языках программирования вызов подпрограмм носит исключительно статический характер. Например, в языке Pascal для оператора, вызывающего подпрограмму Р, обычно генерируется код, создающий новый стек, размещающий в нем аргументы, а затем изменяющий поток управления для выполнения кода, связанного с процедурой Р. Однако в языках, поддерживающих полиморфизм, таких как Smalltalk и C++, активизация операции может осуществляться динамически, поскольку класс объекта, из которого будет вызван метод, может быть неизвестным до выполнения программы. Ситуация становится еще интереснее, если используется механизм наследования. Семантика активизации операции при использовании механизма наследования без полиморфизма совпадает с простым статическим вызовом подпрограмм, но наличие полиморфизма вынуждает программиста прибегнуть к более сложным приемам. Рассмотрим иерархию классов (рис. 3.10), в которую входят базовый класс Displayltem и три подкласса с именами Circle, Triangle и Rectangle. В свою очередь класс Rectangle имеет подкласс SolidRectangle. Предположим, что в классе Displayltem определена переменная экземпляра theCenter (задающая координаты центра изображаемого элемента), а также следующие операции: • draw Нарисовать элемент • move Передвинуть элемент • location Вернуть координаты элемента Операция location является общей для всех подклассов и не требует переопределения, но операции draw и move должны быть переопределены, поскольку только подклассы могут знать, как изображать и передвигать элементы. Класс Circle должен иметь переменную theRadius и соответствующие операции для установки и чтения значения этой переменной set и retrieve соответственно. Операция draw, переопределенная в подклассе, рисует окружность заданного радиуса с центром в точке theCenter. Аналогично, в классе Rectangle следует предусмотреть переменные theHeight и theWidth и соответствующие операции set и retrieve для установки и чтения их значений. Операция draw, переопределенная в этом подклассе, рисует прямоугольник заданной высоты и ширины с центром в заданной точке theCenter. Подкласс SolidRectangle наследует все свойства класса Rectangle, но операция draw в этом подклассе также переопределена. В частности, реализация функции draw в классе SolidRectangle сначала вызывает функцию draw, определенную в суперклассе Rectangle, а затем полученный контур заполняется цветом. Предположим, что некий клиент желает нарисовать все фигуры, реализованные в подклассах. В данном случае компилятор не может статически сгенерировать код, чтобы вызвать подходящую функцию draw, поскольку класс объектов, из которых вызывается эта функция, определяется лишь во время выполнения программы. Посмотрим, как эту задачу можно решить с помощью разных объектно-ориентированных языков программирования.
136 Часть I. Концепции Рис. ЗЛО. Диаграмма класса Displayltem Поскольку в языке Smalltalk нет типов, диспетчеризация методов является строго динамической. Когда клиент посылает сообщение draw объекту, указанному в списке, происходит следующее. • Объект ищет сообщение в словаре сообщений своего класса. • Если сообщение найдено, то вызывается код локально определенного метода. • Если сообщение не найдено, то поиск производится в словаре сообщений суперкласса. Этот процесс распространяется вверх по иерархии, пока сообщение не будет найдено или не будет достигнут базовый класс Object. В последнем варианте язык Smalltalk предусматривает передачу сообщения doesNotUnderstand, служащего признаком ошибки. Главной особенностью этого алгоритма является словарь сообщений (message dictionary), являющийся частью представления класса и потому скрытый от клиента. Этот словарь создается одновременно с классом и содержит все методы, связанные с экземплярами данного класса. Поиск сообщения в словаре требует довольно много времени. Вызов метода в языке Smalltalk требует примерно в 1,5 раза больше времени, чем простой вызов подпрограммы. В коммерческих версиях языка Smalltalk предусмотрена оптимизация диспетчеризации методов за счет кеширова- ния доступа к словарю, поэтому часто передаваемые сообщения находятся быстро. Как правило, кеширование ускоряет быстродействие программ на 20-30% [24]. Операция draw, определенная в подклассе solidRectangle, представляет собой особый случай. Как отмечено выше, ее реализация сначала вызывает одноименный метод, определенный в суперклассе Rectangle. В языке Smalltalk методы суперкласса выделяются с помощью ключевого слова super. Диспетчеризация методов в языке Smalltalk осуществляется так, как уже описывалось, за исключением того, что поиск начинается с суперкласса, а не с класса. Исследования Дейча (Deutsch) дают основание утверждать, что в 85% случаев полиморфизм не нужен, поэтому вызов метода часто можно свести к обычному
Глава 3. Классы и объекты 137 вызову процедуры [25]. Дафф (Duff) отмечает, что, разрабатывая такие классы, программисты часто неявно предполагают существование механизма раннего связывания [26]. К сожалению, в языках без контроля типов, таких как Smalltalk, не существует общепринятых средств для передачи этих предположений компилятору. В языках программирования с более строгим контролем типов, таких как C++, разработчик имеет такую возможность. Поскольку диспетчеризацию методов следует применять как можно реже, сохраняя тем не менее возможность полиморфной диспетчеризации, вызов метода в этих языках немного отличается от описанного выше. Программист, работающий на языке C++, может выбрать операции для позднего связывания, объявив их виртуальными. Все вызовы остальных методов обрабатываются компилятором с помощью раннего связывания, т.е. как простой вызов процедуры. Для управления виртуальными функциями в языке C++ используется концепция виртуальной таблицы vtabfe, определяемой для каждого объекта, требующего полиморфной диспетчеризации, в ходе его создания (т.е. когда класс объекта фиксирован). Виртуальная таблица, как правило, содержит список указателей на виртуальные функции. Например, при создании объекта класса Rectangle виртуальная таблица будет включать запись для виртуальной функции draw, содержащую указатель на ближайшую реализацию функции draw. Если же в класс Displayltem включена виртуальная функция Rotate, которая в классе Rectangle не переопределяется, то соответствующий указатель будет ссылаться на ее реализацию в классе Displayltem. Это позволяет исключить поиск на этапе выполнения программы. Ссылка на виртуальную функцию-член объекта представляет собой лишь косвенное обращение через соответствующий указатель, а требуемый код выполняется немедленно без какого-либо поиска [27]. мо использовать множественное наследование7. Такая структура классов показана на рис. 3.11. Класс Security — разновидность классов Active и Inte- restBearingltem. Аналогично, класс BankAccount является разновидностью классов Asset, InsurableltemиInterestBearingltem. Проектирование подходящей структуры классов, использующей наследование, и особенно множественное наследование, — трудная задача. Часто ее решают методом последовательных приближений. Множественное наследование порождает две проблемы: как разрешить конфликты имен между разными суперклассами и что делать с повторным наследованием. 7 Этот признак является критерием для использования множественного наследования. Если листья диаграммы классов, имеющих ортогональные свойства (например, активы, которые можно застраховать, и активы, приносящие процентный доход), можно объединить в пересекающиеся множества, то при одиночном наследовании не существует ни одного промежуточного класса, который обладал бы указанными свойствами, не разрушая абстракцию листовых классов из-за включения в них свойств, которыми они не должны обладать. Множественное наследование может исправить эту ситуацию, поскольку оно позволяет смешивать только желательные свойства.
138 Часть I. Концепции SavlngaAt Security Checking Account I Рис. 3.11. Множественное наследование Конфликт имен возможен, если в нескольких суперклассах используется одно и то же имя, обозначающее определенный элемент интерфейса класса. Например, предположим, что классы Insurableltem и Asset содержат атрибут presentValue, обозначающий текущую стоимость актива. Поскольку класс RealEstate является наследником обоих этих классов, неясно, что означает наследование двух операций с одним и тем же именем. На самом деле, эта проблема является основной для множественного наследования: конфликт имен может внести двусмысленность в поведение подкласса, имеющего несколько суперклассов. Существует три подхода к разрешению конфликтов имен. Во-первых, семантические правила языка программирования могут объявить конфликт имен недопустимой ошибкой и прекратить компиляцию. Во-вторых, можно считать, что одинаковые имена означают один и тот же атрибут. В-третьих, семантика языка может допускать конфликты имен, требуя, тем не менее, чтобы все ссылки на имя содержали полную информацию о своем источнике. Вторая проблема — повторное наследование. Мейер (Meyer) описывает его так: "При использовании множественного наследования возникает одна тонкость: неясно, что делать, если один и тот же класс является наследником другого класса
Глава 3. Классы и объекты 139 по нескольким линиям. Если язык программирования допускает множественное наследование, то рано или поздно кто-нибудь напишет класс D, являющийся наследником классов В и С, каждый из которых, в свою очередь, будет наследником класса А, или же возникнет другая ситуация, в которой класс D будет двойным (или даже многократным) наследником класса А. Эта ситуация называется повторным наследованием и требует большой осторожности" [29]. Предположим, например, что проектировщик принял неверное решение, назначив класс Mutual Fund наследником двух классов Stock и Bond (см. рис. 3.11). В результате возникло повторное наследование от класса Security, являющегося суперклассом по отношению к классам Stock и Bond. Существует три способа решения проблемы повторного наследования. Во- первых, его можно запретить. Во-вторых, можно разрешить дублирование суперклассов, потребовав уточнить происхождение имен. В-третьих, можно рассматривать множественные ссылки как ссылки на один и тот же класс. Языки программирования используют разные способы решения этой проблемы. Множественное наследование породило особую категорию классов— примеси (mixins). Идея примесей возникла в среде языка Flavors: он допускал комбинирование (смешение) небольших классов при разработке классов с более сложным поведением. "С синтаксической точки зрения, примесь идентична обычному классу, но они имеют разные цели. Примесь предназначена лишь для добавления функций в другие классы — никто никогда не создает экземпляры примесей" [30]. На рис. 3.11 классы Insurableltemn interestBearingltem являются примесями. Ни один из них не может существовать сам по себе; они используются для расширения свойств другого класса. Таким образом, примесь — это класс, обладающий отдельным, узкоспециализированным поведением и предназначенный для расширения функциональных возможностей другого класса с помощью механизма наследования. Функциональное свойство примеси, как правило, полностью ортогонально свойствам класса, с которым она комбинируется. Класс, созданный главным образом из примесей, называется агрегатным (aggregate class). Агрегация Отношения целое/часть между экземплярами классов выражаются отношениями агрегации. Отношения агрегации между классами абсолютно аналогичны отношениям агрегации между объектами этих классов. Как показано на рис. 3.12, класс TemperatureController означает целое, а класс Heater — его часть, что полностью соответствует отношению агрегации между экземплярами этих классов, показанных на рис. 3.6.
140 Часть I. Концепции Heater I Рис. 3.12. Агрегация Физическое включение Класс TemperatureController демонстрирует агрегацию как включение по значению (containment by value). Это значит, что объект класса Heater не существует отдельно от содержащего его экземпляра класса TemperatureController. Периоды существования этих двух объектов тесно связаны между собой. При создании экземпляра класса TemperatureController одновременно создается экземпляр класса Heater. Второй вид агрегации — композиция (composition) — является включением по ссылке (containment by reference). В этом случае класс TemperatureController по-прежнему означает целое, а экземпляр класса Heater по-прежнему представляет собой его часть, но клиент имеет косвенный доступ к нему. Следовательно, продолжительности существования этих объектов слабо связаны друг с другом. Экземпляры классов теперь можно создавать и уничтожать независимо. Агрегация придает направленность отношению "целое/часть". Например, экземпляр класса Heater является частью экземпляра класса TemperatureController, но не наоборот. Разумеется, агрегация не всегда означает физическое включение. Например, несмотря на то что акционер владеет акциями, они не являются его физической частью. Кроме того, продолжительность существования каждого из этих объектов может быть совершенно разной, хотя концептуально отношение целого и части сохраняется (каждая акция является частью активов акционера). Представление этой агрегации может носить весьма косвенный характер. Это отношение также является агрегацией, хотя и без физического включения. Необходимый признак агрегации таков: классы находятся в отношении агрегации друг с другом, только если между любыми двумя их объектами существует отношение "целое/часть". Агрегацию часто путают с множественным наследованием. Сравнивая эти механизмы, следует помнить об их необходимых признаках. Если невозможно уверенно утверждать, что между двумя классами существует отношение "is а", то вместо наследования следует применить агрегацию или другое отношение. Зависимости Кроме наследования, агрегации и ассоциации между объектами существует другой тип отношений — зависимости (dependencies). Зависимость означает, что один из элементов каким-то образом зависит от другого. Изменение одного из
Глава 3. Классы и объекты 141 таких элементов влияет на другой. Существует много разновидностей зависимости (их полный перечень можно найти в спецификации системы обозначений UML, разработанной компанией Object Management Group [31]). Зависимости часто используются в архитектурных моделях (в которых один компонент системы, или пакет, зависит от другого), а также на уровне реализации (когда одна модель зависит от другой). 3.5 Взаимосвязь классов и объектов Классы и объекты — это отдельные, хотя и тесно связанные понятия. В частности, каждый объект является экземпляром какого-либо класса, а любой класс может порождать произвольное число объектов или не порождать ни одного. В большинстве практических приложений классы статичны, т.е. все их периоды существования, семантика и зависимости фиксируются до выполнения программы. Аналогично, класс любого созданного объекта фиксируется заранее. В противоположность этому, объекты интенсивно создаются и уничтожаются в процессе выполнения программы. Отношения между классами и объектами В качестве примера рассмотрим классы и объекты, существующие в системе управления воздушным движением. К наиболее важным абстракциям этой системы относятся самолеты, планы полетов, взлетно-посадочные полосы и коридоры в воздушном пространстве. Смысл этих классов и объектов по самому их определению является статичным. В противном случае было бы невозможно создать приложение, использующие на практике знания о том, как самолеты взлетают, летают и приземляются, не сталкиваясь друг с другом. В противоположность этому, экземпляры данных классов носят динамический характер. К медленно изменяющиеся факторам относится строительство новых взлетно-посадочных полос и реконструкция старых. Быстро изменяющиеся факторы включают в себя появление новых планов полетов и отмену старых маршрутов. Наиболее динамичные аспекты системы управления воздушным движением описывают вход новых самолетов в воздушный коридор и вылет самолетов из воздушного коридора. Роль классов и объектов в анализе и проектировании На этапе анализа и ранних стадиях проектирования перед разработчиками систем программного обеспечения стоят две задачи. 1. Идентификация классов, образующих словарь предметной области. 2. Изобретение структур, в которых объекты взаимодействуют друг с другом, обеспечивая поведение, соответствующее требованиям задачи.
142 Часть I. Концепции Классы и объекты называются основными абстракциями (key abstraction), а взаимодействующие структуры — механизмами реализации (mechanisms of the implementation). На ранних стадиях проектирования внимание разработчиков должно быть сосредоточено на внешних проявлениях основных абстракций и механизмов. Это представление образует логическую основу системы и должно учитывать структуру ее классов и объектов. На последующих фазах проекта и на этапе реализации задача проектировщика изменяется и в центре внимания оказывается внутреннее представление основных абстракций и механизмов, включая их физическое воплощение. Принимаемые в процессе проектирования решения задают архитектуру системы: и архитектуру процессов, и архитектуру модулей. 3.6 Качество классов и объектов Ингаллс (Ingalls) утверждает: "Для построения системы должен использоваться минимальный набор неизменяемых и как можно более общих компонент, рассматриваемых в рамках единой модели" [32]. В объектно-ориентированном проектировании такими компонентами являются классы и объекты, представляющие собой основные абстракции системы, а единство обеспечивается соответствующими механизмами реализации. Опыт показывает, что проектирование классов и объектов является итеративным процессом. За исключением самых простых задач сразу дать точное описание класса практически невозможно. Для того чтобы сгладить концептуальные противоречия между первоначальными абстракциями, необходимо время. Разумеется, уточнение абстракций связано с дополнительными затратами на перекомпиляцию, согласование и модификацию системы. Следовательно, необходимо стараться с самого начала создать как можно более точные абстракции. Измерение качества абстракции Для оценки качества классов и объектов, выделяемых в системе, можно предложить следующие пять показателей. 1. Связанность (coupling). 2. Связность (cohesion). 3. Достаточность (sufficiency). 4. Полнота (completeness). 5. Элементарность (primitiveness). Термин связанность заимствован из теории структурного проектирования, но в более вольном толковании его можно использовать и в объектно-ориентиро-
Глава 3. Классы и объекты 143 ванном проектировании. Стевенс (Stevens), Майерс (Myers) и Константин (Соп- stantine) определяют связанность как "силу связей между отдельными модулями. Сильная связанность усложняет систему, поскольку тесно связанные модули гораздо сложнее воспринимать и модифицировать. Сложность можно уменьшить, разрабатывая системы с как можно более слабыми связями между модулями" [33]. Пример неправильного подхода к проблеме связанности привел Пейдж-Джонс (Page-Jones), описав модульную стереосистему, источник питания которой размещен в одной из звуковых колонок [34]. Наряду со связанностью между модулями, в объектно-ориентированном анализе и проектировании существенную роль играют связанность между классами и объектами. Однако существует определенное противоречие между связанностью и наследованием. С одной стороны, желательно, чтобы классы были как можно слабее связаны между собой. С другой стороны, механизм наследования — тесно связывающий суперкласс с его подклассами — помогает использовать сходство между абстракциями. Понятие связности также заимствовано из структурного проектирования. Грубо говоря, связность — это глубина взаимодействия между элементами отдельного модуля (а в объектно-ориентированном проектировании — между элементами отдельного класса или объекта). Наименее желательной является случайная связность, когда в одном классе или модуле собираются несвязанные друг с другом абстракции. Представьте себе, например, класс, соединяющий абстракции собак и космических аппаратов. Наиболее желательной является функциональная связность, при которой все элементы класса или модуля тесно взаимодействуют, обеспечивая четко определенное поведение. Так, например, класс Dog является функционально связным, если его семантика описывает поведение собаки. К свойствам связанности и связности тесно примыкают понятия достаточности, полноты и простоты. Достаточность означает, что класс или модуль содержат достаточно много характеристик абстракции, чтобы обеспечить целенаправленное и эффективное взаимодействие. В противном случае компоненты системы становятся бессмысленными. Например, разрабатывая класс Set, целесообразно включить в него операцию удаления элемента из множества, но все окажется бесполезным, если пренебречь операцией добавления элемента в множество. На практике нарушение требования достаточности обнаруживается очень быстро. Это случается всякий раз, когда создается клиент, который должен использовать данную абстракцию. Полнота означает, что интерфейс класса или модуля описывает все существенные свойства абстракции. В то время как достаточность подразумевает минимальный интерфейс, полный интерфейс по определению охватывает все аспекты абстракции. Полным называется класс или модуль, интерфейс которого гарантирует все необходимые средства для взаимодействия с клиентами. Полнота является субъективным фактором и часто преувеличивается. Реализуя все осмысленные
144 Часть I. Концепции операции над конкретной абстракцией, класс перегружает пользователя. Многие высокоуровневые операции являются избыточными, поскольку их можно реализовать с помощью операций более низкого уровня. Это приводит нас к понятию элементарности. Элементарными называются операции, для эффективной реализации которых необходимо иметь доступ к внутреннему представлению абстракции. Например, добавление элемента в множество является элементарной операцией, поскольку для реализации операции Add необходим доступ к внутреннему представлению класса Set. С другой стороны, операция добавления четырех элементов в множество не является элементарной, так как ее можно эффективно реализовать с помощью элементарной операции Add, не имея доступа к внутреннему представлению класса. Конечно, эффективность тоже понятие субъективное. Операция, которая требует прямого доступа к структуре данных, примитивна по определению. Операция бесспорно является элементарной, только если ее невозможно реализовать, не имея доступа к внутреннему представлению абстракции. Операция, которую можно реализовать с помощью существующих элементарных операций, но ценой значительно больших вычислительных затрат, также является кандидатом на включение в число элементарных. Выбор операций Разработка интерфейса класса или модуля — это трудная работа. Обычно сначала создается первое приближение класса, а затем, когда появляются клиенты класса, интерфейс расширяется, модифицируется и уточняется. В итоге, проектировщик может выявить шаблоны операций над данной абстракцией и создать новые классы или реорганизовать отношения между существующими классами. Функциональность Внутри класса принято хранить только элементарные операции, каждая из которых описывает небольшой, точно определенный аспект поведения. Такие методы называются мелкомодульными (fine-grained). Кроме того, целесообразно отделять друг от друга методы, не связанные между собой. Это намного облегчает создание подклассов, осуществляющих разумное переопределение поведения суперкласса. Выбор количества методов для описания поведения класса определяется двумя взаимно противоречивыми рассуждениями: 1) попытка описать поведение в одном методе упрощает интерфейс, но укрупняет и усложняет сам метод; 2) распределение функциональных возможностей между методами усложняет интерфейс, но упрощает методы. Как отмечает Мейер (Meyer): "Хороший проектировщик знает, как найти приемлемое решение, позволяющее избежать избыточной детализации, приводящей к фрагментации системы, и недостаточной детализации, порождающей неуправляемые крупные модули" [35].
Глава 3. Классы и объекты 145 В объектно-ориентированном проектировании принято рассматривать методы класса как единое целое, поскольку все они взаимодействуют друг с другом и образуют протокол абстракции. Таким образом, зная требуемое свойство системы, необходимо решить, в каком из классов его описать. Хелберт (Helbert) и О'Брайен (O'Brian) предложили следующие критерии для принятия такого решения [36]. • Возможность повторного использования: может ли данное свойство иметь смысл в другом контексте? • Сложность: насколько трудно реализовать такое свойство? • Применимость: насколько данное свойство характерно для класса, в который оно включается? • Требования к реализации: зависит ли реализация данного свойства от внутренних деталей класса? Как правило, операции над объектами объявляются в определении соответствующего класса (или суперкласса) в виде методов. Временная и пространственная семантика Выбрав конкретную операцию и определив ее функциональную семантику, проектировщик должен принять решение относительно ее временной и пространственной семантики. Это значит, что проектировщик должен определить время, которое потребуется для полного выполнения операции, а также объем памяти, необходимый для нее. Такие решения описываются с помощью наилучшего, среднего и худшего сценариев. При этом худшим считается сценарий, в котором для выполнения операции требуется наибольший объем ресурсов. Как уже отмечалось, объекты посылают сообщения друг другу по соединяющим их связям. Следовательно, связанные объекты должны быть каким-то образом синхронизированы. В параллельных системах управления механизм передачи сообщений намного сложнее, чем обычный вызов подпрограмм. В большинстве распространенных языков программирования синхронизация просто не нужна, поскольку все программы содержат только один поток управления, и все объекты действуют последовательно. В таких случаях передача сообщений называется простой, так как ее семантика больше похожа на простой вызов подпрограмм. Однако в языках, поддерживающих параллельность, применяются более изощренные механизмы передачи сообщений. Это позволяет избежать проблем, возникающих, когда два потока одновременно воздействуют на один и тот же объект, никак не согласовывая свои операции. Как указывалось ранее, объекты, семантика которых сохраняется в средах с несколькими потоками управления, называются защищенными (guarded), или синхронизированными (synchronized).
146 Часть I. Концепции Выбор отношений Выбор отношений между классами и объектами зависит от выбора операций. Если проектировщик хочет, чтобы объект X послал объекту Υ сообщение М, то прямо или косвенно класс X должен иметь доступ к классу Υ, иначе операцию Μ невозможно вызвать в классе X. Под доступом понимается способность одной абстракции находить другую и обращаться к ее открытым ресурсам. Абстракции доступны друг для друга только тогда, когда их области видимости перекрываются и они обладают необходимыми правами доступа (например, закрытая часть класса доступна только его членам и друзьям). Таким образом, связанность отражает степень видимости. Сотрудничество Выбирая отношения, целесообразно пользоваться законом Деметера (Deme- ter), утверждающим, что "методы класса не должны зависеть от структуры других классов, за исключением ближайшей структуры (верхнего уровня) самого класса. Кроме того, каждый метод должен посылать сообщения только объектам, принадлежащим предельно ограниченному множеству классов" [37]. Следование этому закону позволяет создавать слабо связанные классы, реализация которых инкапсулирована. Такие классы достаточно автономны, т.е. чтобы разобраться в их работе, нет необходимости знать строение других классов. При анализе структуры классов системы в целом может оказаться, что иерархия наследования либо слишком широкая и мелкая, либо слишком узкая и глубокая, либо сбалансированная. Широкая и мелкая структура классов выглядит как лес из свободно стоящих деревьев, смешивающихся и согласующихся между собой [38]. Узкая и глубокая структура классов напоминает дерево классов, имеющих общего предка [39]. Каждый из этих вариантов имеет свои достоинства и недостатки. Классы, образующие лес, слабо связаны друг с другом, но не всегда используют все общие свойства, существующие в системе. Дерево классов, наоборот, использует все общие свойства, существующие в системе, поэтому отдельные классы, образующие дерево, меньше, чем классы, образующие лес. Однако для того чтобы разобраться в устройстве класса, входящего в дерево, обычно необходимо понимать предназначение всех его суперклассов. Выбор правильной формы структуры классов сильно зависит от специфики задачи. Иногда необходимо найти компромисс между отношениями наследования, агрегации и зависимости. Например, должен ли класс Саг наследовать, содержать или использовать классы Engine и Wheel? В данном случае отношение агрегации более целесообразно, чем наследование. По мнению Мейера (Meyer), между классами А и В "наследование приемлемо, если любой экземпляр класса В может одновременно рассматриваться и как объект класса А. Отношение клиента следует выбирать тогда, когда каждый экземпляр класса В просто владеет одним
Глава 3. Классы и объекты 147 или несколькими свойствами класса А" [40]. С другой стороны, если объект является чем-то большим, чем простая сумма его частей, то следует предпочесть отношение наследования. Механизмы и видимость Отношения между объектами зависят от механизмов их взаимодействия. Перед проектировщиком стоит простой вопрос: как разделить знания между объектами? Например, на ткацкой фабрике партии материалов поступают для обработки на производственные участки. О поступлении партии на участок необходимо известить управляющего, который должен выбрать определенное действие. Таким образом, проектировщик должен решить, является ли поступление партии материала на участок операцией над участком, над материалом, или тем и другим одновременно. Если это операция над участком, то класс участка должен быть видим для класса материала. Если это операция над материалом, то класс материала должен быть видим для класса участка, так как партия материала должна различать участки. Если это операция над участком и партией материала одновременно, то необходимо обеспечить их взаимный доступ. Кроме того, следует определить отношение между управляющим и участком (но не материалом и управляющим): либо управляющий должен знать все о своем участке, либо участок должен знать о своем управляющем. Выбор реализации Внутреннее представление класса или объекта разрабатывается только после завершения проектирования их внешнего представления. При этом необходимо принять два проектных решения: выбрать способ представления класса или объекта и определить способ их размещения в модуле. Представление Представление классов и объектов почти всегда должно быть инкапсулировано. Это позволяет вносить изменения (например, модифицировать способы использования памяти и временных ресурсов), не нарушая предположения о функциональных свойствах класса или объекта, которые могут иметь их клиенты. Как мудро отметил Вирт: "Выбор способа представления является нелегкой задачей и не определяется одними лишь доступными техническими средствами. Он всегда должен рассматриваться с точки зрения операций над данными" [41]. Например, разрабатывая класс, объекты которого определяют планы полетов самолетов, необходимо решить, как оптимизировать его представление — ускорив поиск или ускорив операции вставки и удаления. Поскольку одновременно оптимизировать и то, и другое невозможно, выбор следует делать, исходя из будущего использования объектов. Иногда такой выбор сделать непросто, и проектировщик выбирает
148 Часть I. Концепции семейство классов с практически одинаковыми интерфейсами, но совершенно разными реализациями, стремясь обеспечить разные способы использования ресурсов. Одним из наиболее трудных компромиссов является выбор между вычислением состояния объекта и хранением его в поле данных. Рассмотрим, например, класс Cone, содержащий метод Volume. Этот метод возвращает объем конуса. Представление конуса, как правило, хранит высоту и радиус основания в полях данных. Следует ли создать дополнительное поле данных для объема или же вычислять его по мере необходимости с помощью метода Volume [42]? Если необходимо, чтобы объем конуса вычислялся быстро, то объем следует хранить в поле данных. Если экономия памяти важнее, то лучше вычислить это значение. Оптимальный способ представления объекта всегда определяется спецификой решаемой задачи. В любом случае этот выбор не должен зависеть от внешнего представления класса. Упаковка Аналогичные вопросы возникают при распределении объявления классов и объектов по модулям. Решение обычно принимается путем компромисса между взаимно противоречивыми требованиями к видимости и сокрытию информации. Как правило, модули должны быть функционально связными внутри и слабо связанными друг с другом. При этом необходимо учитывать многие нетехнические факторы, такие как возможность повторного использования, безопасность и документирование. Проектирование модулей не менее сложная задача, чем проектирование классов и объектов. Как утверждают Парнас (Parnas), Клеменс (Clemens) и Вейс (Weiss): "Применить этот принцип не всегда легко. Он нацелен на минимизацию ожидаемой стоимости программного обеспечения в течение периода ее эксплуатации, и проектировщик должен оценить вероятность изменений. Такие оценки основываются на практическом опыте и знаниях предметной области, включая аппаратное и программное обеспечение" [44]. Резюме • Объект характеризуется состоянием, поведением и индивидуальностью. • Структура и поведение одинаковых объектов описываются в общем для них классе. • Состояние объекта определяет его статические и динамические свойства. • Поведение объекта — это действия и реакции объекта, выраженные в терминах изменения состояний и передачи сообщений.
Глава 3. Классы и объекты 149 • Индивидуальность объекта — это свойство объекта, отличающие его от всех других объектов. • Класс — это множество объектов с одинаковой структурой и поведением. • Между классами существует три вида отношений: ассоциация, наследование и агрегация. • Основными абстракциями являются классы и объекты, образующие словарь предметной области. • Механизм — это структура, с помощью которой множество взаимодействующих объектов обеспечивает требуемое поведение. • Качество абстракций измеряется степенью их связанности, связности, достаточности, полноты и элементарности.
ГЛАВА 4 КЛАССИФИКАЦИЯ Классификация — это средство, с помощью которого мы упорядочиваем свои знания. В объектно-ориентированном проектировании выявление сходства между объектами позволяет найти общие свойства основных абстракций и механизмов, и, в итоге, уменьшить размер приложений и упростить их архитектуру. К сожалению, классификация — сложная задача. Читателей, привыкших получать готовые ответы, следует недвусмысленно предупредить, что готовых рецептов идентификации классов и объектов не существует. Таких вещей, как "совершенная структура классов" или "правильный набор объектов" в природе нет. Как и во многих технических дисциплинах, любое проектное решение является компромиссом между многими факторами. К счастью, есть огромный опыт классификации в других науках. На его основе возник объектно-ориентированный анализ, предложивший полезные методы и эмпирические правила идентификации классов и объектов, относящихся к конкретной задаче. Эти эвристические правила являются предметом изучения данной главы. 4.1 Важность правильной классификации Идентификация классов и объектов — одна из самых сложных задач объектно- ориентированного анализа и проектирования. Опыт показывает, что ее решение содержит в себе элементы открытия и изобретения. Открытия позволяют распознать основные абстракции и механизмы, образующие словарь предметной области. Изобретения помогают сконструировать обобщенные абстракции и новые механизмы, определяющие способы взаимодействия объектов. Итак, классификация всегда сопряжена с открытиями и изобретениями. Целью классификации является выявление общих свойств объектов. Классификация позволяет объеди-
Глава 4. Классификация 151 нить в одну группу объекты, имеющие одинаковую структуру или одинаковые свойства. 1 2 3 4 5 6 7 θ "9 Дата ; Продолжительность > Вес периода 31 декабря !12 ,„^.flQ 31 января Ίΐ Ь$2 261 февраля' Jib""" '.."...".V J [pMJ JJ.J1. J JJ 31 января ; : 1 Показатель IRR вычисляется програииой шшштшшшшшшшшшт Стайность Будуидая стайность ;Ϊ00 (117.05 :ΊΟ !Ц',55 ;10 111.40 ^140 __ ;140ДО Разность Ό .00 £') IRR 10.1705 ! Доходность, %:17,05 =D2*((1+E8)*C2) I =ЬГ(0+Ев)*СЗ)" =D4*(i1+E8)*C4) =СУММ(Е2Е4) =Ь£Ё5 =Е8Ч00~ '" I Классификация — это средство упорядочения знаний Разумная классификация представляет собой неотъемлемую часть любой науки. Михальски (Michalski) и Степп (Stepp) утверждают: "В любой научной дисциплине необходимо разумно классифицировать наблюдаемые объекты или ситуации. Это существенно облегчает понимание основной проблемы и дальнейшее развитие научной теории" [1]. Эти принципы распространяются и на инженерное дело. Знаменитый специалист в области строительной архитектуры и городского планирования Александер (Alexander) заметил, что "проектирование зданий, как небольших, так и гигантских, основано на шаблонах и способности архитектора комбинировать эти шаблоны при создании нового проекта" [2]. Неудивительно, что многие аспекты объектно-ориентированного проектирования связаны с классификацией. Классификация помогает идентифицировать иерархии классов, связанных между собой отношениями обобщения, специализации и агрегации. Выявляя шаблоны взаимодействия объектов, можно изобрести механизмы, образующие фундамент проекта. Кроме того, классификация помогает правильно определить его модульную структуру и разместить объекты в одном или разных модулях, ориентируясь на степень их схожести. О схожести объектов свидетельствуют также их связанность и связность. Классификация играет большую роль при распределении процессов между процессорами. Процессы направляются на один процессор или на разные в зависимости от соображений, связанных с их компоновкой, эффективностью или надежностью. Трудности классификации В предыдущей главе объект определен как сущность, имеющая четкие границы. Однако границы, отделяющие один объект от другого, часто размыты. Например, сложно сказать, где начинается и заканчивается колено. При распознавании разговорной речи трудно понять, относится ли конкретный звук к данному слову или является частью окружающих слов. Представим себе проект текстового редактора. Что считать классом — символы или слова? Как выделить произвольный
152 Часть I. Концепции текст, состоящий из разрозненных фрагментов? Следует ли предложения, абзацы и весь документ описывать в виде классов? Факт, что разумная классификация представляет собой сложную проблему, известен давно. Подтвердим этот тезис примерами классификации в биологии и химии, имеющими аналоги в объектно-ориентированном проектировании. Вплоть до XVIII века в биологии доминировала идея о возможности упорядочить живые организмы по мере возрастания степени их сложности. Мера сложности была чрезвычайно субъективной (поэтому неудивительно, что человек оказался на вершине списка). В середине XVIII века шведский ботаник Карл Линней (Carolus Linnaeus) предложил более подробную таксономию для классификации организмов: по родам (genus) и видам (species). Через сто лет Дарвин (Darwin) предложил теорию, согласно которой механизмом эволюции является естественный отбор, а ныне существующие виды животных произошли от более древних. Теория Дарвина основывалась на разумной классификации видов. Дарвин утверждал: "Натуралисты пытаются объединить виды, роды, семейства в классы, образующие то, что называется естественной системой. Но что подразумевается под этой системой? Некоторые авторы считают ее схемой группировки схожих организмов в один класс и распределения непохожих организмов по разным классам" [3]. В современной биологии термин "классификация" означает "установление иерархической системы категорий на основе предположительно существующих естественных отношений между организмами" [4]. Наиболее общая категория в биологической таксономии — это фауна (kingdom), затем, в порядке возрастания специализация: тип (phylum), подтип (subphylum), класс (class), отряд (order), семейство (family), род (genus) и, наконец, вид (species). Возможно, программистам биология представляется застывшей наукой с четкими критериями классификации организмов. Однако это далеко не так. "Как ни странно, ученые лучше знают, сколько звезд в нашей галактике, чем сколько биологических видов на Земле. По некоторым предположениям количество биологических видов колеблется от 2 до 100 млн. Наиболее точной считается оценка 10 млн, причем лишь 1,4 млн биологических видов имеют название" [58]. Более того, разные критерии классификации одних и тех же организмов приводят к разным результатам. Мартин (Martin) утверждает: "Все зависит от того, что вы хотите от классификации. Если ваша цель — отразить генетическую связь между видами, то вы получите один ответ. Если же вы желаете каким-то образом охарактеризовать уровни адаптации, то ответ будет другой" [5]. Итак, даже в строгих научных дисциплинах классификация сильно зависит от своего предназначения. Аналогичные уроки можно извлечь, изучая химию [6]. В древние времена считалось, что все вещества представляют собой комбинации земли, воздуха, огня и воды. В настоящее время такую классификацию нельзя считать удовлетворительной (конечно, если вы не алхимик). В середине XVII века Роберт Бойль
Глава 4. Классификация 153 (Robert Boyle) предположил, что простейшими химическими абстракциями являются элементы, из которых состоят более сложные структуры. Век спустя, в 1789 году, Лавуазье (Lavoisier) опубликовал первый список, содержащий 23 элемента, некоторые из которых, как выяснилось позднее, элементами вовсе не являются. Однако открытие новых элементов продолжалось и список увеличивался, пока в 1869 году. Менделеев не открыл периодический закон, дававший точные критерии для классификации известных элементов и предсказывавший свойства еще не открытых элементов. И все же даже периодический закон не был завершением истории о классификации элементов. В начале XX века были открыты элементы с одинаковыми химическими свойствами, но с разными атомными весами — изотопы. Вывод ясен. Как утверждал Декарт (Descartes): "Открытие порядка — нелегкая задача..., но если он найден, то понять его совсем нетрудно" [7]. Лучшие проекты программного обеспечения выглядят просто, но, как показывает опыт, разработать простую архитектуру очень трудно. Итеративная суть классификации Все эти сведения мы привели здесь не для того, чтобы оправдать растянутые сроки для создания программного обеспечения, хотя иногда кажется, что программистам необходимы столетия, чтобы выполнить свою работу. Изложенная история лишь подчеркивает, что разумная классификация — это сложная интеллектуальная работа и лучший способ ее выполнения — последовательный, итеративный процесс. Как отметил Шоу (Shaw), при проектировании программного обеспечения "разработка отдельных абстракций часто основана на общих шаблонах. Сначала проблема решается приблизительно. Потом, по мере накопления опыта, некоторые решения оказываются лучше других и возникает что-то вроде фольклора, неформально распространяющегося между людьми. В итоге удачные решения систематически изучаются, программируются и анализируются. Это позволяет создавать модели, поддерживающие их автоматическую реализацию, и разрабатывать теории, обобщающие найденное решение. Это в свою очередь обогащает практику и позволяет решать еще более сложные задачи, которые снова решаются в первом приближении, начиная новый виток спирали" [8]. Поступательная и итеративная природа классификации непосредственно влияет на конструирование иерархий классов и объектов при разработке сложного программного обеспечения. На практике, как правило, за основу берется структура классов, использованная в одном из предыдущих проектов, которую постепенно совершенствуют. Качество классификации можно оценить лишь на поздней стадии разработки, когда созданы клиенты, использующие разработанную структуру. Основываясь на полученном опыте, можно создать новые подклассы существующих классов (вывод), разделить большой класс на много маленьких (фак-
154 Часть I. Концепции Разные наблюдатели классифицируют один и тот же объект по-разному торизация) или объединить несколько маленьких классов в один большой класс (композиция). Иногда в процессе проектирования выявляют ранее незамеченные общие свойства, позволяющие создать новый класс (абстракцию) [9]. Почему же классификация является такой трудной задачей? Это объясняется двумя основными причинами. Во-первых, "идеальной" классификации не существует, хотя, естественно, некоторые классификации лучше других. Кумбс (Coombs), Райффа (Raiffa) и Тралл (Thrall) утверждают: "Способов разделения мира, на объектные системы будет столько же, сколько ученых примется решать эту задачу" [10]. Любая классификация зависит от точки зрения выполняющего его наблюдателя. Во-вторых, разумная классификация требует огромных творческих усилий. Биртвистл (Birtwistl), Даль (Dahl), Мирхауг (Myhrhaug) и Нигард (Nygard) полагают, что "иногда ответ очевиден, иногда зависит от предпочтений наблюдателя, а иногда все зависит от выбора подходящих компонентов" [11]. Все это напоминает загадку: "Чем лазерный луч похож на золотую рыбку?.. Тем, что ни тот, ни другой не умеют свистеть" [12]. Только очень творческая личность может найти сходство между настолько несвязанными предметами. 4.2 Идентификация классов и объектов Проблема классификации занимала умы бесчисленных философов, лингвистов, специалистов по теории познания и математиков еще со времен Платона.
Глава 4. Классификация 155 Полезно изучить накопленный опыт и применить его к объектно-ориентированному проектированию. Классический и современный подходы Исторически известны только три подхода к классификации. 1. Классическая категоризация. 2. Концептуальная кластеризация. 3. Теория прототипов [13]. Классическая категоризация Классический подход к категоризации основан на следующем принципе. "Все сущности, обладающие данным свойством или совокупностью свойств, образуют некоторую категорию. Эти свойства являются необходимыми и достаточными условиями, определяющими категорию" [14]. Например, супруги образуют отдельную категорию: каждый человек либо состоит в браке, либо нет. Этот признак достаточен для того, чтобы решить, к какой категории принадлежит тот или иной человек. С другой стороны, высокие люди не образуют отдельную категорию, если, конечно, не существует абсолютный критерий, позволяющий различать высоких и низкорослых людей. Классическая категоризация впервые была предложена Платоном (Plato). Позднее Аристотель (Aristotle), классифицируя растения и животных, использовал метод, напоминающий современную детскую игру "20 вопросов" (Это животное, минерал или растение? Оно покрыто мехом или перьями? Может ли оно летать? Пахнет ли оно?) [16]. Вопросы классификации волновали и позднейших философов, среди которых следует выделить Фому Аквинского (Quinas), Декарта (Descartes) и Локка (Locke). Фома Аквинский утверждал: "Мы можем называть вещи согласно нашим знаниям об их природе, получаемым через познание их свойств и действий" [17]. Принципы классической категоризации отражены в современных теориях развития ребенка. Пьяже (Piaget) утверждает, что после первого года жизни ребенок осознает постоянство объектов и вскоре приобретает навыки их классификации, вначале используя базовые категории, такие как собаки, кошки и игрушки [18]. Позднее ребенок обнаруживает как более общие категории (например, животные), так и более специализированные (например, гончие) [19]. Таким образом, классический подход в качестве критерия схожести объектов использует родственные свойства. В частности, объекты можно разделять на непересекающиеся множества в зависимости от наличия или отсутствия некоторого признака. Мински (Minsky) предположил, что "наиболее полезными являются такие совокупности свойств, элементы которых мало взаимодействуют между собой. Это объясняет всеобщую популярность таких критериев, как размер, цвет,
156 Часть I. Концепции форма и вещество. Поскольку эти атрибуты слабо связаны друг с другом, их можно комбинировать и утверждать, что некий объект одновременно велик или мал, деревянный или стеклянный, круглый или квадратный" [20]. Вообще говоря, свойства не сводятся лишь к измеримым характеристикам. Они могут описывать любое наблюдаемое поведение. Например, тот факт, что птицы могут летать, а рыбы — нет, позволяет отличить орла от лосося. Выбор конкретных свойств, которые следует рассматривать в определенной ситуации, сильно зависит от предметной области. Например, цвет автомобиля может оказаться важным для управления запасами автомобильного завода, но не имеет значения для программы, управляющей светофорами на городских улицах. Вот почему нет абсолютных критериев классификации, хотя одна структура классов может больше подходить для одного приложения, чем для другого. Джеймс (James) полагает: "Нельзя утверждать, что некоторая схема классификации лучше других отражает структуру или порядок в природе. Природа безразлична к нашим попыткам разделить сущности на категории. Некоторые классификации могут оказаться важнее других, но только в связи с нашими интересами, а не потому, что они точнее или адекватнее отражают реальность" [21]. Классическая категоризация оказывает сильное влияние на современное западное мышление, однако, как показывает пример с высокими и низкорослыми людьми, этот подход не всегда удовлетворителен. Как заметил Коско (Kosko): "Естественные категории, как правило, являются нечеткими. Большинство птиц летает, но не все. Стул может быть деревянным, металлическим или пластмассовым, а количество ножек у него целиком зависит от прихоти конструктора. Практически невозможно перечислить однозначные свойства естественной категории, не допускающей исключений" [22]. Эти проблемы классической категоризации, действительно, имеют фундаментальный характер. Для их решения были развиты концептуальная кластеризация и теория прототипов. Концептуальная кластеризация Концептуальная кластеризация является более современным вариантом классического подхода. Она возникла в результате попыток разработать способы формального представления знаний. Степп и Михальски утверждают: "При таком подходе сначала формируются концептуальные описания классов (кластеров сущностей), а затем проводится классификация в соответствии с этими описаниями" [23]. Например, можно сформулировать понятие "любовная песня". Эта сущность в большей степени является именно понятием, а не свойством, поскольку степень "любовности" песни едва ли поддается измерению. Однако если можно каким-то образом понять, что данная песня скорее о любви, чем не о любви, то ее следует отнести к этой категории. Концептуальная кластеризация тесно связана с теорией нечетких (многозначных) множеств, в которой объект может принадлежать к нескольким категориям
Глава 4. Классификация 157 Проблема классификации На рис. 4.1 изображены 10 поездов, обозначенных буквами от А до J. Каждое изображение состоит из локомотива и от двух до четырех вагонов. Прежде чем продолжать чтение, попытайтесь за 10 минут объединить изображения в группы, руководствуясь каким-то критерием. Например, изображения можно разбить на три группы: в одной группе у поездов только черные колеса, в другой группе — только белые, а в третьей — и белые, и черные. Этот пример заимствован из работы Степпа (Stepp) и Михальски (Michalski) о концептуальной кластеризации [15]. Совершенно очевидно, что в реальной жизни эта задача не имеет "правильного" ответа. Участники эксперимента провели классификацию 93 различными способами. Чаще всего классификация проводилась по длине состава (с двумя, тремя и четырьмя вагонами). Второй по популярности вид классификации — по цвету колес поезда. Сорок из девяноста трех видов классификации были уникальными. Экспериментируя с этим рисунком, мы убедились в правоте Степпа и Михальски. Большинство опрошенных людей предлагали один из двух наиболее популярных видов классификации (по длине состава и цвету колес поезда). Например, один участник эксперимента предложил отнести к одной группе составы, обозначенные буквами, состоящими из прямых линий (А, Е, F, Η и J), а к другой — буквами с кривыми линиями. Это яркий пример нетривиального, даже несколько странного способа мышления. Теперь изменим условия (как это часто бывает в реальной жизни). Предположим, что круги обозначают груз с токсичными веществами, прямоугольники — лесоматериалы, а все остальные знаки обозначают пассажиров. Попытайтесь заново осуществить классификацию изображений и обратите внимание на то, как новая информация повлияла на ваш выбор. В наших опытах кластеризация значительно изменилась. Большинство опрошенных людей классифицировало поезда по тому, содержит состав токсичный груз или нет. Итак, наш простой эксперимент показал, что новые сведения о реальной ситуации упрощают задачу разумной классификации. одновременно, причем степень его принадлежности категории изменяется. Концептуальная кластеризация позволяет высказывать абсолютные суждения о классификации, основываясь на принципе "наилучшего согласия". Теория прототипов Классическая категоризация и концептуальная кластеризация достаточно выразительны для проектирования сложных программных систем. Однако существуют ситуации, в которых эти методы не работают. Для решения этой проблемы была разработана теория прототипов, предпосылки основы которой заложены в работе Рош (Rosch) и ее коллег по когнитивной психологии [24].
158 Часть I. Концепции Α. Д. Ж. 3. и. О Η <=> Н"^ТЧ° □ □.! Ό U Ό СГ О О пч ,/Т~Н л .Н P. f Ό—α—σ ό—υ υ—σ —σ ο ο ό—σ ν—υ ^J σ | Ο H^=3HL^Jl·- 1 δ HpQCH Ъ—σ Ъ σ ГШ η Ι—w Π Μ TJ ό σ л » т ЧУ-г) 1АН d—о—σ \ О Яр .hfgR, О, /Ч1л"Н Ъ—σ b—σ Ъ σ υ—σ ^J—и π π Γπ Ε5Ί—I d ΗυΛ Ι ό σ ο—ο L-\J—σ Μ Рис. 4.1. Проблема классификации Некоторые абстракции не имеют ни четких границ, ни четкого определения. Лакофф (Lakoff) объясняет эту проблему так: "По утверждению Виттгенштейна (Wittgenstein), существуют категории (например, игры), не соответствующие классическим образцам, поскольку нет свойств, присущих всем играм... Несмотря на отсутствие общих свойств, их можно объединить, руководствуясь понятием, которое Виттгенштейн назвал фамильным сходством (family resemplances)... По наблюдениям Виттгенштейна, у категории игр нет четких границ. Категорию можно расширять, включая в нее новые разновидности игр при условии, что они
Глава 4. Классификация 159 напоминают уже известные игры" [25]. По этой причине описанный подход называется теорией прототипов: класс объектов определяется прототипом и объект считается членом класса только при условии, что он в достаточной степени похож на соответствующий прототип. Лакофф (Lakoff) и Джонсон (Johnson) использовали теорию прототипов для решения задачи о классификации стульев. "Мы считаем мягкий стул, парикмахерское кресло и табуретку разновидностями стула не потому, что они имеют некоторый фиксированный набор признаков прототипа, а потому, что они имеют достаточное фамильное сходство с прототипом... Не требуется никакого общего набора свойств прототипа, которое годилось бы и для мягкого стула и парикмахерского кресла, но они оба являются стульями, так как каждый из них, каждый по-своему, похож на прототип. Главными при определении фамильного сходства являются свойства взаимодействия с объектом" [26]. Свойство взаимодействия — центральное понятие теории прототипов. В концептуальной кластеризации сущности группируются в соответствии с различными концепциями. В теории прототипов классификация объектов производится по степени их сходства с конкретными прототипами. Применение классических и современных теорий Разработчикам, постоянно испытывающим недостаток ресурсов и времени в условиях изменяющихся требований, предмет нашего обсуждения может показаться далеким от реальности. На самом деле три рассмотренных подхода к классификации имеют непосредственное отношение к объектно-ориентированному проектированию. Как показывает опыт, сначала осуществляется идентификация классов и объектов, относящихся к исследуемой предметной области. При этом проектировщики концентрируют свое внимание на идентификации структур и свойств, включенных в словарь предметной области. Таких абстракций, как правило, много [27]. Если этот метод не позволяет создать приемлемую структуру классов, следует попытаться применить концептуальную кластеризацию (или уточнить классификацию понятий, относящихся к предметной области). В центре внимания при этом находятся свойства взаимодействующих объектов. Если же оба метода не приводят к удовлетворительному результату, следует провести классификацию по ассоциации, в которой кластеры содержат объекты, напоминающие некоторый прототип. Эти три способа классификации образуют теоретическую основу объектно- ориентированного анализа, предлагая много практических советов и эмпирических правил, которые можно применить для идентификации классов и объектов при проектировании сложной системы программного обеспечения.
160 Часть I. Концепции Объектно-ориентированный анализ Несмотря на то что границы между анализом и проектированием размыты, они имеют совершенно разные цели. На этапе анализа осуществляется первичное исследование задачи и моделирование реальности с помощью классов и объектов, образующих словарь предметной области. На этапе проектирования изобретаются абстракции и механизмы реализации принятого решения. В последующих разделах рассматриваются многочисленные проверенные практикой подходы к анализу объектно-ориентированных систем. Классические подходы Многие исследователи предлагали разнообразные источники классов и объектов, согласованных с требованиями предметной области. Этот подход называется классическим (classical), поскольку в его основе лежат принципы классической категоризации. Например, Шлаер (Sclaer) и Меллор (Mellor) предложили следующие источники классов и объектов [28]. • Материальные пред- Автомобили, телеметрические данные, датчики меты • Роли • События • Взаимодействие давления. Мать, учитель, политик. Посадка, прерывание, запрос. Заем, встреча, пересечение. Для моделирования баз данных Росс (Ross) предложил аналогичный список [29]. • Люди • Места • Предметы • Организации Понятия События Индивидуумы, выполняющие некоторые функции. Области, связанные с людьми или предметами. Материальные объекты или группа объектов. Формально организованные совокупности людей, ресурсов и оборудования, имеющих определенную цель и, в целом, не зависящих от индивидуумов. Принципы и идеи, используемые для организации деятельности и/или мониторинга и/или обмена информацией. То, что происходит в определенный момент времени или последовательно.
Глава 4. Классификация 161 Коад (Coad) и Йордон (Yourdon) предложили свой список источников потенциальных объектов [30]. • Структуры • Другие системы • Устройства • Памятные события • Разыгрываемые роли • Места • Организационные единицы На более высоком уровне абстракции Коад ввел понятие предметной области, состоящей их логически связанных групп классов, относящихся к высокоуровневым функциям системы. Анализ характеристик В отличие от классических подходов, концентрирующих внимание на материальных элементах предметной области, альтернативные методы объектно- ориентированного анализа сосредоточены на динамических характеристиках как на первоисточнике классов и объектов1. Это напоминает концептуальную кластеризацию: классы образуются из групп объектов, демонстрирующих сходное поведение. Вирфс-Брок (Wirfs-Brock), Уилкерсон (Wilkerson) и Винер (Wiener), например, делают акцент на обязанностях (responsibilities), под которыми подразумеваются "знания объекта и действия, которые он способен выполнять. Обязанности — это средство выражения предназначения объекта и его места в системе. Обязанности объекта представляют собой совокупность всех услуг, которые он может предоставлять согласно договоренностей" [32]. Иначе говоря, в группы объединяются объекты, имеющие общие обязанности, а иерархии состоят из классов, связанных ^лаер (Shlaer) и Меллор (Mellor) дополнили свою более раннюю работу, чтобы учесть поведение объектов. В частности, они изучали жизненный цикл объекта как средство определения его границ [31]. Отношения "является" ("is а") и "является частью" ("part of). Внешние системы, с которыми взаимодействует приложение. Устройства, с которыми взаимодействует приложение. События, которые необходимо запомнить. Роли, которые исполняют пользователи, работающие с приложением. Здания, офисы и другие места, существенные для работы приложения. Группы, к которым принадлежат пользователи.
162 Часть I. Концепции с суперклассами, описывающими общие обязанности, и подклассами, уточняющими их поведение. Рубин (Rubin) и Голдберг (Goldberg) предлагают идентифицировать классы и объекты, исходя из функций системы. Они предлагают "в первую очередь понять, что происходит в системе. Это позволит понять ее функции. Затем эти функции следует сопоставить с частями системы и попытаться понять, кто инициирует функцию и кто участвует в ее реализации... Инициаторы и участники, играющие существенные роли, опознаются как объекты, и на них возлагаются обязанности за выполнение этих ролей" [33]. Концепция Рубина тесно связана с понятием функциональной точки (functional point), предложенным Албрехом (Albrech) в 1979 году. Согласно его определению, функциональная точка — это "отдельное бизнес-действие конечного пользователя" [34], т.е. вывод, запрос, ввод, запись или соединение. Несмотря на то что эта концепция происходит из области информационных систем, она может быть обобщена для любой автоматизированной системы. По существу, функциональная точка — это любое значимое, видимое извне и поддающееся проверке поведение системы. Анализ предметной области Рассмотренные выше принципы обычно применяются для разработки отдельных специфических приложений. С другой стороны, цель анализа предметной области состоит в идентификации классов и объектов, общих для всех приложений, относящихся к данной сфере знаний, например, ведению историй болезни пациентов, торговле ценными бумагами, разработке компиляторов или систем управления ракетами. Проектировщик, застрявший на середине пути в поисках новых идей, с помощью анализа узкой предметной области может найти основные ключевые абстракции, доказавшие свою полезность в аналогичных системах. Анализ предметной области работает хорошо, за исключением редких, действительно уникальных программных систем. Идею анализа предметной области впервые предложил Нейборс (Neighbors). Он определил анализ предметной области как "попытку идентифицировать объекты, операции и отношения, которые эксперты считают наиболее важными" [35]. Мур (Moore) и Байлин (Bailin) выделили следующие этапы анализа предметной области. • Построение модели предметной области в ходе консультаций с экспертами в этой области. • Изучение систем, существующих в данной предметной области, и представление результатов в стандартном виде. • Идентификация сходства и различий между системами при участии экспертов предметной области.
Глава 4. Классификация 163 • Уточнение обобщенной модели по существующим системам [36]. Анализ предметной области можно вести среди аналогичных приложений (вертикальный анализ) или среди аналогичных частей того же самого приложения (горизонтальный анализ). Например, начиная проектирование системы мониторинга состояния пациентов, целесообразно изучить архитектуру существующих аналогов, чтобы понять смысл и оценить полезность основных абстракций и механизмов, использованных в них. Аналогично система бухгалтерского учета должна поддерживать разные виды отчетов. Если считать отчеты в рамках конкретного приложения отдельной предметной областью, то их анализ может привести разработчика к идентификации основных абстракций и механизмов, обслуживающих все виды отчетов. Полученные таким образом классы и объекты представляют собой совокупность основных абстракций и механизмов, обобщающих решение исходной задачи. Таким образом, итоговый проект, вероятно, станет проще по сравнению с проектом, построенным на основе анализа отдельных отчетов. Кого следует считать экспертом в предметной области? Часто в роли эксперта выступает обычный пользователь системы, например, инженер или диспетчер железной дороги, а также медсестра или доктор, работающие в больнице. Эксперт не обязан быть программистом. Просто он должен хорошо знать все аспекты исследуемой проблемы и свободно оперировать понятиями из словаря предметной области. Отдельных менеджеров отпугивает идея о прямом контакте между разработчиками и конечными пользователями (некоторые из них приходят в ужас от одной только мысли дать конечному пользователю возможность увидеть программиста!). Для очень сложных систем анализ предметной области является формальным процессом, требующим участия большого количества экспертов и разработчиков в течение длительного периода времени. Такой формальный анализ не обязательно проводить при разработке всех проектов, особенно небольших. Обычно для уточнения задачи достаточно короткой встречи экспертов в предметной области и архитектором или проектировщиком. Удивительно, как мало информации нужно для того, чтобы принять разумное решение. Действительно, такие встречи очень полезны на протяжении всего проекта. Анализ прикладной области редко носит целостный характер. Для того чтобы повысить его эффективность, следует осознанно выбрать небольшой фрагмент прикладной области, проанализировать его, принять проектное решение и перейти к исследованию другой части. Анализ прецедентов использования Классический подход, исследование поведения и анализ предметной области сильно зависят от индивидуального опыта аналитика. Для большинства проектов это неприемлемо, поскольку результат анализа в такой ситуации непредсказуем.
164 Часть I. Концепции Однако существует подход, который в сочетании с тремя указанными выше методами позволяет упорядочить анализ. Этот метод, названный анализом прецедентов (use case analysis), впервые был формализован Джекобсоном (Jacob- son). В работе Джекобсона и его соавторов было сформулировано следующее определение прецедентов использования: "Последовательность взаимосвязанных операций, выполняемых действующим субъектом в диалоге с системой для достижения некоторой цели, допускающей применение количественного критерия успеха" [37]. Анализ прецедентов использования можно применять на этапе изучения требований, когда конечные пользователи, другие эксперты предметной области и группа разработчиков перечисляют сценарии, наиболее важные для функционирования системы. (Сначала достаточно просто перечислить эти сценарии, не вдаваясь в детали.) В совокупности эти сценарии описывают все функции приложения. Затем каждый сценарий тщательно исследуется. Иногда для этого их раскладывают на эпизоды, как фильм. [38]. Изучая сценарий, группа должна идентифицировать объекты, участвующие в сценарии, а также определить их обязанности и способы взаимодействия в терминах выполняемых операций. Таким образом, группа разработчиков вынуждена четко разделить сферы влияния всех абстракций. По мере развития процесса проектирования группа расширяет набор первоначальных сценариев, вводя новые абстракции или добавляя, модифицируя и перераспределяя обязанности между существующими абстракциями. Кроме того, сценарии служат основой для тестирования систем. CRC-карточки CRC-карточки — это простой и удивительно эффективный метод анализа сценариев2. CRC-карточки, которые впервые предложили использовать Бек (Beck) и Каннингхэм (Cminingham) как средство обучения объектно-ориентированному программированию [39], оказались полезным инструментом для проведения мозговых штурмов и улучшения взаимодействия между разработчиками. CRC- карточка представляет собой обычные библиографические карточки размером 3x5 дюйма3, на которых аналитик сверху пишет карандашом имя класса, на одной половине — обязанности класса, а на другой — его сотрудников. На каждый класс, участвующий в сценарии, заводится отдельная карточка. Анализируя сценарий, проектировщики могут поручать новые обязанности существующим классам, группировать новые обязанности в новых классах, а также (чаще всего) разделять обязанности одного класса среди более мелких или делегировать их другому классу. 2Аббревиатура CRC означает Class/Responsibilities/Collaborators (Класс/Обязанности/Сотрудники). 3Если смета проекта допускает, купите карточки размером 5x7 дюймов. Очень удобны также разлинованные карточки, а разноцветные карточки — это признак очень "крутого" проектировщика.
Глава 4. Классификация 165 CRC-карточки можно упорядочивать так, чтобы представлять шаблоны взаимодействия. С точки зрения динамической семантики сценария, карточки позволяют демонстрировать потоки сообщений между прототипами экземпляров каждого класса, а с точки зрения статической семантики они представляют иерархии классов, связанных отношениями обобщения/специализации или агрегации. Неформальное описание Радикальная альтернатива классическому объектно-ориентированному анализу была выдвинута Эбботтом (Abbott), предложившим описывать задачу (или ее часть) на английском языке, а затем подчеркивать существительные и глаголы [40]. Существительные являются кандидатами на роль классов, а глаголы — на роль операций. Подход Эбботта полезен, так как он прост и стимулирует разработчика работать со словарем предметной области. Однако этот метод не имеет средств для строгого анализа и совершенно непригоден для решения сложных проблем. Человеческий язык — весьма неточное средство выражения мыслей, потому качество итогового списка объектов и операций зависит от писательского таланта разработчика. Более того, любое существительное имеет соответствующую глагольную форму и наоборот, следовательно, список кандидатов может быть смещен в сторону объектов или операций. Структурный анализ Многие организации пытались использовать в качестве основного инструмента объектно-ориентированного проектирования структурный анализ. Этот подход кажется привлекательным уже хотя бы потому, что много аналитиков имеют опыт структурного анализа, и существует большое количество программных CASE-средств, поддерживающих автоматизацию этих методов. Однако наш личный опыт структурного анализа для объектно-ориентированного проектирования оказался неудачным. Структурный анализ начинается с создания принципиальной схемы системы, описанной диаграммами потоков данных и другими средствами структурного анализа. Эти диаграммы позволяют создать формальную модель проблемы. Основываясь на этой модели, можно идентифицировать классы и объекты, относящиеся к предметной области, используя один из следующих трех методов. Макменамин (McMenamin) и Палмер (Palmer) предлагают начинать структурный анализ с изучения словаря данных и анализа контекстных диаграмм модели. "Рассматривая список основных элементов данных, следует подумать, о чем они говорят или что описывают. Например, если в предложение входят прилагательные, то к каким существительным они относятся? Ответы на эти вопросы помогут заполнить список кандидатов на роль объектов" [41]. Эти кандидаты на роль
166 Часть I. Концепции объектов происходят из окружающей среды, из основных входных и выходных данных, а также продуктов, услуг и других ресурсов системы . Следующие два способа основаны на анализе отдельных диаграмм потоков данных. По отдельной диаграмме потоков данных (в терминологии Уарда (Ward) и Меллора (Mellor) [42]) кандидаты на роль объектов можно найти среди следующих сущностей: • внешние сущности; • наборы данных; • наборы средств управления; • управляющие преобразования. Источники кандидатов в классы перечислены ниже: • потоки данных; • потоки управления. Преобразования данных можно рассматривать либо как операции, либо как существующие объекты, либо как характеристики объектов, создаваемых специально для выполнения этих преобразований. Зайдевиц (Seidewitz) и Старк (Stark) предложили другой метод, который они назвали анализом абстракций (abstraction analysis). Этот метод предназначен для идентификации основных сущностей, которые по своей природе аналогичны основным преобразованиям в структурном проектировании. "В структурном анализе входные и выходные данные изучаются до тех пор, пока не достигнут высшего уровня абстракции. Основными преобразованиями считаются процессы переработки входных данных в выходные. В анализе абстракций разработчик делает то же самое, но, кроме этого, он изучает основное преобразование для того, чтобы определить, какие процессы и состояния образуют наилучшую абстрактную модель системы" [43]. После идентификации основной сущности в конкретной диаграмме потоков данных аналитик приступает к изучению всех остальных сущностей, прослеживая входящие и исходящие из центра потоки данных, группируя процессы и состояния, встречающиеся по пути. Зайдевиц и Старк пришли к выводу, что анализ абстракций слишком сложен для успешного практического применения и в качестве альтернативы предложили объектно-ориентированный анализ [44]. Необходимо подчеркнуть, что принципы структурного проектирования, которое, как правило, сочетается со структурным анализом, полностью ортогональны принципам объектно-ориентированного проектирования. Опыт показывает, что использование структурного анализа в процессе объектно-ориентированного проектирования часто приводит к полному провалу, если разработчик не способен сопротивляться соблазну структурного проектирования. Другая очень серьезная
Глава 4. Классификация 167 опасность заключается в том, что многие аналитики любят рисовать диаграммы потоков данных, представляющие собой скорее описание проекта, а не сущностную модель задачи (essential model). Чрезвычайно трудно построить объектно- ориентированную систему на основе модели, столь сильно ориентированной на алгоритмическую декомпозицию. По этой причине для объектно-ориентированного проектирования более предпочтительным является объектно-ориентированный анализ, позволяющий уменьшить риск испортить проект надуманными элементами алгоритмического анализа. Если по каким-либо уважительным причинам4 разработчик вынужден использовать структурный анализ, необходимо немедленно прекратить создание диаграмм, как только они начинают напоминать проект, а не сущностную модель. Кроме того, как только проектирование зайдет достаточно далеко, следует отказаться от методов структурного анализа. Помните, что средства проектирования, такие как диаграммы потоков данных, — это не конечный продукт, а инструменты, с помощью которых разработчики выражают свое понимание задачи и способы ее решения. Обычно проектировщики рисуют диаграммы, а затем изобретают механизмы реализации требуемого поведения системы. Как показывает практика, сам процесс проектирования изменяет точку зрения разработчиков на задачу. Следовательно, следует применять только средства структурного анализа, относящиеся к достаточно высокому уровню абстракции. Именно они позволяют адекватно описать сущностную модель задачи и, благодаря этому, применяются во многих проектах. 4.3 Основные абстракции и механизмы Основная абстракция (key abstraction) — это класс или объект, входящий в словарь проблемной области. Главный смысл основных абстракций состоит в том, что они очерчивают границы задачи: подчеркивают элементы, входящие в систему и потому относящиеся к проекту, и отбрасывают избыточные сущности. В предыдущей главе термин механизм (mechanism) использовался для описания любой структуры, в которой объекты взаимодействуют друг с другом для обеспечения поведения, удовлетворяющего требованиям задачи. Проект класса содержит априорные знания о поведении объектов, а механизм — это проектное решение, касающееся способа взаимодействия между совокупностью объектов. Рассмотрим процесс идентификации и уточнения основных абстракций и механизмов. Разумеется, политические и исторические причины уважительными не считаются.
168 Часть I. Концепции Идентификация основных абстракций Идентификация основных абстракций сильно зависит от предметной области. По мнению Голдберг (Goldberg), "правильный выбор объектов зависит от цели приложения и глубины детализации обрабатываемой информации" [45]. Как отмечалось выше, идентификация основных абстракций включает в себя два процесса: открытие и изобретение. Открытие позволяет распознавать абстракции, используемые экспертами предметной области, поскольку обычно они упоминают лишь важные абстракции [46]. С помощью изобретения проектировщики создают новые классы и объекты, не обязательно являющиеся частью предметной области, но полезные при проектировании или реализации системы. Например, пользователь банкомата оперирует словами "счет", "депозит" или "снятие денег со счета". Эти термины образуют часть словаря предметной области. Разработчик такой системы использует те же самые абстракции, но обязан добавлять свои, такие как "базы данных", "диспетчеры экрана", "списки", "очереди" и т.д. Эти основные абстракции являются продуктом конкретного проекта, а не предметной области. Уточнение основных абстракций Определив кандидатов на роли основных абстракций, необходимо оценить их соответствие критериям, описанным в предыдущих главах. Страуструп (Strous- trup) пишет: "Часто это значит, что программист должен ответить на несколько вопросов. Как создаются объекты данного класса? Можно ли копировать и/или уничтожать объекты данного класса? Какие операции можно выполнять над такими объектами? Если ответы на эти вопросы неудовлетворительны, то вполне вероятно, что соответствующее понятие слишком туманно, так что стоит еще раз продумать задачу, прежде чем приступать к программированию" [47]. Идентифицировав новую абстракцию, необходимо найти ее место в иерархии уже существующих классов и объектов. Эту задачу невозможно решить только методом нисходящего или восходящего анализа. Халберт (Halbert) и О'Брайен (O'Brien) утверждают: "Нет необходимости строить иерархию классов, начиная с суперкласса и дополняя ее подклассами. Обычно создаются несколько внешне разных типов, осознается их связь, затем их общие характеристики описываются в одном или нескольких суперклассах... и этот процесс повторяется несколько раз, пока не возникнет полный и корректный проект программы" [48]. Эта рекомендация является результатом эмпирических наблюдений, подтверждающих, что объектно-ориентированное проектирование представляет собой итерационный процесс. К аналогичным выводам пришел и Страуструп: "Наиболее частые реорганизации в иерархиях классов — это выделение общих частей двух классов в новый класс и разделение класса на два новых" [49].
Глава 4. Классификация 169 Классы и объекты должны находиться на соответствующем уровне абстракции: не слишком высоко и не слишком низко Разместить классы и объекты на правильных уровнях абстракции довольно трудно. Иногда, определив общий подкласс, проектировщик может передвинуть его вверх в структуре классов, увеличив степень его совместного использования. Этот процесс называется продвижением класса (class promotion) [50]. Аналогично, может оказаться, что некий класс обладает слишком общими свойствами, что затрудняет наследование из-за большого семантического разрыва. Это явление называется конфликтом детализации (grainsize conflict) [51]. В обоих случаях необходимо выявить связанность или слабую связность абстракций, и разрешить конфликт. Название основных абстракций Несмотря на то что большинство проектировщиков часто легкомысленно относятся к выбору правильных имен для классов и объектов, отражающих их семантику, очень важно отразить в именах сущность описываемых абстракций. Программы необходимо писать так же тщательно, как художественное произведение, думая и о читателях, и о компьютере [52]. Представьте себе все имена, с помощью которых можно идентифицировать отдельный объект: его собственное
170 Часть I. Концепции имя, имя его класса и имя модуля, в котором этот класс объявлен. Умножьте это количество на тысячу объектов и сотни классов, и вы поймете масштаб проблемы. Мы предлагаем следующие правила. • Объекты следует называть существительными: например, theSensor или shape. • Классы следует называть обобщенными существительными: например, Sensors или Shapes. • По возможности, выбранные имена должны соответствовать терминам, используемым экспертами предметной области. • Операции, модифицирующие данные, следует называть активными глаголами: например, Draw или moveLef t. • Имена операций выбора должны подразумевать запрос или состояние: extentOf или isOpen. • Подчеркивание и заглавные буквы можно использовать по своему усмотрению. Внешний вид имен не важен — главное, чтобы программа не была противоречивой. Идентификация механизмов Рассмотрим системное требование, предъявляемое к автомобилю: нажатие на педаль акселератора должно приводить к увеличению оборотов двигателя, а отпускание этой педали — к их уменьшению. Как это происходит на самом деле, водителю совершенно безразлично. В автомобиле может быть использован любой механизм, обеспечивающий требуемое поведение, и поэтому выбор его реализации предоставляется на усмотрение разработчика. Например, можно принять любое из перечисленных ниже проектных решений. • Прямая механическая связь между акселератором и карбюратором. • Электронный механизм, соединяющий датчик давления, расположенный под акселератором, с компьютером, управляющим топливным инжектором (проводной механизм). • Отсутствие связей. Бак с горючим размещается на крыше автомобиля и топливо течет в двигатель под влиянием силы тяжести. Поток топлива регулируется зажимом на бензопроводе. Нажатие на педаль акселератора ослабляет зажим и ускоряет течение топлива (очень дешевый механизм). Выбор альтернативных механизмов зависит от таких параметров, как стоимость, надежность, технологичность и безопасность. Выход объектов за пределы правил и ограничений, заданных конкретным механизмом, неприемлем точно так же, как нарушение правил взаимодействия меж-
Глава 4. Классификация 171 ду объектами. Водитель был бы удивлен, если бы, нажав на педаль акселератора, он включил фары, а не увеличил обороты двигателя. В то время как основные абстракции отражают словарь проблемной области, механизмы определяют дух проекта. В процессе проектирования разработчик должен придумать не только представление классов, но и способы взаимодействия между их объектами. Здесь на помощь проектировщику вновь приходит анализ сценариев. Выбрав конкретный шаблон взаимодействия, проектировщик должен распределить работу среди многих объектов, обозначив подходящие методы. В итоге протокол отдельного класса описывает все операции, реализующие все его поведение и все механизмы, связанные с каждым из его экземпляров. Таким образом, механизмы представляют собой стратегические проектные решения, аналогичные выбору структуры классов. В противоположность этому, проектирование интерфейса отдельного класса носит тактический характер. Стратегические решения должны быть сделаны явно, иначе проект станет сборищем изолированных объектов, конфликтующих друг с другом и выполняющих свое задание без оглядки на других. В наиболее элегантных, стройных и быстрых программах воплощены тщательно продуманные механизмы. Механизмы — это средства, с помощью которых объекты взаимодействуют друг с другом для реализации поведения более высокого уровня
172 Часть I. Концепции Механизмы как шаблоны Механизмы представляют собой разновидность шаблонов, существующих в структурированных системах. На нижнем конце этой цепочки находятся идиомы — выражения, присущие конкретным языкам программирования или предметным областям и отражающие общепринятые способы использования языка5. Например, в языке CLOS не принято использовать подчеркивание в именах функций или переменных, как в языке Ada [53]. Изучение идиом — неотъемлемая часть овладения языком. Как правило, они передаются от программиста к программисту в форме фольклора. Однако, как отметил Коплиен (Coplien), идиомы играют важную роль в систематизации шаблонов низкого уровня. Он заметил, что "многие действия программистов являются идиоматическими" и поэтому идентификация таких идиом позволяет "использовать конструкции языка C++ для выражения функциональности, выходящей за рамки самого языка, с сохранением иллюзии, что они являются частью языка" [54]. В то время как идиомы являются частью программистской культуры, на верху цепочки расположены среды разработки (framework) — совокупности классов, предназначенных для определенной прикладной ситуации. Таким образом, среда разработки поставляет готовые классы, механизмы и услуги, которые клиент может использовать или адаптировать. Среды разработки в основном обеспечивают возможность повторного использования классов. Часто они являются коммерческими продуктами, как, например, среда .NET компании Microsoft, или открытыми проектами, как среда Apache Software Foundation's Struts и Junit (авторы — Эрих Гамма (Erich Gamma) и Кент Бэк (Kent Beck)). Примеры механизмов Рассмотрим механизм рисования, широко используемый в графических интерфейсах пользователя. Для того чтобы представить графический элемент на экране, необходимо взаимодействие нескольких объектов: окно, представление, представляемая модель и клиент, который знает, когда надо вывести эту модель на экран, но не имеет понятия, как это сделать. Сначала клиент просит окно нарисовать себя. Так как окно может иметь несколько представлений, оно в свою очередь приказывает каждому из них нарисовать себя. Каждое представление посылает сообщение своей модели нарисовать себя, в результате чего и появляется изображение на экране. В этом механизме модель полностью отделена от окна и своего представления в соответствии с парадигмой "модель-представление-контроллер" (model-view-controller — MVC) [55]. 5 Игнорирование или неправильное использование идиомы влечет немедленные социальные последствия: вы превращаетесь в деревенщину или, еще хуже, в дилетанта, не заслуживающего уважения.
Глава 4. Классификация 173 Таким образом, механизмы обеспечивают более высокий уровень повторного использования кода по сравнению с повторным использованием отдельных классов. Например, парадигма MVC широко используется в пользовательском интерфейсе языка Smalltalk. Эта парадигма, в свою очередь, строится на основе механизма зависимостей (dependency mechanism), встроенного в поведение базового класса Model языка Smalltalk и пронизывающего большую часть библиотеки классов языка Smalltalk. Примеры механизмов и шаблонов можно найти практически во всех предметных областях. Например, структуру операционной системы можно описать на высоком уровне абстракции с помощью механизмов диспетчеризации программ. В системах искусственного интеллекта используются разнообразные механизмы систем, реализующих механизм рассуждений (reasoning systems). Одной из наиболее распространенных парадигм является механизм "доски объявлений" (blackboard mechanism), которую каждый индивидуальный источник знаний заполняет независимо от других. В таком механизме не существует центрального управления, но любое изменение "доски объявлений" может явиться стимулом для поиска нового способа решения поставленной задачи [56]. Коад (Coad) похожим образом идентифицировал ряд общих механизмов в объектно-ориентированных системах, включая шаблоны временных ассоциаций (patterns of time associations), регистрацию событий (event logging) и широкую рассылку сообщений (broadcasting) [57]. Во всех перечисленных вариантах эти механизмы проявляются не как индивидуальные классы, а как структуры взаимодействующих классов. Эти рассуждения завершают изучение методов классификации и понятий, лежащих в основе объектно-ориентированного проектирования. Следующие три главы посвящены самой системе обозначений, процессу и прагматике объектно- ориентированного проектирования. Резюме • Идентификация классов и объектов представляет собой важнейшую задачу объектно-ориентированного анализа и проектирования; идентификация состоит из открытия и изобретения. • Классификация — это, по существу, проблема кластеризации. • Классификация — это итерационный процесс; трудности классификации обусловлены тем, что существует много равноправных способов. • Существуют три подхода к классификации: классическая категоризация (классификация по свойствам), концептуальная кластеризация (классификация по понятиям) и теория прототипов (классификация по схожести с прототипом).
174 Часть I. Концепции • Сценарии — это мощное средство объектно-ориентированного анализа. Его можно использовать в сочетании с другими методами: классического анализа, анализа поведения, анализа предметной области и анализа вариантов. • Основные абстракции отражают словарь предметной области. Их находят либо в предметной области, либо изобретают в процессе проектирования. • Механизмы — это стратегические проектные решения, касающиеся взаимодействия разнообразных объектов.
ЧАСТЬ II Метод
Невозможно точно предсказать, какое новшество приведет проект к успеху, а какое — к провалу. Изобретая что-то новое, будь то мост, самолет или небоскреб, инженер имеет широкие возможности. Он может просто скопировать все лучшее из существующих проектов, прошедших проверку временем, а может усовершенствовать то, что сочтет нужным. Генри Петроски, "Проектирование как человеческая деятельность" Для рыночного успеха любой технологии необходимо выполнить несколько условий. Во-первых, следует создать критическую массу пользователей, которым эта технология необходима. Это привлечет к ней инвестиции. Во-вторых, для того чтобы возник потребительский рынок, очень желательно, чтобы знания, относящиеся к предлагаемой технологии, легко осваивались, расширялись и распространялись. Для того чтобы технология получила признание, необходимо описать способ ее использования (т.е. описать процесс) и продемонстрировать преимущества. Именно этому посвящена вторая часть книги, в которой описан стандартный язык (Unified Modeling Language), процесс и прагматика объектно-ориентированного анализа и проектирования.
ГЛАВА 5 ОБОЗНАЧЕНИЯ Анализ и проектирование не ограничиваются составлением диаграмм. Они лишь позволяют описать поведение системы (для анализа) или показать детали архитектуры (для проектирования). Если понаблюдать за работой инженера — программиста, технолога, химика, архитектора и любого другого, — то можно быстро убедиться, что будущая система формируется исключительно в сознании разработчика. В ходе проектирования разработчики часто записывают свои решения на таких "высокотехнологичных" носителях информации, как доски, салфетки или конверты [1]. 5.1 Элементы обозначений Хорошо продуманная и выразительная система обозначений очень важна для разработки программного обеспечения. Во-первых, стандартная система обозначений позволяет аналитику или проектировщику описать сценарий или архитектуру, а затем доходчиво изложить свои решения другим людям. Символ транзистора на рисунке электрической схемы понятен инженерам-электрикам во всем мире. Аналогично, изучая чертежи здания, созданные нью-йоркскими архитекторами, строители в Сан-Франциско легко поймут, где следует расположить двери, окна или электрическую проводку. Во-вторых, как утверждает Уайтхед (Whitehead) в своей известной работе по математике, "Освобождая мозг от лишней работы, хорошая система обозначений позволяет ему сосредоточиться на более сложных задачах" [2]. В-третьих, выразительная система обозначений позволяет автоматизировать большую часть утомительной проверки согласованности и правильности проектных решений. В Отчете управления научных исследований Министерства обороны США (Defense Science Board) указывается: "Разработка программного обеспечения является трудоемкой работой и будет ею всегда... Хотя машины
178 Часть И. Метод могут выполнять рутинную работу и помогать людям отслеживать нить рассуждений, разработка понятий является прерогативой человека... Разработка концептуальных структур всегда будет неотъемлемой частью проектирования систем программного обеспечения, но проблем, связанных с их выражением, можно избежать" [3]. Краткий исторический очерк Система обозначений Unified Modeling Language (UML) — это язык моделирования, используемый для анализа, описания и разработки систем программного обеспечения. Как указывалось в главе 2, использование объектно-ориентированных языков программирования стимулировало появление объектно-ориентированных методологий проектирования. В конце 1980-х и начале 1990-х годов возникло множество методологий, которые впоследствии были модифицированы и уточнены. Многие из них оказались успешными в одних отраслях и потерпели неудачу в других. В результате перед специалистами возникла задача использования полезных аспектов разных методов. Эта ситуация привычна для практиков, применяющих объектно-ориентированный подход. Несмотря на то что в большинстве случаев практики придерживаются какой-то конкретной методологии, в своей повседневной работе они охотно подхватывают новые идеи. В середине 1990-х годов Буч (Booch), Рамбо (Rumbaugh) и Джекобсон (Ja- cobson) создали компанию Rational Software Corporation и стали пропагандировать свои методы. Это привело к появлению первой версии языка UML. Затем они объединили свои усилия с другими специалистами и компаниями, предлагая стандартный язык моделирования консорциуму Object Modeling Group (OMG), создающему и поддерживающему стандарты в компьютерной индустрии. В ноябре 1997 года консорциум OMG принял систему обозначений UML в качестве стандарта. С тех пор контроль над языком UML и его дальнейшее развитие относятся к компетенции группы OMG. За прошедшее время язык UML несколько раз подвергался ревизии. В книге описывается версия UML 2.O. Подробная история языка UML описана во многих книгах, перечисленных в приложении Б. Модели и представления Как и во многих других научных дисциплинах и видах искусства (например, электронике, химии, архитектуре, музыке), имеющих собственные системы обозначений для описания создаваемых продуктов, язык UML используется в объектно-ориентированном проектировании для моделирования (т.е. представления) разрабатываемой системы. В целом, построенная модель UML с определенной точностью описывает реальную систему, которая будет создана в результате реализации проекта. Однако в одной большой диаграмме невозможно охватить все
Глава 5. Обозначения 179 тонкие детали сложной программной системы. В языке UML существует множество разнообразных диаграмм, каждая из которых отражает определенный аспект системы. Клейн (Kleyn) и Гингрич (Gingrich) утверждают: "Необходимо понять как структуру, так и роль исследуемых объектов. Следует уяснить таксономическую структуру классов объектов, используемые механизмы наследования, индивидуальное поведение объектов и динамическое поведение системы в целом. Эта задача в чем-то аналогична показу теннисного или футбольного матча. Для правильного отражения происходящих событий при трансляции таких спортивных соревнований один и тот же момент следует показать с разных точек зрения. Каждая камера передает свой аспект происходящего, недоступный другим камерам" [4]. Рассмотрим, например, приложение, состоящее из нескольких сотен классов. Часто невозможно, а на самом деле и не нужно, создавать одну диаграмму, демонстрирующую все эти классы и все отношения между ними. Вместо этого следует использовать несколько диаграмм классов, каждый из которых отражает разные аспекты модели. Одна диаграмма должна показывать отношения наследования между основными классами, а другая — транзитивное замыкание всех классов, используемых в конкретном классе. Если модель стабильна (т.е. находится в устойчивом состоянии (steady state)), то такие диаграммы остаются семантически согласованными друг с другом и с моделью. Например, если в ходе некоего взаимодействия (описанного в объектной диаграмме) объект А передает сообщение Μ объекту В, то сообщение Μ должно быть определено в классе В явно или неявно. В соответствующей диаграмме классов должно быть отражено соответствующее отношение между классами А и В, так чтобы экземпляры класса А на самом деле могли посылать сообщение Μ экземплярам класса В. Все сущности, имеющие одно и то же имя на всех диаграммах, относятся к одному и тому же элементу модели. Например, если класс С встречается на двух диаграммах одной и той же системы, то обе ссылки относятся к одному и тому же классу. Исключение из этого правила образуют лишь операции, имена которых могут быть перегружены. Таксономия диаграмм Диаграммы UML разделяются на две группы: структурные диаграммы и диаграммы поведения (рис. 5.1). Такая классификация соответствует концепции сложности, описанной в главе 1. Сложность системы зависит как от организации элементов системы (т.е. структуры), так и от способа их взаимодействия друг с другом (т.е. поведения).
180 Часть П. Метод Структурные диаграммы Диаграмма пакетов Диаграмма классов Диаграмма компонентов Диаграмма развертывания Диаграмма объектов Диаграмма композитных структуры Диаграммы поведения Диаграмма прецедентов использования Диаграмма деятельности Диаграмма конечных автоматов Диаграммы взаимодействий Диаграмма последовательностей Диаграмма обзора взаимодействий Диаграмма коммуникации Диаграмма синхронизации Рис. 5.1. Диаграммы UML Структурные диаграммы Эти диаграммы используются для демонстрации статической структуры элементов в системе. Они могут изображать архитектурную организацию системы, ее физические элементы, текущую конфигурацию, а также специфические элементы предметной области. К структурным диаграммам языка UML относятся следующие диаграммы. е Диаграммы пакетов (package diagram) е Диаграммы классов (class diagram) е Диаграммы компонентов (component diagram) е Диаграммы развертывания (deployment diagram) е Диаграммы объектов (object diagram) е Диаграммы композитных структур (composite structure diagram)
Глава 5. Обозначения 181 Структурные диаграммы часто используются в сочетании с диаграммами поведения для описания определенных аспектов системы. Каждый класс может иметь соответствующую диаграмму конечных автоматов (state machine diagram), описывающую поведение его экземпляров. Аналогично, совместно с диаграммами объектов, представляющих определенный сценарий, диаграммы взаимодействия (interaction diagram) демонстрируют моменты времени или порядок передачи сообщений по мере их вычисления. Диаграммы поведения Диаграммы, рассмотренные выше, носят статический характер. Однако события, происходящие в системах программного обеспечения, являются динамическими: объекты создаются и уничтожаются, объекты передают сообщения другим объектам и системам, внешние события активизируют операции над определенными объектами. Ничего удивительного, что описание динамического поведения с помощью статических средств, например, на листе бумаги, сталкивается со сложными проблемами. Однако это явление характерно практически для всех научных дисциплин. В объектно-ориентированном проектировании семантика динамического поведения и способы ее реализации описываются с помощью следующих средств. • Диаграмма прецедентов использования (use case diagram) • Диаграмма деятельности (activity diagram) • Диаграмма конечных автоматов (state machine diagram) • Диаграммы взаимодействий (interaction diagram) ■ Диаграмма последовательностей (sequence diagram) ■ Диаграмма коммуникации (communication diagram) ■ Диаграмма обзора взаимодействий (interaction overview diagram) ■ Диаграмма синхронизации (timing diagram) ■ Элементы языка UML, образующие эти диаграммы, рассмотрены далее. Практическое использование диаграмм Тот факт, что язык UML представляет собой подробную спецификацию, не означает, что необходимо постоянно использовать все его аспекты. На самом деле семантику большей части задач анализа и проектирования можно выразить с помощью подмножества этой системы обозначений. Это подмножество будет выделено в ходе описания системы обозначений. Следует ли беспокоиться о том, что некоторые детали остались за пределами этого подмножества? Иногда эти
182 Часть П. Метод элементы языка выражают важные тактические решения (как показано в приложениях). Кроме того, существуют определенные детали инфраструктуры языка UML, привнесенные поставщиками программных средств для облегчения синтеза и анализа систем. Такие внутренние детали позволяют осуществлять интеграцию внешних CASE-средств, поддерживающих эту систему обозначений со средами разработки программного обеспечения, предназначенных для работы с объектно- ориентированными языками. Как отмечает Вайнберг (Weinberg): "В некоторых областях, таких как архитектура, основным средством графического представления проекта являются эскизы, а точные детальные чертежи редко используются, пока не окончена творческая часть проектирования" [5]. Следует помнить, что обозначения — это только средство выражения размышлений о поведении и архитектуре системы, а не самоцель. Таким образом, следует пользоваться только самыми необходимыми элементами обозначений. Чересчур подробно описывать решение задачи так же вредно, как ставить слишком жесткие ограничения. Например, на чертеже архитектор может показать расположение выключателя света в комнате, но его точное место не будет определено, пока заказчик и прораб не проверят схему электропроводки. Было бы глупо заранее указывать на чертеже трехмерные координаты этого выключателя (разумеется, если это не является функционально важной деталью для заказчика: может быть, все члены его семьи имеют рост намного выше или ниже среднего). Таким образом, если аналитики, проектировщики и конструкторы относительно небольшой системы программного обеспечения обладают большим опытом и уже установили тесный рабочий контакт друг с другом, им будет достаточно эскиза (хотя и в этом случае, принимая архитектурное решение, необходимо учитывать проблемы последующей эксплуатации системы). На практике такая ситуация встречается редко. Если система очень велика и связана с интенсивным использованием программного обеспечения, а конструкторы недостаточно опытны или разделены пространством, временем или контрактом, то процесс проектирования необходимо описывать более подробно. Концептуальные, логические и физические модели В процессе проектирования модели системы могут иметь разные уровни детализации. Концептуальная модель описывает систему в терминах реальных или предполагаемых сущностей из предметной области, а также отношений между ними. На концептуальном уровне моделирование должно использовать терминологию предметной области и не должно зависеть от технологических проблем. Логическая модель системы использует понятия, вошедшие в концептуальную модель, а также устанавливает существование и смысл основных абстракций и механизмов, определяющих архитектуру системы и весь проект. Физическая модель системы описывает конкретное программное и аппаратное обеспечение,
Глава 5. Обозначения 183 необходимое для реализации системы. Очевидно, что физическая модель сильно зависит от технологической специфики. Со временем проект эволюционирует от концептуальной к логической и физической моделям. На каждом из этих этапов используются разные диаграммы. Некоторые диаграммы используются лишь на ранних стадиях проектирования, а другие — на протяжении всего проекта. Кроме того, на использование диаграмм влияет тип создаваемой системы. Например, система для торговли ценными бумагами, предназначенная для биржевого брокера, как правило, описывается большим количеством диаграмм конечных автоматов и диаграмм синхронизации, чем система, моделирующая чековую книжку. Концептуальная, логическая и физическая модели выражают результаты анализа и проектирования. В совокупности эти разные модели имеют богатую семантику. Они достаточно выразительны, для того чтобы охватить все интересные стратегические и тактические решения, необходимые на этапах анализа системы и формирования ее архитектуры. Кроме того, эти модели достаточно полны, для того чтобы обеспечить реализацию систем на практически любом объектно- ориентированном языке. Роль инструментов проектирования Обозначения, описанные в главе, можно использовать вручную, хотя проектирование крупных систем требует применения автоматизированных средств поддержки. Помимо всего прочего, любая система автоматического проектирования использует определенную систему обозначений, что позволяет даже плохим разработчикам быстрее создавать свои низкокачественные проекты. Высококлассные проекты создают опытные проектировщики, а не замечательные средства проектирования. Инструменты лишь позволяют проявиться индивидуальности, помогая разработчикам сосредоточиться исключительно на творческих задачах анализа и проектирования. Существуют вещи, которые автоматизированные системы проектирования могут делать хорошо, а есть вещи, которые они не умеют делать вообще. Инструменты проектирования обеспечивают проверку согласованности, ограничений и полноты, а также анализ моделей. Это позволяет разработчику свободно обозревать результаты анализа и проектирования. Например, взглянув на диаграмму компонентов, проектировщик может изучить конкретный механизм или локализовать все классы, связанные с определенным компонентом. Изучая диаграмму последовательностей, описывающую некий сценарий, разработчик может углубиться в иерархию наследования. Если исследуемый сценарий связан с активным объектом, то разработчик может использовать инструменты проектирования для идентификации процессора, через который проходит конкретный поток управления, а затем просмотреть анимацию конечного автомата, связанно-
184 Часть П. Метод го с этим процессором. Избавившись от необходимости удерживать в памяти все детали, связанные с анализом и проектированием, разработчик, использующий такие инструменты, может сосредоточиться лишь на творческой работе. С другой стороны, инструмент проектирования не может подсказать проектировщику, что необходимо изобрести новый класс или упростить структуру какого-то класса. Все это может сделать лишь человек. Можно было бы попытаться использовать для этого какую-нибудь экспертную систему, но для этого необходимы: 1) эксперт как в области объектно-ориентированного проектирования, так и в предметной области и 2) способность описывать эвристическую классификацию и большие общие знания. В ближайшем будущем такие полные и всезнающие системы не появятся. Тем не менее, реальные системы необходимо разрабатывать уже сейчас. Продукты объектно-ориентированного конструирования Как правило, анализ системы предусматривает изучение совокупности сценариев и диаграмм деятельности (для описания системы с помощью сценариев), диаграмм классов (для выражения ролей и обязанностей агентов, обеспечивающих определенные функции системы), а также диаграмм взаимодействия и/или диаграмм конечных автоматов (для демонстрации поведения агентов, обусловленного последовательностью событий). Аналогично, архитектура системы может состоять из набора диаграмм пакетов, классов, объектов, компонентов и развертывания, а также соответствующих динамических представлений. Между этими диаграммами существуют связи, позволяющие отслеживать требования в обратном направлении — от реализации к спецификации. Этот процесс начинается с диаграммы развертывания. Ее узел может изображать некий артефакт, представляющий собой компонент, определенный в конкретной диаграмме компонентов. В свою очередь, эта диаграмма компонентов может содержать определения совокупности классов, описанных в диаграмме классов. В заключение, определения отдельных классов ссылаются на некие сценарии и требования, поскольку эти классы в общем прямо отражают словарь предметной области. Пропорциональное увеличение или уменьшение Язык UML одинаково хорошо подходит для описания как небольших систем, состоящих из десятков классов, так и крупных систем, содержащих тысячи классов. Как показано в следующих двух главах, эта система обозначений особенно хорошо согласуется с итерационным подходом к проектированию. Не следует создавать диаграммы и откладывать их как нечто не подлежащее изменению. Наоборот, диаграммы должны постоянно уточняться с учетом новых проектных решений и выявленных деталей.
Глава 5. Обозначения 185 Кроме того, язык UML не зависит от каких-либо языков объектно-ориентированного программирования и может использоваться с любым из них. Синтаксис и семантика языка UML В оставшейся части главы описывается синтаксис и семантика языка UML в контексте объектно-ориентированного анализа и проектирования. Приводятся несколько небольших примеров использования этой системы обозначений на основе системы управления гидропонной теплицей, описанной в главе 2. В главе не объясняется процесс проектирования, на протяжении которого разрабатывались диаграммы на языке UML, поскольку эта тема рассматривается в главе 6. Порядок изложения диктуется последовательностью, в которой диаграммы языка UML 2.0 обычно появляются в процессе проектирования. Этот порядок является наиболее целесообразным, поскольку сначала следует рассмотреть все структурные диаграммы и лишь затем — диаграммы поведения. Итак, диаграммы описываются в следующем порядке. • Раздел 5.2 — диаграммы пакетов • Раздел 5.3 — диаграммы компонентов • Раздел 5.4 — диаграммы развертывания • Раздел 5.5 — диаграммы прецедентов использования • Раздел 5.6 — диаграммы деятельности • Раздел 5.7 — диаграммы классов • Раздел 5.8 — диаграммы последовательностей • Раздел 5.9 — диаграммы обзора взаимодействий • Раздел 5.10 — диаграммы композитных структур • Раздел 5.11 — диаграммы конечных автоматов • Раздел 5.12 — диаграммы синхронизации • Раздел 5.13 — диаграммы объектов • Раздел 5.14 — диаграммы коммуникации В части III каждая глава описывает разные виды приложений, использующих разные наборы соответствующих им диаграмм. Источники информации о языке UML 2.0 Система обозначений UML 2.0 является довольно обширной и сложной, о чем свидетельствует документ OMG UML 2.0 Specification. Для эффективного использования этого языка необходимо больше информации, чем изложено в главе. Если
186 Часть П. Метод после прочтения документа OMG UML 2.0 Specification и этой главы читатели пожелают расширить свои знания, они могут обратиться к справочнику The Unified Modeling Language Reference Manual, Second Edition. Кроме того, дополнительные источники информации о языке UML 2.0 перечислены в приложении Б. 5.2 Диаграммы пакетов В ходе объектно-ориентированного анализа и проектирования необходимо организовать артефакты так, чтобы они ясно представляли результаты исследования предметной области и принятые проектные решения. В разных ситуациях в центре внимания могут оказаться либо физическая структура визуальной модели либо представление элементов модели с нескольких точек зрения. Преимущества организованного представления элементов объектно-ориентированного анализа и проектирования перечислены ниже [32]. • Ясность и доступность процесса проектирования сложных систем • Поддержка параллельных моделей, используемых многими пользователями • Поддержка контроля версий • Поддержка абстракций на нескольких уровнях — от систем до классов внутри компонентов • Поддержка инкапсуляции и включения; поддержка модульности Основным средством, позволяющим изобразить организационную структуру проекта, являются диаграммы пакетов, с помощью которых можно представить сгруппированные элементы языка UML. Основными элементами диаграмм пакетов являются пакеты, их области видимости и зависимости между ними. Основы: обозначения пакетов Пакет UML представляет собой одно из двух основных обозначений, используемых в диаграммах пакетов. Вторым является отношение зависимости, которое будет описано далее. Пакет изображается в виде прямоугольника с ярлыком в левом верхнем углу. По правилам языка UML 2.0, если пакет не содержит никаких элементов UML, то его имя указывается внутри прямоугольника. Если же пакет содержит какие-либо элементы, то его имя должно размещаться внутри ярлыка. На рис. 5.2 изображена конкретная реализация правил именования пакетов. Здесь пакет HydroponicsGardeningSystem (Система управления гидропон-
Глава 5. Обозначения 187 ной теплицей)1 представлен в виде черного ящика, содержимое которого скрыто [35, 36]. HydroponicsGardenlngSystem | Рис. 5.2. Пакетное обозначение HydroponicsGardenlngSystem Когда количество элементов невелико (из-за небольшого размера системы или в результате укрупнения ее деталей), для элементов пакета используются соответствующие обозначения (пакет, прецедент использования, класс, компонент и т.д.). На рис. 5.3 изображен пакет HydroponicsGardeningSystem, содержащий два пакета. Слева показаны пакеты Planing (Планирование) и Greenhouse (Теплица), физически содержащиеся внутри пакета HydroponicsGardeningSystem. Справа продемонстрировано альтернативное обозначение отношения включения (containment relationship) [37, 38] I HydroponicsGardeningSystem | HydroponicsGardeningSystem : Planning | ! Greenhouse I ι l· 1 I ϊ | ' 1 | [ Рис. 5.З. Обозначение пакетов, содержащих элементы Основы: области видимости элементов Доступ к услугам, предоставляемым группами взаимодействующих классов внутри пакета, или, в общем, любыми элементами, содержащимися внутри пакета, определяется областью видимости отдельных элементов, включая вложенные ^ри переводе имен приняты следующие соглашения: названия пакетов, классов, объектов и других сущностей, представляющих собой часть программной реализации системы, не переводятся и сопровождаются пояснениями на русском языке, а условия, ограничения, состояния объектов, сценарии и прочие элементы проекта, относящиеся к предметной области и не являющиеся элементами языка UML, переводятся на русский язык. — Примеч. ред.
188 Часть П. Метод пакеты. Области видимости элементов, определенных внутри пакета как открытые или закрытые, распространяются как на вложенные элементы, так и на импортируемые. Концепция импортируемых элементов будет рассмотрена далее. Область видимости определяется вмещающим пакетом, образующим пространство имен для своих элементов. Благодаря этому каждый элемент, содержащийся в пакете, имеет уникальное имя, отличающее его, по крайней мере, от других элементов того же типа. Например, это значит, что не существует двух одноименных классов, содержащихся в одном и том же пространстве имен [39, 40]. Эти понятия будут рассмотрены при изучении концепций импорта и доступа. Элементы, считающиеся открытыми, могут рассматриваться как часть интерфейса пакета, поскольку они видны всем другим элементам. Элементы, объявленные закрытыми, остаются невидимыми для сущностей, расположенных вне вмещающего пакета. Определения открытых и закрытых элементов в пакете вместе с соответствующими обозначениями (в скобках) приведены ниже [41, 42]. • Открытый (+) Является видимым для элементов, размещенных внутри вмещающего пакета, включая вложенные пакеты, а также для внешних элементов. • Закрытый (-) Является видимым только для элементов, размещенных внутри вмещающего пакета, и вложенных пакетов. На диаграмме уровни доступа располагаются перед именем элемента, как показано на рис. 5.4. Класс GardeningPlan (План выращивания) является открытым и доступен для всех элементов, а класс PlanAnalyst (Аналитик) закрыт. Planning | +GardeningPlan -PlanAnalyst Рис. 5.4. Видимость элементов внутри пакета Planning
Глава 5. Обозначения 189 Основы: отношение зависимости Если элемент предоставляет определенный уровень доступа, то этот факт изображается с помощью отношения зависимости. Как указывалось ранее, отношение зависимости является вторым основным обозначением в диаграммах пакетов. Это отношение показывает, что некий элемент зависит от другого элемента, который выполняет его обязанности в системе. Зависимости между элементами UML (включая пакеты), как показано на рис. 5.5, изображаются с помощью пунктирных стрелок. Хвост стрелки размещается на зависимом элементе (клиенте), а острие — на элементе, поддерживающем зависимость (сервере). Тип зависимости иногда отражается с помощью метки, размещенной между элементами и представляющей собой ключевое слово, взятое в кавычки « », например, «import». Зависимости между элементами, размещенными внутри пакетов, разделяются на три вида: импорт (import), доступ (access) и слияние (merge), а зависимости между пакетами, связанными отношениями между содержащимися в них элементами, — на пять: отслеживание (trace), вывод (derive), уточнение (refine), разрешение (permit) и использование (use) [43]. Зависимости, существующие между пакетами, содержащими несколько элементов, объединяются на пакетном уровне. Зависимости между пакетами могут обозначаться ключевыми словами, указывающими тип и заключенными в кавычки « ». Однако если между элементами разных пакетов существуют разнотипные зависимости, зависимости между пакетами никак не обозначаются. На рис. 5.6 показаны зависимости между элементами, изображенными на рис. 5.5, поднятые на пакетный уровень. Обратите внимание на то, что две зависимости между отдельными элементами пакетов Planning (Планирование) и CropTypes (Виды растений) на пакетном уровне объединены в одну [44]. Основы: диаграммы пакетов До сих пор рассматривались следующие составные части диаграмм. • Пакетные обозначения • Видимость элементов • Отношение зависимости Диаграмма пакетов — это структурная диаграмма языка UML 2.0, в которой основными элементами являются пакеты и зависимости между ними. Однако, как показано на рис. 5.4 и 5.5, обозначения пакетов можно использовать и для описания структуры других элементов модели, например, классов. Кроме того, их можно использовать и не на структурных диаграммах. Этот факт уже упоминался, когда описывалась возможность использования диаграммы пакетов для организации прецедентов использования. Таким образом можно прояснить структуру очень сложных систем или разделить ее на части. Пример применения
190 Часть П. Метод 1 HydroponlcsGardenlngSystem Planning | -PlanAnalyst +PlanMetrlcs +GardeningPlan \ \ Ί L. \ \ Greenhouse \ \ 1 \ +EnvironmentalController CropTypes I —> r^ —_-, +CropEncyclopedia +CropDatabase Μ ~ "ΙΓ"" ι "i 1 } ШиШШШ41Ш^Ш| -LU- U-UJUI J-JU 1 I : 1 1 1 1 +Nutrltionist | f ' fi 1 Рис. 5.5. Обозначения зависимостей в системе Hydroponics- GardeningSystem диаграммы пакетов продемонстрирован на рис. 5.7, где пакеты используются для распределения прецедентов использования, связанных с классом Hydroponics- GardeningSystem по двум группам — операций и поддержки [45]. Действующие лица и прецеденты использования рассматриваются далее. Элементы, сгруппированные в пакете, должны иметь нечто общее, например, образовывать подсистему, совокупность связанных между собой прецедентов использования или классов, реализующих функции системы [46]. Какими критериями следует пользоваться при создании пакетов элементов? Существует много методов организации системы с помощью пакетов — по архитектурным слоям, по подсистемам, по пользователям (прецедентам использования) и т.д. Хорошо продуманные пакеты слабо связаны между собой и обладают высокой внутренней связанностью. Иначе говоря, взаимодействие между элементами внутри пакета должно быть более интенсивным, чем между пакетами. Кроме того, не следует обобщать иерархии и агрегации на пакеты [47]. Этот тезис также будет разъяснен далее.
Глава 5. Обозначения 191 HydroponlceGardeningSystem | Planning I """^ I J N Greenhouse -i^ ^ / CropTypes 1 • / • ' \ 1 ! ' 1 | | 1 | | Рис. 5.6. Агрегация зависимостей между элементами разных пакетов На каждый элемент, погруженный в пространство имен, можно ссылаться с помощью квалификатора, имеющего формат имя пакета: :имя элемента. Элементы, принадлежащие разным пространствам имен (т.е. включенные в разные пакеты), могут иметь одинаковые имена [48,49]. Эта идея позволяет уточнить концепцию импорта и доступа. Уточненная концепция: импорт и доступ Импорт и доступ представляют собой две стороны одной медали: импорт обеспечивает открытое включение элементов в пакет, а доступ — закрытое. Это значит, что элементы в импортирующем пакете, находящиеся в его области видимости, могут обнаружить импортируемые сущности. Однако если пакет реализует доступ к своим элементам, то никакие другие элементы не могут обнаружить сущности, импортируемые в пространство имен пакета. Эти сущности являются закрытыми; они невидимы извне пакета, реализующего механизм доступа [50, 51]. Естественно задать вопрос: зачем нужны механизмы импорта и доступа? Дело в том, что эти механизмы позволяют ссылаться на открытые элементы других пространств имен, не используя квалификаторы; импортирующий пакет автоматически добавляет имена к элементам, импортируемым в свое пространство имен. Однако если имена и тип импортируемых сущностей совпадают с именем и типом собственного элемента пакета, то они не будут включены в импортирующее пространство имен. Аналогично, если имена и тип импортируемых элементов из разных пространств имен совпадают, они не будут добавлены в импортирующее пространство имен [52, 53].
192 Часть П. Метод Садовник OperateHydroponicsGardeningSystem | / Управление \ V^ Специалист по удобрениям SupportHydroponlcsGardeningSystem | s—χ γ Просмотр \ Аналитик Рис. 5.7. Обозначение пакетов, используемых при разделении системы на части Импорт элементов пакета может быть широко- или узконаправленным. Это значит, что импортироваться могут как все элементы, так и специально выбранные. Вернемся к рис. 5.5, на котором изображен класс PlanAnalyst (Аналитик), зависящий от класса CropEncyclopedia (Справочник по растениям). Поскольку пакет Planning (Планирование) не импортирует пакет CropTypes (Виды растений) и не имеет доступа к нему, он должен использовать квалификаторы, например, для ссылки на класс CropEncyclopedia следует использовать имя HydronicsGardeningSystem::Crop::CropEnciclopedia.
Глава 5, Обозначения 193 HydroponJcsGaroteningSystem | ι Plans I 1 +GardeningPlan 1 1 j +PtaitMetf§cs щ 1 шттттшшшшштшптш 1 ^d CropTypes |^ «CropEncyctopedia 1 +CropDatabase Greenhouse •Cooler -Ught StorageTank | тиши +NutrieiitTartk +WaterTank 1 ■ 1 t 1 I 1 Рис 5-8. Импорт в пакет HydronicsGardeningSystem
194 Часть П. Метод Для того чтобы показать, что пакет Planning импортирует пакет Crop- Types, на диаграмме, изображенной на рис. 5.8, показана зависимость в виде пунктирной стрелки, помеченной меткой <<import>>. Это значит, что классы PlanAnalyst и PlanMetrics (Показатели плана) имеют доступ к классам CropEncyclopedia и CropDatabase (База данных по растениям), не используя квалификаторы. Для класса PlanMetrics это следует из того, что его пространство имен (пакет Plans) обеспечивает доступ к элементам пакета, в который он вложен. Кроме того, рис. 5.8 демонстрирует, что пакет Planning осуществляет закрытый импорт пакета Plans (Планы), о чем свидетельствует зависимость, помеченная надписью <<access». Это необходимо для того, чтобы обеспечить классу PlanAnalyst доступ к классам GardeningPlan (План выращивания) и PlanMetrics, не используя квалификаторы. Однако поскольку зависимость доступа является закрытой, импорт пакета Greenhouse в пакет Planning не дает увидеть элементы пакета Greenhouse, такие как класс Gardener, не прибегая к помощи квалификаторов. Кроме того, элементы пакета Greenhouse не могут видеть класс PlanAnalyst, поскольку этот класс скрыт в закрытом разделе. Анализ пакета Greenhouse (Теплица) показывает, что для именования элементов пакета StorageTank (Резервуар) класс Gardener (Садовник) должен использовать квалификаторы, поскольку его пространство имен не импортирует этот пакет. Например, для ссылки на класс Water Tank (Резервуар воды) следует использовать имя Storage: :WaterTank. Заглянув поглубже, можно увидеть элементы внутри пакета EnvironmentalController (Контроллер окружающей среды). Все они закрыты, т.е. невидимы за пределами своего пространства имен — пакета EnvironmentalController. Итак, имя без квалификатора (часто называемое простым именем) — это имя элемента, не содержащее никакой информации о пути к его местоположению в модели. Оно используется для доступа к следующим элементам пакета [54, 55]. • Собственные элементы • Импортируемые элементы • Элементы внутри вмещающего пакета Вложенный пакет может использовать имя без квалификатора для ссылки на содержание вмещающего пакета при любом уровне вложения. Однако если имя и тип элемента вмещающего пакета совпадают с именем и типом какого-либо элемента во вложенном пакете, следует использовать квалификатор. С точки зрения вмещающего пакета механизм доступа выглядит совершенно иначе — для того чтобы ссылаться на элементы вложенных пакетов, не используя квалификаторы, пакет должен импортировать их [56, 57].
Глава 5. Обозначения 195 53 Диаграммы компонентов Компонент — это повторно используемая часть программного обеспечения, реализующая определенное функциональное свойство системы. На самом нижнем уровне компонент представляет собой совокупность классов, тесно связанных между собой, но слабо связанных с другими группами классов. Каждый класс в системе должен существовать либо в отдельном компоненте, либо на верхнем уровне системы. Кроме того, компонент может содержать внутри себя другие компоненты. Компоненты — это разновидность структурированных классификаторов, внутреннюю структуру и функционирование которых можно изобразить в виде диаграммы компонентов. Компонент, взаимодействующий с другими компонентами с помощью четко определенных интерфейсов и реализующий определенное функциональное свойство системы, сам может состоять из компонентов, выполняющих свою собственную функцию. Таким образом, компоненты можно использовать для иерархической декомпозиции системы и представления ее логической архитектуры. Эта логическая точка зрения на компоненты является одним из новшеств, появившихся в языке UML 2.0. Ранее компоненты считались физическими единицами, из которых состоит система. Теперь же компонент можно интерпретировать как артефакт, размещенный в узле диаграммы [58, 59]. Основными элементами диаграммы компонентов являются компоненты, их интерфейсы и средства их реализации. Основы: обозначение компонентов Поскольку компонент — это структурированный классификатор, его детальную структуру можно изобразить с помощью частей, портов и соединителей. На рис. 5.9 продемонстрирован пример компонента EnvironmentalControlSys- tem. Этот компонент изображен в виде прямоугольника, в который полужирным шрифтом вписано имя компонента, выбранное проектировщиками. Кроме того, компонент сопровождается одним или двумя дескрипторами (tags): ключевым словом «component» и пиктограммой компонента, размещенной в правом верхнем углу прямоугольника [60, 61]. На границе прямоугольника, изображающего классификатор, показаны семь портов, представленных в виде маленьких квадратов. По умолчанию порты открыты для доступа. Кроме того, компоненты могут иметь скрытые порты. Эти порты также изображаются с помощью маленьких квадратов, но, в отличие от открытых портов, такие квадратики полностью размещаются внутри прямоугольника, соприкасаясь с его границей одной стороной. Скрытые порты могут использоваться для проверки точек, невидимых со стороны. Порты используются компонентами для взаимодействия с внешней средой и обеспечивают инкапсуляцию структу-
196 Часть П. Метод АтЫепПеглр GardentngPian М(|пипдыхпГО1 ι юшгдодмгшо! ыхятдыэгшхл Рис 5.9. Обозначение компонента EnvironmentalControlSystem рированного классификатора. Хотя на рис. 5.9 изображены безымянные порты, как правило, для повышения ясности диаграммы они должны иметь имя, имеющее формат имя порта : Тип Порта. В названии порта его тип указывать необязательно [62,63]. К портам, представленным на рис. 5.9, присоединены интерфейсы, обеспечивающие взаимодействие компонента с окружающей средой. Интерфейсы изображаются с помощью обозначений "штепсель-розетка" (ball-and-socket). Интерфейс, предоставляемый компонентом для обеспечения взаимодействия с внешней средой (provided interface), изображается в виде штепселя (ball), например, Light- ingControl (Управление освещением) на рис. 5.9. Интерфейс, который компонент требует от внешней среды (required interface), изображается как розетка (socket). Примером требуемого интерфейса является AmbientTemp (Температура) [64, 65]. Компонент EnvironmentalControlSystem (Система управления окружающей средой) показан как черный ящик, поскольку наблюдателю доступны лишь функциональные свойства, реализованные предоставляемыми и требуемыми интерфейсами. Невозможно затянуть внутрь этого компонента и увидеть инкапсулированные компоненты и классы, которые действительно обеспечивают его функционирование. Соответствие между портами и интерфейсами не обязательно должно быть взаимно-однозначным. Как показано на рис. 5.10, порты можно использовать для группировки интерфейсов. Например, группируя интерфейсы, можно прояснить очень сложные диаграммы или продемонстрировать желание иметь порт, обеспечивающий несколько видов взаимодействия. Так, один порт, изображенный на рис. 5.10, может запрашивать как освещенность, так и температуру окружающей среды. Аналогично, план выращивания и температурное расписание, поступающие от центра управления системой гидропонной теплицы, поступают через один
Глава 5. Обозначения WI и тот же пори Обратите внимание на то, что в этом случае имена интерфейсов разделяются запятыми. Демонстрируя сложные порты этой системы, следует указывать разные интерфейсы. Например, один порт системы содержит требуемые интерфейсы AmbientLight (Освещенность) и AmbientTemp (Температура), а другой — предусмотренные интерфейсы GardeningPlan (План выращивания) и TempRamp (Температурный график) [66,67]. AmbientLight, AmbieofTemp GanleningPlan, TempRamp ι ι a «component» τ г ugntinguontroi neennguoniroi иооипдиопшл Рис 5.10. Обозначение юмпонента с группами интерфейсов Основы: диаграмма компонентов Диаграммы компонентов позволяют отразить логическое расслоение и разбиение архитектуры проектируемой системы. С их помощью изображаются взаимные зависимости между компонентами, т.е. функциональные свойства системы, обеспеченные взаимодействующими компонентами, соединенными посредством четко определенных интерфейсов. Например, на рис. 5.11 продемонстрирована диаграмма компонентов системы EnvironmentalControlSys teiru Принцип "прозрачного ящика" позволяет продемонстрировать четыре инкапсулированных компонента, обеспечивающих его функционирование: EnvironmentalController (Контроллер окружающей среды), LightingController (Контроллер освещения), HeatingController (Контроллер обогрева) и CoolingController (Контроллер охлаждения) [68,69]. Для того чтобы различать предусмотренный и требуемый интерфейсы, на рис. 5.9 использовались обозначения ""штепсель-розетка". Эти интерфейсы, обеспечивающие связь между компонентами, называются сборочными соединениями (assembly connector), или интерфейсными соединениями (interface connectors).
198 Часть П. Метод AmbientTemp AmbientLight LightControl а «component» LlghtingController г Gardening Plan ш «component» EnvironmentalController Q HeatControl a «component» HeatingController I TempRamp I CoolControl \j CoolControl a «component» CoolingController Ϊ LightingControl HeatingControl CoolingControl Рис. 5.11. Диаграмма компонента EnvironmentalControlSystem Связь между компонентами можно было бы изобразить с помощью линии. Однако этот способ недостаточно информативен. Альтернативный подход продемонстрирован на примере интерфейса между компонентами EnvironmentalController и CoollingController. На самом деле эта зависимость является избыточной, поскольку имена интерфейсов совпадают: CoolControl (Управление охлаждением) [70, 71]. Ранее уже указывалось, что компоненты предназначены для повторного использования. Например, поскольку требования интерфейса компонента Light- ingController реализуются другим компонентом, то компонент Lighting- Controller можно заменить компонентом EnvironmentalControlSystem. Это свойство компонентов позволяет легко обновлять систему по мере необходимости. Фактически, заменить можно все содержимое компонента EnvironmentalControlSystem, поскольку его предусмотренные и требуемые интерфейсы реализуются его внутренними компонентами.
Глава 5. Обозначения 199 Основы: интерфейсы компонентов При необходимости описание интерфейсов компонента можно уточнить с помощью спецификаций, как показано на рис. 5.12. Рассмотрим два из семи интерфейсов компонента EnvironmentalControlSystem: CoolControl и Am- bientTemp [72, 73]. «interface» CoolControl + start() + stop() + setTemp() + setFanSpeed() «realize» ft- a «component» EnvironmentalController «use» 1. «interface» AmbientTemp + getAmbientTempO Рис. 5.12. Спецификация двух интерфейсов компонента EnvironmentalController Интерфейс CoolControl реализуется компонентом EnvironmentalControlSystem. Это значит, что именно компонент EnvironmentalControlSystem обеспечивает функциональные свойства, указанные интерфейсом: инициирование, завершение, установка температуры и установка скорости вращения вентилятора. Эти операции можно уточнить с помощью параметров и типов возвращаемых значений. Функциональные свойства этого интерфейса обусловлены компонентом CoolingController (см. рис. 5.11). На рис. 5.12 показана также зависимость компонента EnvironmentalController от интерфейса AmbientTemp. С помощью этого интерфейса компонент EnvironmentalController запрашивает температуру окружающей среды, необходимую для выполнения своих обязанностей в компоненте EnvironmentalControlSystem. На рис. 5.13 показано альтернативное обозначение интерфейсов компонента EnvironmentalController. На нем продемонстрированы три предусмотренных интерфейса, перечисленные в списке «provided interfaces». Кроме того, для интерфейса CoolControl, изображенного на рис. 5.12, показаны связанные с ним операции. В списке «required interfaces» перечислены
2M Часть П. Метод также требуемые интерфейсы, а в разделе «realizations» — три класса [74,75]. «component» EfivifOfMteiitalCofitrofler «provided interfaces» UghtControl HeatControl CoolControl startO stopO setTempi) setFanSpeedO «required interfaces» AmbtentUgM AmbJentTanp geiAmbientTempO GardeningPian TempRamp «realizations» Plan Controller Sensorlnput Рис. 5.13. Альтернативные обозначения интерфейсов и реализации компонента Environmental- Controller Основы: реализация компонентов На рис. 5.13 показано, что компонент EnvironmentalController состоит из классов Plan (План), Controller (Контроллер) и Sensorlnput (Показатели датчиков). Эти три класса обеспечивают все функции, предусмотренные требуемыми интерфейсами [76,77]. На рис. 5.14 показано отношение реализации между компонентом EnvironmentalController и классами Plan, Controller и Sensorlnput. Как видим, зависимость реализации существует между каждым из указанных классов и компонентов EnvironmentalController. Этот факт можно отразить в виде отношения включения, изображенного на рис. 5.15. Каждый из классов Plan, Controller и Sensorlnput физически содержится в компоненте EnvironmentalController. Имена, приписанные этим внутренним классификаторам, зависят от особенностей используемого программного обеспечения. Кроме того,
Глава 5. Обозначения 2tl следует упомянуть об отношении ассоциации между множественности [78]. Рмс5Л4. Зависимости ι ιEnvironmentalController Υ Pin Τ i Enririm телМСсмйгоЯсг Τ [ι τ SI Τ Ι Ι Рис 5.15. mentalController между Environ-
202 Часть П. Метод Уточненная концепция: внутренняя структура компонентов Внутреннюю структуру компонента можно показать с помощью диаграммы внутренней структуры (internal structure diagram). На рис. 5.16 продемонстрирована внутренняя структура подсистемы EnvironmentalController. В данном примере ключевое слово «component», использованное на рис. 5.9, заменено ключевым словом <<subsys tem», поскольку эта часть системы состоит из четырех довольно сложных компонентов, логически связанных между собой. Разумеется, это дело вкуса. В некоторых ситуациях ключевое слово «component» стоит оставить без изменения. Кроме того, рис. 5.16 содержит обозначение, которое до сих пор не встречалось, — метку «delegate» на линиях, соединяющих интерфейсы внутренних компонентов и порты подсистемы EnvironmentalController. Это позволяет показать, какие внутренние компоненты выполняют обязанности с помощью предоставляемых интерфейсов, а какие ожидают услуг, обеспечиваемых требуемыми интерфейсами [79, 80]. Подсистемы позволяют продемонстрировать логическую модель системы. Подсистема — это совокупность других подсистем и компонентов. Каждый компонент подсистемы должен существовать только в одной подсистеме или находиться на верхнем уровне системы. На практике крупные системы обычно изображаются одной диаграммой компонентов верхнего уровня, состоящими из подсистем, находящихся на высшем уровне абстракции. С помощью такой диаграммы проектировщик вникает в логическую архитектуру системы. Разделение на подсистемы более ярко выделяет возможность повторного использования компонента (или подсистемы) EnvironmentalControlSystem по сравнению с рис. 5.11. Порты, изображенные на границе подсистемы, показывают, что обязанности, предусмотренные интерфейсами, делегируются другим внутренним частям подсистемы. Однако следует помнить, что для выполнения своих "контрактов" эти внутренние части, в свою очередь, могут нуждаться в услугах внешней среды компонента EnvironmentalControlSystem, например, запрашивать план выращивания. Точнее говоря, компонент : EnvironmentalController запрашивает компонент GardeningPlan, уточняющий требования к окружающей среде (освещение, отопление и охлаждение). Запросы требуемого интерфейса направляются на безымянный порт, соединенный с интерфейсом GardeningPlan. Таким образом, проектировщик знает, что в системе следует предусмотреть компонент EnvironmentalControlSystem, содержащий план выращивания. Кроме того, компонент EnvironmentalControlSystem необходимо соединить с классами AmbientLight, AmbientTemp и TempRamp. Разъемы подсистемы EnvironmentalControlSystem обеспечивают ее связь как с окружающей средой, так и с внутренними компонентами. На рис. 5.16
Глава 5. Обозначения 203 AmbientTemp GardeningPlan AmbientLight «delegate» I TempRamp «component» :LlghtlngController «component» :HeatingController «component» :CoollngController ) LightingControl HeatingControl ) CoolingControl «delegate» «delegate» ΐ «delegate» LightingControl HeatingControl CoolingControl Рис. 5.16. Внутренняя структура компонента подсистемы EnvironmentalCon- troller показаны соединительные звенья делегирования (delegation connectors). С помощью этих соединений осуществляется связь между обязанностями (предусмотренными интерфейсами) подсистемы EnvironmentalControlSystem и ее запросами (требуемыми интерфейсами). Например, компонент : LightingControl совершенно очевидным образом выполняет обязанности интерфейса LightingControl (Управление освещением). По отношению к пользователям подсистема EnvironmentalControlSystem является непрозрачной [81, 82]. 5.4 Диаграммы развертывания Диаграммы развертывания (deployment diagram) используются для того, чтобы показать распределение артефактов по узлам физической схемы создаваемой
2t4 Часть П. Метод системы. Диаграмма развертывания позволяет изобразить физическую структуру систолы. На этапе проектирования диаграмма развертывания используется для представления физической совокупности узлов, служащей основой для реализации системы. Диаграммы развертывания состоят из трех основных элементов: артефактов, узлов и связей между ними. Основы: обозначение артефактов Артефакт — это физический элемент системы, реализующий часть программного проекта. Как правило, он представляет собой исполняемую программу, но может быть тагае текстовым файлом, документом или другим элементом системы, связанным с иодом программного обеспечения. Между артефактами могут существовать отношения зависимости (dependency) или объединения (composition), например, [10,11]. Артефакт изображается в виде прямоугольника, содержащего его имя, метку с ключевым словом «artefact» и пиктограмму в виде листка бумаги в правом верхнему ушу. Например, на рис. 5.17 показан артефакт HeatingController. ехе. . . . .. mr- ■**!.■ .JinИщи - -ίΓ^. i " ι a НшИнуГинЦцИн HeatingController.exe Имя артефакта включает в себя расширение .ехе. Это свидетельствует о том, что он представляет собой исполняемую программу. Между артефактом HeatingController . ехе и компонентом HeatingController (Контроллер обогрева) существует отношение зависимости, обозначенное меткой <<manifest>>. Это значит, что артефакт HeatingController. ехе осуществляет физическую связь этого компонента с остальной частью проекта.
Глава 5. Обозначения 205 Основы: обозначение узла Узел — это вычислительный ресурс, как правило, имеющий память и процессор, в котором размещен артефакт. Узлы, выполняющие сложную функцию, могут содержать другие узлы. Этот факт отражается в виде вложения или с помощью отношения объединения. Существуют два типа узлов: устройства и среды исполнения [13, 14]. Устройство — это часть аппаратного обеспечения, обладающая вычислительными возможностями, например, компьютер, модем или датчик. Среда исполнения — это программное обеспечение, предназначенное для развертывания существующих артефактов конкретного типа. Примерами сред исполнения являются «database» и «J2EE server». Среды исполнения обычно размещаются на устройствах [15]. На рис. 5.18 показаны пиктограммы в виде трехмерных кубов, представляющих узлы, в данном случае узлы PC и ApplicationServer. Для уточнения спецификации узла эта пиктограмма может сопровождаться дополнительными символами. Выбор имен узлов ничем не ограничен, поскольку он относится к аппаратному, а не программному обеспечению. рс л Ц «ТСРЛР» I Ι τ / : I AppRcatfoftSenrar 3 Рис. 5.18. Обозначения двух узлов Связь между узлами осуществляется посредством передачи сообщений и сигналов по каналам, изображаемым в виде сплошных линий. Каналы связи обычно считаются двунаправленными. Если же канал является однонаправленным, то его направление можно показать с помощью стрелки. Каждый канал связи может иметь метку в виде ключевого слова, например, «http» или «TCP/IP», несущего информацию о соединении. Кроме того, каналы связи позволяют отразить множественность узла. На рис. 5Л8 связь между узлами PC (Персональный компьютер) и ApplicationServer (Сервер приложения) носит двусторонний характер. Каналы связи
206 Часть П. Метод обычно представляют определенное прямое соединение между частями аппаратного обеспечения, например, USB-кабель, соединение Ethernet и даже путь к совместно используемой памяти. Однако канал связи может изображать и косвенное соединение, например, спутник-земля или сотовую связь. В данном случае диаграмма изображает двустороннюю связь с помощью протокола TCP/IP. Как указано на рис. 5.18, с одним узлом ApplicationServer могут быть связаны один или несколько узлов PC. Основы: диаграмма развертывания На рис. 5.19 продемонстрирован пример диаграммы развертывания, отражающей физическую архитектуру подсистемы EnvironmentalControlSystem гидропонной теплицы. Как видим, архитекторы этой системы решили разделить часть ее функций между двумя узлами (PC и ApplicationServer) и двумя устройствами (LightMeter (Измеритель освещенности) и Thermometer (Измеритель температуры)). Если сравнить эту диаграмму развертывания с диаграммой компонентов подсистемы EnvironmentalControlSystem (см. рис. 5.11), то легко убедиться, что диаграмма развертывания учитывает не все ее интерфейсы. Некоторые из них для простоты пропущены. Кроме того, каждый артефакт, показанный на диаграмме, выполняет функции только одного компонента. Размещение артефактов EnvironmentalController.exe, Lighting- Controller . exe, HeatingController. ехе и CoolingController. ехе в узле ApplicationServer изображено с помощью включения. Другой способ представления развертывания основан на использовании зависимости артефакта GardeningPlanDeveloper. ехе (Разработчик плана выращивания) от узла PC, изображенной с помощью линии, которая помечена ключевым словом «deploy». Третий способ обозначения развертывания использует текстуальное перечисление артефактов внутри пиктограммы узла. Этот способ особенно полезен для изображения более сложных или крупных диаграмм развертывания [16, 17]. На рис. 5.19 между артефактами существуют три безымянные зависимости: от артефактов LightingController. ехе, HeatingController. ехе и CoolingController .ехе к артефакту EnvironmentalController.exe. Эти зависимости связывают друг с другом компоненты, которые реализуют данные артефакты, а не компоненты, которые размещены в узле. Кроме того, на рис. 5.19 показана еще одна зависимость — от артефакта Envi - ronmentalController.ехе к артефакту GardeningPlanDeveloper.ехе. Это связано с интерфейсом компонента EnvironmentalController, для работы которого необходим план выращивания. Здесь изображен план выращивания, разработанный элементом PlanAnalyst с помощью артефакта GardeningPlanDeveloper .ехе, реализующего функции компонента GardeningPlan-
Глава 5. Обозначения 207 «device» LightMeter «serial» 71 ψ «device» Thermometer «serial» ApplicatfonServer HeatingControllerexe W\ LightingController.exe Щ CoolingController.exe Щ 4 V & EnvironmentalController.exe W\ «TCP/IP» PC pi «deploy» A. GardeningPianDeveloper.exe Щ WW «manifest»* Τ ^L a «component» GardeningPlanDeveloper «deployment spec» GardeningPlanDeveloper.xml Рис. 5.19. Диаграмма развертывания подсистемы EnvironmentalControlSystem
208 Часть П. Метод Developer. Следует подчеркнуть, что элемент PlanAnalyst может выполнить свою задачу с помощью одного из двух узлов PC. Два устройства, Lightmeter и Thermometer, считывают показания датчиков освещенности и температуры внешней среды, запрашиваемые артефактом EnvironmentalController.exe. Последним элементом является спецификация развертывания GardeningPlanDeveloper. xml, зависящая от артефакта GardeningPlanDeveloper. exe. Эта спецификация описывает размещение артефакта в системе, например, особенности его выполнения и транзакций [18]. 5.5 Диаграммы прецедентов использования Многолетний опыт показывает, что одной из основных причин краха программных проектов является недостаточное взаимопонимание между его основными участниками или полное отсутствие контактов между ними. Это особенно важно в ситуациях, когда проектировщики и заказчики работают в разных областях знаний. Бизнесмены могут хорошо знать определенную задачу, которую необходимо решить, но, тем не менее, дать организаторам проекта лишь самое общее описание своих пожеланий, уточнив некоторые детали. Можно ли создать успешный проект в таких условиях? В одном из наиболее патологических случаев сотрудники одной коммерческой фирмы считали контакты с разработчиками ниже своего достоинства и потенциально опасными для карьеры. Иногда проектировщики получают подробное задание, но не имеют ни малейшего представления о целях бизнеса, т.е. для чего они разрабатывают новую систему. Желает ли компания, стремящаяся стать недорогим поставщиком, чтобы система позволяла экономить затраты? Или же ее цель — предоставлять высококачественные специализированные услуги? Какова цель компании — быстрое развитие или внедрение инноваций? Не понимая целей компании, разработчики могут принять проектное решение, которое будет им противоречить. Таким образом, крайне необходим подход к разработке систем, который позволял бы понять цели бизнеса, не отвлекая штатных сотрудников компании от их основной работы (в конце концов, у них есть свои повседневные обязанности). Инструменте»! решения такой задачи являются диаграммы прецедентов использования (use case diagrams). Они изображают элементы системы, взаимодействующие друг с другом. Основы: действующие лица Действующие лица (actors) — это сущности, контактирующие с системой. Действующими лицами могут быть как люди, так и другие системы. Они являются внешними сущностями по отношению к системе и изображаются в виде стили-
Глава 5. Обозначения 209 зеванных фигурок. На рис. 5.20 показаны два действующих лица, работающих с системой управления гидропонной теплицы. Садовник Аналитик Рис. 5.20. Действующие лица Действующие лица можно описать с помощью их ролей. В реальном мире люди (и системы) могут исполнять несколько ролей. Например, один и тот же человек может быть продавцом, менеджером, отцом, художником и хд. Основы: прецеденты использования Прецеденты использования демонстрируют, что именно действующие лица хотят от системы. Некоторые прецеденты использования, связанные с системой управления гидропонной теплицей, изображены на рис. 5.21. Прецеденты использования — это не просто возможности, предоставляемые системой. Прецедент использования должен быть полным потокам целесообразных поступков действующего лица. Джейкобсон (Jacobson) дал следующее определение [6]. Прецедент использования — это конкретный способ использования системы с помощью определенной части ее функциональных свойств... Следовательно, прецедент использования — это особая последовательность связанных между собой операций, выполняемых действующим лицом и системой в диалоге... Каждый прецедент использования представляет собой полный перечень событий, происходящих в системе, с точки зрения пользователя. f Управление \ I садом J Рис 5.21. Прецеденты использования Основы: диаграмма прецедентов использования Для того чтобы описать действие системы, можно создать диаграмму прецедентов использования, соединив действующих лиц и соответствующие прецеден-
210 Часть И. Метод Садовник Специалист по удобрениям f Просмотр γ \ отчетов / Аналитик Рис. 5.22. Диаграмма прецедентов использования ты с помощью основных ассоциаций, изображаемых линиями, как показано на рис. 5.22. Ассоциации в диаграмме прецедентов использования показывают, какие действующие лица инициируют выполнение того или иного прецедента. Например, управлять резервуарами для полива может только действующее лицо Садовник, а просматривать отчеты могут все действующие лица. Спецификация деталей прецедентов использования Как описать детали прецедентов использования? Как задать полный поток событий? Оптимальным способом является использование дополнительных UML-
Глава 5. Обозначения 211 моделей (таких как диаграммы деятельности, которые будут рассмотрены далее) и текстуальных спецификаций. В литературе по языку UML описано много способов спецификации прецедентов использования. Большинство из них содержат следующий минимум информации: название прецедентов использования, его цель (в виде короткого описания), оптимистический вариант (т.е. поток событий, при котором система функционирует нормально) и один или несколько прагматичных вариантов (т.е. потоки событий, когда события протекают не так, как предусмотрено проектом). Пример спецификации прецедента использования Рассмотрим прецедента использования Обслуживание резервуаров. Спецификация прецедента использования Название прецедента использования. Обслуживание резервуаров Цель прецедента использования. Прецедент использования позволяет поддерживать требуемый уровень заполнения резервуаров. Он позволяет действующему лицу обеспечивать необходимый объем воды и питательных веществ в соответствующих емкостях. Оптимистический сценарий: A. Действующее лицо проверяет уровни заполнения в резервуарах воды и питательных веществ. Б. Действующее лицо определяет, какой резервуар необходимо пополнить. B. Действующее лицо приостанавливает все текущие операции, выполняемые системой с резервуарами. Г. Действующее лицо выбирает резервуары и задает уровень их заполнения. Для каждого выбранного резервуара выполняются операции Д-Ж. Д. Если резервуар нагрет, то система отключает нагреватели. 1. Нагреватели устанавливают безопасную температуру. Е. Система заполняет резервуары. Ж. Если резервуар заполнен и должен быть нагрет, система включает нагреватели. 1. Температура содержимого резервуаров достигает оптимальной температуры. 3. Действующее лицо возобновляет текущее функционирование гидропонной системы. Прагматичный сценарий:
212 Часть П. Метод Условия вынуждают изменить поток операций: Условие 1: воды и питательных веществ недостаточно для заполнения резервуаров до уровня, указанного действующим лицом. П. Предупредить действующее лицо о недостатке воды и питательных веществ. Показать объем имеющихся запасов воды и питательных веществ. Г2. Предложить действующему лицу отказаться от наполнения или пересмотреть уровни заполнения резервуаров. ГЗ. Если действующее лицо пересматривает уровни заполнения, то выполнить этап Г. Г4. Если действующее лицо отказывается от наполнения резервуаров, то выполнить этап 3. Г5. В противном случае выполнить этап Г2. условие Mmi · · · В спецификацию прецедента использования можно включить и другую полезную информацию, например, предусловия (которые должны удовлетворяться до начала выполнения прецедента), постусловия (которые должны удовлетворяться после начала выполнения прецедента), ограничения, предположения н т.д. Например, в гидропонной системе существует ограничение, регламентирующее, что резервуары воды и питательных веществ для одного и того же растения должны наполняться синхронно. Это решение диктуется желанием сохранить баланс между колнчествсш воды и питательных веществ, предназначенных для этого растения. Спецификация прецедента использования не должна быть слишком длинной — несколько страниц, не больше. Если спецификация оказалась слишком длинной, прецедент следует пересмотреть и удалить из него излишние операции. В таких случаях целесообразно разделить большой прецедент использования на несколько маленьких. Кроме того, на практике часто невозможно заранее предусмотреть все условия, когорте могут изменить поток событий. В прецедент использования следует включить лишь самые важные из них. Не следует перечислять все возможные ошибки, которые могут произойти, например, если оператор введет данные в неверном формате (предоставьте пользовательскому интерфейсу самостоятельно обработать такие исключительные ситуации). Уточненная концепция: отношения «include» и «extend» , Для описания моделей прецедентов использования в основном используются (обычно неправильно) два отношения: «±nclude> и «extend».
Глава 5. Обозначения 213 Отношение «include» В рассмотренном примере использовался прецедент использования Обновление справочника по растениями Предположим, что в ходе проектирования разработчик выясняет; что действующее лицо Специалист по удобрениям с помощью данного прецедента использования должен иметь возможность просмотреть содержание справочника до его обновления. Для этого действующее лицо Специалист по удобрениям должен инициировать прецедент использования Просмотр отчетов. По тем же причинам действующее лицо Садовник обязан активизировать прецедент использования Обслуживание резервуаров. Ни одно действующее лицо не должно выполнять прецедент использования вслепую. Следовательно, прецедент использования Просмотр отчетов является общим для обоих Обновить справочник по растениям и Обслуживание резервуаров. Этот факт можно отразить с помощью отношения «include», как показано на рис. 5.23. Например, из этой диаграммы следует; что прецедент использования Обновить справочник по растениям включает в себя прецедент использования Просмотр отчетов. Иначе говоря, при выполнении прецедент использования Обновить справочник по растениям обязательно должен выполняться прецедент использования Просмотр отчетов. Без прецедента использования Просмотр отчетов прецедент использования Обслуживание резервуаров считается неполным. Место, в котором выполняется включенный прецедент использования, указывается в спецификации прецедента точкой включенш1 (и&ктопроШ). Кроме того, точки включения могут быть показаны на диаграмме прецедент использования. Отношение «extend» В ходе разработки прецедентов использования может оказаться, что некоторые операции хотя и составляют часть прецедента, но не являются обязательными. В рассмотренном примере действующее лицо Садовник, выполняя прецедент использования Управление садом, имеет возможность просмотреть некоторые отчеты. Это можно сделать, выполнив прецедент использования Просмотр отчетов. Однако прецедент использования Просмотр отчетов не является неотъемлемой частью прецедент использования Управление садом. Прецедент использования Управление садом является полным и без него. Таким образом, диаграмму прецедентов использования необходимо модифицировать, чтобы показать, что прецедент использования Просмотр отчетов расширяет прецедент использования Управление садом, как показано на рис. 5.24. Место, в котором выполняется расширенный прецедент использования, изображается в спецификации точкой расширения (extension point). Кроме того, точки
214 Часть II. Метод Садовник Специалист по удобрениям Аналитик Рис. 5.23. Диаграмма прецедентов использования, демонстрирующая отношение «include» расширения могут быть показаны на диаграмме прецедентов использования так, как продемонстрировано на рис. 5.25. Опасности, связанные с отношениями «include» и «extend» Несмотря на то что эти два отношения весьма удобны для выражения общих функциональных свойств («include») и упрощения потока сложных прецедентов использования («extend»), в ходе моделирования прецедентов их часто используют неправильно. Основная причина этих ошибок заключается в том, что некоторые люди плохо понимают разницу между отношениями
Глава 5. Обозначения 215 Садовник Специалист по удобрениям Аналитик Рис. 5.24. Диаграмма прецедентов использования, демонстрирующая отношение «extend» «include» и «extend». В работе [7] Максимчук (Maksimchuk) и Най- бург (Neiburg) привели краткий перечень этих различий (табл. 5.1). Другая распространенная ошибка заключается в том, что эти отношения нарушают основные принципы использования прецедент использования. Включаемый и расширяющий прецеденты использования остаются прецедентами и должны подчиняться общим правилам. Прецедент использования должен быть полным потоком целесообразных операций, которые система должна выполнить по желанию действующего лица. Если строго следовать этому принципу, то можно избежать ошибки, связанной с использованием этих отношений для "функциональной декомпозиции" преце-
216 Часть П. Метод РЖ. 5.25. Диаграмма прецедентов использования, демонстрирующая точку рашшрсшш дентов использования. Эта ошибка является основной проблемой моделирования прецедентов использования, поскольку многие проектировщики, используя отношения «include» и «extend», разбивают прецедент использования на мелкие части, а затем связывают их между собой. Причина этой ошибки коренится в остатках структурного анализа и проектирования (Structured Analysis/ Stracmied Design - SA/SDX пр^ го подхода можно разложить крупные задачи на более мелкие части. Это сразу нарушает принципы анализа прецедентов использования, излаженные в шпале раздела, и приводит к утере преимуществ, предоставляемых объектной моделью проектирования (перечислены в первых четырех главах).
217 Таблица 5.1. Основные между* «include» и «extend»* Является ли АфСИДДеШ ИСПОЯ&ЭОВанНЯ НСООЯЗЯ— тельным? Является лн основной прецедент использования полным без данного прецедента? Является ли расширение условным? Изменяет ли данный прецедент использования Her Нет Нет Нет Да Да Да Да * Воспроизводится по работе Максимчук (Makiamrhttk) и Найбург (Naiburg) [7]. Уточненная концепция: обобщение Как показано в главе 3, можно связать прецеденты использования между собой с помощью отношения обобщения (generalization relatkniships). Как и классы, прецеденты могут иметь общие функциональные свойства, которые другие прецеденты (дочерние) могут модифшдорояат Пример такой модификации прецедента, описывающего покупку билетов, приведен на рис.5.26. 5JUL Обобщение прецедента использования Прецедент использования Покупка билетов содержит основные шаги, которые необходимо выполнить, покупая любой билет. В то же время дочерние прецеденты — Купить билеты на концерт, Купить билеты в театр и Купить билеты на бейсбол—«ннфешзируют прецедент Покупка билетов для определенных видов билетов.
218 Часть П. Метод 5.6 Диаграммы деятельности В предыдущем разделе описана спецификация прецедента использования в виде текста. Текстовое описание прецедента имеет ряд преимуществ: их легко создавать и изменять (для этого не требуются сложные инструменты), их можно создавать везде (для этого достаточно иметь бумагу и карандаш), их легко использовать и распределять между сотрудниками компании и разработчиками проекта и т.д. Однако сложные прецеденты использования, деловые операции и алгоритмы иногда трудно описать в виде текста. Сложные потоки информации намного удобнее представлять с помощью визуальных средств. Визуальное представление процессов иногда позволяет выявить потенциальные проблемы, которые невозможно обнаружить в текстуальном описании прецедента использования. В одном из проектов сложный производственный процесс был документирован с помощью формальных спецификаций, изобретенных компанией, поставляющей программное обеспечение для этого проекта. Эти спецификации были согласованы с обеими компаниями, занимавшимися реализацией производственного процесса. Несмотря на строгость и формальный характер спецификаций, как только была создана основная визуальная диаграмма производственного процесса, сразу обнаружились его узкие места. Диаграммы деятельности позволяют визуально изобразить поток операций в системном, производственном или технологическом процессе. Эти диаграммы концентрируют внимание на том, какие действия выполняются и кто (или что) несет ответственность за их выполнение. Элементами диаграмм деятельности являются узлы действий (action node), узлы управления (control nodes) и узлы объектов (object nodes). Узлы управления разделяются на три категории: начальные и конечные (причем существует два варианта конечных узлов: конец действия или конец потока), принятия решений и слияния (decision and merge), а также ветвления и объединения (fork and join)2. Основы: действия Действие (action) — это элементарный компонент поведения, представленный в диаграмме деятельности. Деятельность может состоять из многих действий, которые изображаются на соответствующих диаграммах. На рис. 5.27 показано действие Проверить уровни резервуаров, которое может быть выполнено в гидропонной теплице. Обратите внимание на символ в правом нижнем углу пиктограммы. Он означает, что данная операция относится к типу callBehavior, который является одним из предопределенных типов операций в языке UML 2 и представляет со- 2Более подробно этот вопрос рассмотрен в серии из пяти статей Конрада Бока (Conrad Bock) под названием "UML 2 Activity and Action Models", приведенной в разделе Μ.
Глава 5. Обозначения 219 Проверить уровни резервуаров I+I Рис. 5.27. Обозначение действия бой "элементарные действия, моделирующие манипуляции с объектами и связи между ними, а также вычисления и обмены сообщениями между объектами" [91]. Тип callBehavior относится к действиям, в определения которых входят узлы действий, узлы контроля и узлы объектов. Следовательно, этот тип охватывает большинство действий, используемых в диаграммах деятельности. С практической точки зрения, символ в виде трезубца следует использовать для обозначения только тех операций, которые должны вызываться. Основы: начало и остановка Поскольку диаграмма деятельности демонстрирует последовательность технологических операций, она должна иметь начало и конец. Стартовая точка (начальный узел) диаграммы деятельности изображается в виде черного кружочка, а точка остановки (конечный узел процесса) — в виде зрачка. На рис. 5.28 показана простая диаграмма деятельности, состоящей из одного действия: Проверить уровни резервуаров. о Начало Проверить уровни резервуаров Конец Рис. 5.28. Начальный и конечный узлы простой диаграммы деятельности Кроме конечного узла действий, в диаграммах существует конечный узел потока (flow final node), обозначаемый вложенным символом "X". Конечный узел потока используется для остановки отдельного потока без остановки всего процесса. Он будет описан в ходе обсуждения узла слияния (merge node). Основы: узлы принятия решений и слияний Узлы принятия решений и слияний управляют потоком в диаграмме деятельности. Каждый такой узел изображается в виде ромба с входящими и исходящими стрелками. Узел принятия решений имеет один входящий поток и несколько исходящих. Он используется для направления входящего потока по одному (и только
22· Часть П. Метод одному) каналу, исходящему их этого узла. Входящие потоки обычно сопровождаются предохранительными условиями, определяющими выбор их дальнейшего направления. На рис. 5.29 показано предохранительное условие [все уровни в норме] и альтернатива [иначе]. В узле принятия решений не предусмотрены ни задержки, ни синхронизация потоков. Q Проверить уровни > J [иначе] [все уровни в пределах нормы] Рис 5.29. Узел принятия решений В узел слияния входят несколько потопов, которые на выходе из узла полностью или частично сливаются в один. На рис. 5.30 три потока достигают точки слияния (изображенного в виде ромба), проходят через узел и направляются на узел действия Зарегистрировать системное событие. Таким образом, происходит регистрация нескольких событии. На рис. 5.30 показан также конечный узел потока, рассмотренный ранее. Основы: разделы Элементы диаграммы деятельности можно сгруппировать в разделы (partitions). Цель раздела — указать границы ответственности за выполнение конкретных действий. В моделях предприятий разделами могут быть филиалы, отделы или организации. В системах разделами могут быть системы и подежстемьь В щш- кладном моделировании разделы объединяют объекты, входящие в приложения. (Однако эта разновидность взаимодействий между мелкими модулями чаще описывается с помощью диаграмм последовательностей, которые будут рассмотрены
Глава 5. Обозначения 221 Зарегистрировать системное событие ® FlowFinal Рис 5Лв. Узел слияния и конечный узел потока далее.) Каждый раздел может иметь название, отражающее границы его ответственности. На рис. 531 показано, как разные процессы, из которых состоит прецедент использования Обслуживание резервуаров, описывающий работу гидропонной теплицы, распределены между элементами Gardener, Water- Tank и NutrientTank. Уточненные концепции: разветвления, объединения и параллельность Узлы разветвления (fork node) и объединения (join node) аналогичны узлам принятия решения (decision node) и слияния (merge node) соответственно. Основным отличием между ними является параллельность. Как и узел принятия решений, узел разветвления имеет один входящий поток и несколько исходящие Разница заключается в том, что в узле принятия решений происходит выбор только одного исходящего потока, а в узле разветвления один поток расщепляется на несколько. Все исходящие потоки являются параллельными. На рис. 5.31 из узла Установить уровни резервуаров выходит один поток, поступающий на узел разветвления, изображенный толстой горизонтальной линией. Далее поток NutrientTank (Резервуар удобрений), соответствующий действию На-
222 Часть П. Метод Рис. 5.31. Диаграмма деятельности с разделами
Глава 5. Обозначения 223 полнить, и WaterTank (Поток воды), связанный с действиями Отключить обогрев, Наполнить и Включить обогрев, идут параллельно. Как и узел слияния, узел объединения имеет несколько входящих потоков и один исходящий. Однако все потоки, входящие в узел объединения, должны быть завершены до того, как будет инициирован исходящий поток. На рис. 5.31 вторая толстая линия представляет собой узел объединения. В него входят потоки NutrientTank и WaterTank, которые должны быть завершены до того, как выходной поток последует на узел действия Возобновить операции. (Аналогично концепции объединения, в которой в одном действии участвуют несколько потоков управления или объектов, все потоки должны поступать на узел действия до того, как оно начнется. После завершения действия начинаются все потоки (управления и объектов), исходящие из соответствующего узла.) Уточненные концепции: потоки объектов В некоторых ситуациях полезно рассматривать объекты, подвергающиеся манипуляциям в ходе выполнения действия. Для этого на диаграмме деятельности следует изобразить поток объектов. (Однако это нельзя рекомендовать для всех диаграмм деятельности, поскольку изображение всех объектов делает диаграмму слишком сложной и громоздкой.) На рис. 5.32 показана предыдущая диаграмма, к которой добавлен поток объектов. В раздел WaterTank добавлены два узла объектов (прямоугольники с меткой : WaterTank). Это означает, что после отключения нагрева уровень в резервуаре воды будет ниже предельного, а после действия Наполнить резервуар будет полным. Состояния объекта : WaterTank — [ниже предельного уровня] и [полный] — указываются под именем объекта. Уточненные концепции: дополнительные элементы Диаграммы деятельности, как и все диаграммы UML, имеют богатую семантику. На них иногда могут изображаться и другие элементы — например, дополнительные типы объектов, области прерывания, разъемы и т.д. Дополнительные сведения о диаграммах деятельности приведены в приложении Б. 5.7 Диаграммы классов Диаграмма классов показывает классы и их отношения в логической схеме проекта. Отдельная диаграмма классов представляет определенный аспект структуры системы. На стадии анализа диаграммы классов используются для того, чтобы указать общие роли и обязанности сущностей, обеспечивающих функционирование системы. На стадии проектирования диаграммы классов позволяют представить архитектуру системы.
224 Часть flL Метод Отложить операции {вое уровни в пределах допустимого] К Отключить |{темпервту| обогРев i^ г с [{темперетурв ниже безопасной] .-WaterTank допустимого уровнящ обогрев г* ( \ Ι Наполнить ж {полный] Рис 5.32. Диаграмма деятельности с узлами объектов Двумя главными элементами диаграмм классов являются классы и основные отношения между ними.
Глава 5. Обозначения 225 Основы: классы На рис. 5.33 показана пиктограмма, представляющая один из классов в диаграмме классов и пример класса в системе управления гидропонной теплицей. Пиктограмма класса состоит из трех компонентов: имени, атрибутов и операций. ClassName + attributes type + operationsQ : return type TemperatureSensor calibrationTemperature string measuredTemperature· string = [0 .60] {list} currentTemperatureO: string calibrate(actualTemperature. string). void Рис. 5.33. Пиктограмма класса и пример класса в системе управления теплицей Каждый класс должен иметь уникальное имя в соответствующем пространстве имен. По общепринятому соглашению имя начинается с прописной буквы, а пробелы между именами пропускаются. Кроме того, первая буква атрибута и операции является строчной, а последующие слова начинаются с прописных букв. Пробелы при этом также игнорируются. Поскольку класс является пространством имен для своих атрибутов и операций, имя атрибута должно быть однозначным в контексте класса. Выбор имен операций зависит от правил, принятых в конкретном языке программирования. Формат спецификаций атрибутов и операций показан ниже [19]. • Формат спецификации атрибута: • видимость имяАтрибута : Тип [кратность] = ЗначениеПоУмолчанию {строка свойств} • Формат спецификации операции: • видимость имяОперации (имяПараметра : Тип) = ТипВозвращаемогоЗначения{строка свойств} Концепция видимости (visibility) — открытой, закрытой, защищенной или пакетной — обсуждается в следующем подразделе. Как для атрибута, так и для операций, тип — это имя класса или тип данных. Кратность атрибута также будет рассмотрена немного позже. Пока лишь подчеркнем, что на рис. 5.33 в классе TemperatureSensor (Датчик температуры) кратность [ 0 ... 60 ] атрибута measuredTemperature (Измеренная температура) означает, что он представляет собой массив, состоящий из 60 измерений температуры. Значение атрибута, заданное по умолчанию, указывается в момент его создания, разумеется, если это значение вообще предусмотрено. Строка свойств, указанная в фигурных скобках, описывает дополнительные свойства атрибута, как, например, строка {list},
226 Часть П. Метод указанная после атрибута measuredTemperature в классе Temperature- Sensor. В данном случае ключевое слово list (список) означает, что измерения температуры упорядочены и могут повторяться. Это позволяет определить порядок измерений температуры во времени и допускает повторяющиеся значения. Комбинация имяПараметра : Тип повторяется столько раз, сколько аргументов имеет операция. В некоторых диаграммах классов полезно указывать лишь некоторые атрибуты и операции. Это объясняется тем, что, за исключением простейших случаев, перечислять все члены класса в диаграмме нецелесообразно. Таким образом, представленные атрибуты и операции лишь конспективно представляют спецификацию класса, который является единственным местом объявления всех своих членов. Если необходимо показать больше членов класса, следует увеличить размер его пиктограммы. Если проектировщик решил не показывать ни один член класса, можно указать лишь имя класса. При желании синтаксис атрибутов и операций можно привести в соответствие с правилами выбранного языка программирования. Как указано в главе 3, экземпляры абстрактного класса создать невозможно. Поскольку абстрактные классы имеют исключительное значение для проектирования качественных иерархий классов, для них используются особые обозначения (см. рис. 5.34). В частности, имя абстрактного класса изображается курсивом. Это позволяет подчеркнуть, что существовать могут лишь экземпляры его подклассов. Операция абстрактного класса также изображается курсивом, чтобы показать, что она может по-разному реализоваться во всех экземплярах его подклассов. В системе управления гидропонной теплицы существуют удобрения, содержащие витаминные добавки, но не имеющие тип "элемент питания". Следовательно, класс Foodltem (Элемент питания) является абстрактным. На рис. 5.34 показан также класс Tomato (Помидор), описывающий конкретный вид растения [20]. Смысл отношений между классами будет разъяснен далее. Основы: отношения между классами Классы редко бывают изолированными. Наоборот, как указывалось в главе 3, они взаимодействуют друг с другом, используя разные методы. К основным отношениям между классами относятся ассоциация (association), обобщение (generalization), агрегация (aggregation) и объединение (composition). Их пиктограммы представлены на рис. 5.35. Каждое отношение сопровождается текстуальной меткой, в которой указывается имя отношения или его предназначение. Кроме того, участники ассоциации также могут иметь метки. Правда, обе метки, как правило, не используются одновременно. Пиктограмма ассоциации соединяет два класса и означает семантическую связь между ними. Ассоциации часто обозначаются именными группами, напри-
Глава 5. Обозначения 227 Рис. 5.34. Представление абстрактного класса мер Анализирует, описывающими природу связи (см. рис. 5.35). Класс может иметь ассоциацию с самим собой (так называемая рефлексивная ассоциация (reflexive association)), например, для отражения взаимодействия между экземплярами класса PlanAnalyst. В этом случае обозначение участников ассоциации и самой ассоциации позволяет внести ясность в диаграмму. Одна пара классов может иметь несколько ассоциативных связей. Возле пиктограммы ассоциации можно указать ее кратность (см. главу 3), используя синтаксис следующих примеров: • 1 Одна связь • * Неограниченное количество (от нуля и больше) • 0 . . * Нуль или больше • 1. . * Один или больше • 0 . . 1 Нуль или один • 3 . . 7 Конкретный диапазон (от трех до семи включительно) Обозначение кратности пишется возле целевого полюса ассоциации (target end). Оно указывает количество связей между каждым экземпляром класса с экземплярами целевого класса. Если кратность отношения явно не указана, то следует считать, что она не определена. Лучше всегда указывать кратность отношения, чтобы не возникало недоразумений. Обозначения оставшихся трех типов связи уточняют пиктограмму ассоциации. Это позволяет уточнять отношения на этапе разработки проекта. Сначала констатируется существование семантической связи между двумя классами, а затем, после принятия тактических решений об истинной природе этих отношений, эта связь уточняется как обобщение, агрегация или объединение. Пиктограмма обобщения означает отношение обобщения/специализации (отношение "является", описанное в главе 3) и изображается в виде закрытой стрел-
228 Часть П. Метод АССОЦИАЦИЯ staff* 1 PlanAnalyst I +Iead0.1 J 12 Analyzes 1..* PlanMetrics ОБОБЩЕНИЕ Plan {incomplete, disjoint} GrowlngPlan 7Г GardeningPlan {incomplete} FrultGrowingPlan АГРЕГАЦИЯ ОБЪЕДИНЕНИЕ Foodltwn 123 Л Л: VttamlnContent CalorfcEqulvalent Рис. 5.35. Отношения между классами ки. Конец стрел1си указывает на суперкласс, а ее противоположный конец обозначает подкласс. Класс GrowingPlan (План выращивания) на рис. 5.35 является суперклассом, а класс FruitGrowingPlan (План выращивания фруктов) — его подклассом. В соответствии с правилами выбранного языка реализации, подкласс наследует структуру и функциональные свойства своего суперкласса. Класс может иметь один (одиночное наследование) или несколько (множественное наследование) суперклассов. Конфликты имен между суперклассами разрешаются в соответствии с правилами выбранного языка программирования. Кроме того, отношения обобщения не должны быть кратными. Как указывалось в главе 3, агрегация, будучи отношением "является частью", является частным вариантом отношения ассоциации. Пиктограмма агрегации обо-
Глава 5. Обозначения 229 значает иерархию "целое/часть" и подразумевает возможность перемещаться от объединения к его частям. Агрегация изображается в виде линии с незакрашенным ромбом на конце, указывающим на агрегат (целое). Класс на другом конце стрелки — это класс, экземпляры которого являются частями объекта агрегата. Допускаются рефлексивная и циклическая агрегации. Иерархия "целое/часть" не всегда означает физическое включение. Например, профессиональное сообщество имеет множество членов, но это не значит, что оно ими владеет. На рис. 5.35 показано, что класс EnvironmentalController содержит классы Light, Heater и Cooler. Кратность * (т.е. нуль или больше), указанная возле линии, изображающей отношение агрегации, подчеркивает отсутствие физического включения. Выбор отношения агрегации обычно осуществляется на этапе анализа или архитектурного проектирования. Выбор отношения объединения (физического включения) представляет собой пример тактического решения. Отношение включения имеет большое значение, поскольку оно играет важную роль в процессе конструирования и уничтожения частей агрегата. Пиктограмма объединения изображается в виде линии с закрашенным ромбом на конце, соединенном с агрегатом. Кратность этой линии равна 1, поскольку часть агрегата не имеет смысла за его пределами. Таким образом, продолжительность существования части совпадает с продолжительностью существования целого. Класс Foodltem на рис. 5.35 физически содержит классы VitaminContent и CaloricEquivalent. Рассмотрим следующий пример. На рис. 5.36 показан класс CropHystory, экземпляры которого физически содержат неограниченное количество экземпляров классов NutirentSchedule и ClimateEvent. Объединение означает, что создание и уничтожение этих частей происходит вследствие создания или уничтожения агрегата. В противоположность этому, каждый экземпляр класса CropHystory не содержит ни одного экземпляра класса Crop. Это значит, что продолжительности существования этих двух объектов не зависят друг от друга, хотя один из них можно считать частью другого. Описанные выше пиктограммы являются основными элементами диаграмм классов. В совокупности они позволяют разработчику достаточно полно описать структуру классов системы. Уточненные концепции: шаблонные (параметризованные) классы Элементы, рассмотренные выше, представляют собой существенную часть диаграмм классов. Однако многие стратегические и тактические решения требуют расширения системы обозначений. Как правило, разработчики стараются придерживаться основных обозначений и применять лишь те дополнительные понятия, без которых нельзя обойтись при анализе и проектировании деталей, играющих важную роль в визуализации или анализе системы.
230 Часть П. Метод CropHistory Crop ClimateEvent NutrientSchedule Рис. 5.36. Физическое включение Некоторые языки программирования, например, C++, предусматривают шаблонные (параметризованные) классы. Шаблонный класс (template class) — это семейство классов, структура и функциональные свойства которых определяются формальными параметрами независимо друг от друга. Для того чтобы создать конкретный класс из этого семейства, формальные параметры должны быть заменены фактическими (процесс связывания). Конкретные классы могут иметь экземпляры. Шаблонные классы сильно отличаются от обычных классов. Это является основанием для того, чтобы использовать особые обозначения. Шаблонный класс изображается как обычный класс (см. рис. 5.37), но в правом верхнем углу пиктограммы находится пунктирный прямоугольник. Связанный класс (bound class) также изображается как обычный класс. Отношение связывания между шаблонным и связанным классами представляется в виде пунктирной стрелки, указывающей на шаблонный класс. Стрелка имеет метку «bind». Фактические параметры, соответствующие формальным параметрам шаблона, указываются в виде «Формальный параметр —> Фактический параметра Как показано на рис. 5.37, класс PlanSet (Множество планов) связан с классом Set (Множество), причем класс GardeningPlan (План выращивания) является фактическим параметром, заменяющим формальный параметр Item (Элемент). Шаблонный класс не может иметь ни одного экземпляра и сам не может быть шаблонным параметром. Связанный класс представляет собой новый класс, отличающийся от всех конкретных классов семейства с другими фактическими параметрами.
Глава 5. Обозначения 231 Item I I «bind» <ltem -> GardeningPlan> Рис. 5.37. Шаблонный класс и связанные с ним классы Уточненные концепции: видимость В разделе 5.2, который посвящен диаграммам пакетов, рассмотрена концепция видимости элементов, определяющая, существует ли доступ к элементу пакета извне. Кроме того, класс является объемлющим пространством имен для соответствующих элементов. В данном разделе рассматривается видимость ассоциаций, атрибутов и операций. Все интересные объектно-ориентированные языки программирования проводят четкое разграничение между интерфейсом и реализацией классов. Как показано в главе 3, большинство языков предусматривают разные уровни доступа к интерфейсу. Например, в языке C++ члены класса могут быть открытыми (доступными для всех клиентов), защищенными (доступными только для подклассов или членов самого класса) или закрытыми (доступными только для членов класса и его друзей). Кроме того, в языке C++ определенные элементы могут быть частью реализации класса и, как следствие, быть недоступными даже для друзей класса. Такой уровень доступа называется видимостью реализации (implementation visibility). Видимость можно задать, указав на диаграмме один из следующих символов [33].
232 Часть П. Метод Открытая (+) Доступен для всех элементов в области видимости класса Защищенная (#) Доступен только для членов класса и подклассов Закрытая (-) Доступен только для членов класса Пакетная (~) Доступен только для элементов пакета Для того чтобы продемонстрировать уровень доступа источника (source end) к цели (target end), возле имен, приписанных к полюсам ассоциации, указываются специальные символы. Например, на рис. 5.38 имена источника и цели (database (база данных) и crop (растение)) ассоциации между классами CropDatabase (База данных по растениям) и GrainCrop (Зерновая культура) являются открытыми. Это значит, что каждый из этих классов имеет доступ к другому. В противоположность этому, имена источника и конца ассоциации между классами GrainCrop и GrainYieldPredictor (Прогноз урожая зерновых) свидетельствуют о том, что класс GrainCrop недоступен для класса GrainYieldPredictor. Crop scientificName1 yield nutrientValue: CropDatabase ♦crop GrainCrop -crop +yield ψ 1 1..23 VitaminContent CalorfcEqulvalent 1..* GrainYieldPredictor Рис. 5.38. Уровни доступа Другая концепция, заслуживающая внимания, заключается в том, что ассоциация имеет направление. На этапе анализа все ассоциации считаются двусторонними логическими связями между классами. Однако на этапе проектирования в центре внимания оказывается направление ассоциации. Ненаправленные ассо-
Глава 5. Обозначения 233 циации между классами GrainCrop и GrainYieldPredictor означают, что некоторый метод класса GrainCrop в своей реализации использует члены класса GrainYieldPredictor. Эти символы относятся также ко всем вложенным сущностям. В частности, в пиктограмме класса можно указать уровень доступа к атрибутам и операциям с помощью соответствующих префиксов, приписанных к их именам. Например, на рис. 5.38 показано, что класс Crop имеет один открытый атрибут (scientif icName), один защищенный (yield) и один закрытый (nutrient- Value). Уточненные концепции: имена полюсов ассоциации и квалификаторы В предыдущей главе описана важность идентификации разнообразных ролей, которые играют объекты в ходе взаимодействия с другими объектами. Кратко говоря, роль абстракции — это ее грань, которой она обращена к внешнему миру в конкретный момент времени. Роль определяет цель или силу взаимодействия между классами. В примере, изображенном на рис. 5.39, роль отражается с помощью имени полюса ассоциации (в языке UML 1 это понятие называлось -contributor +infoSource -ΞΗ +assistant +lead CropEncyclopedia +infoSource -userContributor scientificName 0..1 Ведет каталог Crop +staff +Iead0..1 CollaboratesWith Рис. 5.39. Имена сторон ассоциации и квалификаторы
234 Часть И. Метод именем роли), написанного рядом с пиктограммой класса. На рис. 5.39 показано, что классы PlanAnalyst и Nutritionist делают вклад в работу класса CropEncyclopedia. Это значит, что они поставляют информацию для этой энциклопедии. Класс PlanAnalyst является пользователем энциклопедии, поскольку он выполняет поиск информации. В каждом случае роль клиента идентифицирует поведение объекта и протокол, используемый клиентом и его сервером в ходе исполнения роли. Обратите внимание на то, что класс PlanAnalyst имеет рефлексивную ассоциацию, поскольку существует несколько экземпляров этого класса, взаимодействующих друг с другом и использующих отдельные протоколы, отличающиеся от протокола ассоциации с классом CropEncyclopedia. Этот пример демонстрирует также ассоциацию между классами CropEncyclopedia и Crop, которая изображается с помощью квалификатора, показанного в маленьком квадратике возле класса CropEncyclopedia. Квалификатор — это атрибут, однозначно идентифицирующий отдельный целевой объект. В данном примере класс CropEncyclopedia использует в качестве квалификатора атрибут scientif icName, обеспечивающий доступ к отдельным элементам множества экземпляров класса CropEncyclopedia. В целом квалификатор должен быть атрибутом объекта, являющегося частью агрегата на целевой стороне ассоциации. Хотя квалификаторы могут быть многократными, их значение должно быть уникальным. Без квалификатора кратность объектов класса Crop обозначается символом *. Уточненные концепции: ограничения Ограничение (constraint) — это выражение определенного семантического условия, которое должно быть выполнено. Иначе говоря, ограничение — это инвариант класса или отношение, которое должно выполняться, пока система находится в устойчивом состоянии. Следует подчеркнуть, что система должна пребывать именно в устойчивом состоянии, поскольку существуют промежуточные ситуации, в которых состояние системы изменяется (а значит, является временным). Все ограничения, касающиеся системы, находящейся в промежуточном состоянии, выполнить невозможно. Ограничения — это гарантии, выполняющиеся только, если система находится в устойчивом состоянии. Примеры ограничений — предусловия и постусловия, применяемые к системе, находящейся в устойчивом состоянии, т.е. в специальные моменты времени, когда операция активизируется или завершается [21]. В ходе проектирования системы разработчики должны гарантировать, что все наложенные ограничения будут выполнены. Ограничения могут распространяться практически на все элементы модели. Смысл ограничений формулируется в виде строки, заключенной в фигурные скобки {} и размещенной рядом с классом или отношением, на которые они распространяются. Это выражение может быть
Глава 5. Обозначения 235 сформулировано как на естественном языке (в виде текста), так и с помощью более формальной системы обозначений OCL (UML Object Constraint Language). Одним из преимуществ формальной системы обозначений является возможность верификации ограничений. Как правило, ограничения формулируются в виде текста в определенном стиле, принятом среди разработчиков [22]. Размещение ограничения на визуальной диаграмме зависит от количества элементов, на которые оно распространяется. Общие принципы размещения ограничений приведены в табл. 5.2. Однако следует иметь в виду, что на размещение ограничений, помимо общих принципов, влияют особенности используемого программного обеспечения. Таблица 5.2. Размещение ограничений* Количество Размещение ограничений элементов диаграммы Один В примечании, соединенном с элементом пунктирной линией. Возле элемента. Два В примечании, соединенном с элементом пунктирной линии. Возле пунктирной линии, соединяющей элементы. Пунктирная линия может изображаться в виде стрелки, конец которой указывает на первую позицию коллекции. Три и более В примечании, соединенном с элементом пунктирной линии. Возле пунктирной линии, пересекающей ассоциацию (обобщение, агрегацию или объединение). * По мотивам работы Рамбо (Rumbaugh), Джейкобсона (Jacobson) и Буч (Booch) [23]. Ограничения, применяемые к ассоциациям обобщения, означают, является ли классификатор отношения полным. Они разделяются на четыре вида — полные, неполные, непересекающиеся, пересекающиеся [24]. • Полные классификаторы — экземпляр суперкласса является экземпляром по крайней мере одного из подтипов. • Неполные классификаторы — экземпляр суперкласса не является экземпляром хотя бы одного из подтипов. • Непересекающиеся классификаторы — классификаторы не имеют общих экземпляров. • Пересекающиеся классификаторы — классификаторы имеют общие экземпляры. Вернемся к рис. 5.35 и рассмотрим эти ограничения. Ограничение {incomplete } ({неполный}), наложенное на обобщения класса Plan (План), означает, что кроме планов выращивания и полива существуют и другие типы планов. Это
236 Часть П. Метод значит, что экземпляр класса Plan может не быть экземпляром класса Growing- Plan (План выращивания) или GardeningPlan (Садовнический план). Ограничение {disjoint} ({отдельный}) означает, что план не может быть одновременно планом выращивания и садовническим планом, по крайней мере, при указанных определениях классов. Иначе говоря, экземпляр класса GrowingPlan не может быть экземпляром класса GradeningPlan. В диаграммах классов существуют и другие типы ограничений, относящихся к самим классам. К ним, например, относится ограничение {list} ({список}) на атрибут measuredTemperature класса TemperatureSensor, рассмотренное ранее при анализе рис. 5.35. Это ограничение означает, что измерения температуры могут быть упорядоченными и повторяющимися. Как показано на рис. 5.40, ограничения могут накладываться на отдельные классы, ассоциации в целом, а также на части ассоциаций. На данной диаграмме продемонстрировано ограничение кратности, наложенное на класс Environ- mentalController, означающее, что количество экземпляров этого класса в системе не может превышать семи. {момент повторного включения => (момент выключения + 5 минут)} {имеет ¥\ уникальный индекс} Рис. 5.40. Ограничения
Глава 5. Обозначения 237 Класс Cooler (Кондиционер) имеет разные виды ограничений. На его диаграмме показано, что операции с кондиционером обладают гистерезисом — кондиционер нельзя включить раньше, чем через пять минут после его выключения. Это ограничение приписано классу Cooler, поскольку требуется, чтобы этот инвариант выполнялся для всех экземпляров этого класса. На данной диаграмме показаны также два ограничения на ассоциации. В ассоциации между классами EnvironmentalController и Light требуется, чтобы отдельные осветительные приборы имели уникальные индексы. Кроме того, на диаграмме показано ограничение "исключающее или" {хог} на ассоциацию между контроллерами Heater и Cooler, утверждающее, что класс EnvironmentalController не может активизировать нагреватель и кондиционер одновременно. Это ограничение накладывается на ассоциацию, а не на классы Heater и Cooler, так как эти контроллеры нагревателя и кондиционера не в состоянии обеспечить выполнение этого инварианта. Ограничения могут оказаться полезными для выражения вспомогательных классов, атрибутов и ассоциаций. Например, рассмотрим классы Adult (Взрослый) и Child (Ребенок), каждый из которых является подклассом абстрактного класса Person (Человек). В класс Person можно было бы включить атрибуты dateOfBirth (дата рождения) и age (возраст). Однако атрибут age является вторичным: его можно вычислить по значению атрибута dateOfBirth. Таким образом, в нашу модель можно включить оба атрибута, одновременно сформулировать ограничение, указывающее, что один из них вычисляется на основании другого. Выбор вторичного атрибута относится к тактическим решениям, но ограничение в любом случае является его неотъемлемой частью. Аналогично, между классами Adult и Child может существовать ассоциация Parent (Родитель). Кроме того, в зависимости от цели модели между ними можно установить ассоциацию Caretaker (Опекун). Например, такая ситуация возникает, когда моделируются юридические отношения между родителями и ребенком в системе социального обеспечения. Класс Caretaker является вторичным. Он выводится из ассоциации Parent и этот факт можно сформулировать в виде ограничения, наложенного на ассоциацию Caretaker. Уточненные концепции: классы ассоциаций и примечания В заключение рассмотрим концепции, относящиеся к моделированию собственно ассоциаций. Для решения этой проблемы можно использовать обобщенные элементы обычных диаграмм. Рассмотрим пример, продемонстрированный на рис. 5.41. На нем показана ассоциация "множество-множество" между классами Crop (Растение) и Nutrient (Питание). Это значит, что урожай каждого растения зависит от N видов удоб-
238 Часть П. Метод Уточнение отношений между классами Обсуждая пиктограммы, изображающие отношения между классами, мы убедились, что обобщение, агрегация и объединение являются уточнением более абстрактных ассоциаций. В частности, на рис. 5.35 показано, что класс Environ- mentalController агрегирует классы Light, Heater и Cooler как собственные части. На рис. 5.40 эта агрегация заменена более общими отношениями ассоциации. Это объясняется тем, что проект, изображенный на рис. 5.40, может представлять собой решение, сделанное на одном из ранних этапов проектирования. Позднее отношения между классами могли уточняться и представляться с помощью агрегации. Идея, лежащая в основе рис. 5.35, заключается в том, что класс Envi- ronmentalController является чем-то большим, чем подсистемой, состоящей из классов Light, Heater и Cooler. Возможно, в ходе проектирования может понадобиться включить в систему дополнительный класс, реализующий управление как отдельное функциональное свойство — например, класс Controller. рений, а каждое удобрение может использоваться для выращивания N растений. Класс NutrienSchedule (Расписание подкормки) на самом деле представляет свойство отношения "множество-множество", экземпляр которого является конкретным отображением урожай-удобрения. Для выражения этого семантического факта от ассоциации Crop-Nutrient (снабженной атрибутами) проведена пунктирная линия к классу NutrienSchedule (атрибут ассоциации). Каждая ассоциация должна иметь по крайней мере один такой атрибут, называемый классом ассоциаций (association class), а имя такой ассоциации должно совпадать с именем класса, используемого в качестве атрибута. Сама идея снабжать ассоциации атрибутами является обобщением. В частности, в ходе анализа и проектирования существует огромное количество на первый взгляд случайных предположений и решений, собираемых разработчиками. Впоследствии многие из этих идей теряются из-за отсутствия удобного места для их хранения. Голова разработчика не самое надежное место для хранения проектных решений. Таким образом, полезно дополнить элементы диаграмм примечаниями, описывающими предположения и проектные решения. На рис. 5.41 показаны два таких примечания. Примечание, сопровождающее класс NutrientSchedule, сообщает нечто об ожидаемой уникальности его экземпляров. Другое примечание, соответствующее классу Nutrient, отражает ожидания разработчиков, которые заключаются в том, что атрибут unitCost (стоимость единицы) будет запрашиваться из базы данных. Для изображения таких примечаний используются пиктограммы в виде блокнотного листка, которые соединяются с соответствующим элементом с помощью пунктирной линии. В зависимости от используемого программного обеспечения содержание примечаний может быть любым, включая текст, фрагменты кода или
Глава 5. Обозначения 239 Crop пвшшшшяяшшшшшшшшщшш * * Выбирается из общей совокупности расписания NutrientSchedule / / Nutrient В - рН Level: 1 - unitCost: 1 \ N 1 / / Ик. 1ж unitCost: извлекается из базы удобрений Рис. 5.41. Ограничения ссылки на другие документы. Примечание, относящееся к диаграмме в целом, не соединяется ни с одним ее элементом. 5.8 Диаграммы последовательностей Диаграммы последовательностей (sequence diagram) используются для отслеживания хода выполнения сценария в том же контексте, что и диаграммы взаимодействий. (Диаграммы взаимодействий рассматриваются далее.) Основы: объекты и взаимодействия На рис. 5.42 показана диаграмма последовательностей, дублирующая большую часть семантики соответствующей диаграммы взаимодействий. Преимущество диаграммы последовательностей заключается в простоте отслеживания сообщений, передаваемых последовательно. Диаграммы последовательностей часто оказываются удобнее, чем диаграммы объектов (которые будут рассмотрены далее), и позволяют выразить семантику сценария на ранних стадиях проектирования, еще до создания протоколов отдельных классов. Кроме того, диаграммы последовательностей уже на ранних этапах проектирования позволяют очертить контуры разрабатываемой системы. С другой стороны, преимущество диаграмм объектов состоит в удобном масштабировании систем, в которых задействовано большое
240 Часть П. Метод количество часто активизируемых объектов. Таким образом, эти диаграммы конкурируют друг с другом. PlanMetrlcs timeToHarv83t(C) netCost(C) : GafdanlnuPlan С i Crop statusQ maturationTimeQ yiejdQ yieldQ С:Grain Crop ▼ 1.5: netCost(C) Q 1 3: yield PlanAnahirt 1' timeToHarvest(C) · CzGrainCrop :PlanMetrics -1 2: maturationTime 1 1 status :GardeninqPian A 1 4 yield Рис. 5.42. Диаграмма последовательностей (сверху) и связанная с ней диаграмма взаимодействий (снизу) Основы: "линия жизни" и сообщения В диаграмме последовательностей основные сущности (совпадающие с основными сущностями диаграммы объектов) изображаются горизонтально вдоль верхней границы. Из пиктограммы каждого объекта выходит вертикальная пунк-
Глава 5. Обозначения 241 тарная линия, называемая "линией жизни" (lifeline). Эта линия показывает пределы существования объекта. Сообщения (которые часто означают события или инициирование операции) изображаются в виде горизонтальных линий. Концы этих линий расположены на вертикальных линиях, выходящих из пиктограмм, соответствующих объектам на верхней границе диаграммы. Сообщения направляются от отправителя к адресату. Порядок сообщений указывается в вертикальном направлении: первое сообщение расположено выше остальных, а последнее — ниже. В результате нумерация сообщений становится излишней. Тип сообщения отражается с помощью разнообразных линий и стрелок, представленных на рис. 5.43. Objectl Objectt Синхронное сообщение Т1 Асинхронное сообщение -^г1 Ответное сообщение Потерянное сообщение Найденное сообщение О" Сообщение об уничтожении ЧЭ X Рис. 5.43. Диаграмма последовательностей (сверху) и связанная с ней диаграмма взаимодействий (снизу) Синхронное сообщение (synchronous message), как правило, представляющее собой вызов операции, изображается в виде сплошной линии с закрытой стрелкой. Асинхронное сообщение (asynchronous message) изображается в виде сплошной линии с открытой стрелкой. Потерянное сообщение (lost message), т.е. сообщение, не дошедшее до адресата, представляет собой синхронное сообщение, линия которого упирается в конечную точку (закрашенный кружок). Найденное сообщение (found message) — сообщение с неизвестным отправителем — представляется как синхронное сообщение, исходящее из конечной точки.
242 Часть П. Метод Уточненные концепции: уничтожение Уничтожение (destruction event) означает, что объект разрушен. Этот факт изображается символом X, расположенным к конце "линии жизни". Примером такого события является уничтожение объекта Ob j ect2, показанное на рис. 5.43. Если уничтоженный объект входит в объединение, то другие объекты в этом объединении могут быть также уничтожены. Диаграммы последовательностей очень просты. Однако для выражения некоторых довольно сложных взаимодействий к ним можно добавить новые элементы. Уточненные концепции: спецификация выполнения Простые диаграммы последовательностей могут не указывать положения фокуса управления при передаче сообщений. Например, если объект А посылает сообщения X и Υ другим объектам, может быть неясно, являются ли эти сообщения независимыми или представляют собой часть одного и того же сообщения Ζ. Как показано на рис. 5.42 и 5.43, для уточнения таких ситуаций каждую вертикальную линию, исходящую из объектов диаграммы последовательностей, можно снабдить прямоугольником, с помощью которого указывается относительный момент времени, в который фокус управления находится на данном объекте. Например, на рис. 5.44 первым объектом, на котором находится фокус управления, является безымянный экземпляр класса GardeningPlan, ответственный за поддержание климатических условий с помощью вызовов других методов, в свою очередь вызывающих другие методы. В конце концов фокус управления возвращается на объект GardeningPlan. ; Gqr<teningPlan ; Environmental Controller setClimateQ : Heater getTemperatureQ 5^ heatQ —~ύ coolQ F3 : Cooler Ή Рис. 5.44. Спецификация выполнения
Глава 5. Обозначения 243 Сценарий Диаграммы последовательностей могут содержать текстуальные описания, хотя эта возможность не является стандартной для языка UML 2.0. В сложных ситуациях, связанных с проверкой условий и итерациями, диаграммы последовательностей можно усовершенствовать с помощью сценариев (scripts). Как показано на рис. 5.45, сценарий можно написать на левом поле диаграммы, причем этапы сценария могут быть согласованы с передачей сообщений. Сценарии можно писать в свободном формате, на естественном языке или используя специальный язык реализации. : GardeninaPlan Поддерживать климатический план Определить текущую температуру Если температура слишком низкая, то включить нагреватель, иначе включить кондиционер Зарегистрировать изменение микроклимата ; Environmental Cpntrollw ; Heam setClimateQ ML F3 getTemperatureQ 6-*—J heatQ -πι coolQ ; СИП ■D Рис. 5.45. Сценарии и диаграммы последовательностей Уточненные концепции: механизм использования взаимодействий В языке UML 2.0 существуют разнообразные конструкции, позволяющие упростить сложные диаграммы последовательностей. Первым из них является механизм использования взаимодействий (interaction use). Он позволяет указать на диаграмме последовательностей, что проектировщик намерен повторно использовать некое взаимодействие, определенное в другом месте. Этот факт изображается с помощью метки ref, заключенной в рамку, как показано на рис. 5.46. В данном случае проведена модификация предыдущей диаграммы последовательностей — в нее включена последовательность Login (Регистрация), которую необходимо выполнить до того, как действующее лицо PlanAnalyst приступит к использованию системы. Метка ref означает, что в данное место диаграммы вставляется (т.е. копируется) последовательность Login. Фактическую последовательность действий можно было бы изобразить с помощью другой диаграммы.
244 Часть П. Метод : PlanAnalyst ! PlanMotrics : |rf у 1 — Login [ timeToHarve3t(C) _ InetCost(C) status() : GarcUnlngPlan 1 *~\ yield С: Crop maturationTimeO 0 t m yieldO J* С: Grain Crop *L ^1 ϊ Рис. 5.46. Механизм использования взаимодействия Login Уточненные концепции: управляющие конструкции Дополнительные фрагменты могут не только упрощать диаграммы последовательностей, но и иллюстрировать конструкции управления. Например, на рис. 5.47 продемонстрировано включение цикла в диаграмму последовательностей. Обратите внимание на рамку, в которую вписано ключевое слово loop. Выполнение последовательности операций в этой рамке зависит от условия [для каждого садовнического плана]. Предположим, что существует несколько объектов GardeningPlan, часть которых являются активными, а часть — пассивными (к их числу относятся прошлые планы, сохраненные для истории). Как избежать перебора всех пассивных планов, сосредоточившись только на активных? Это можно сделать, вставив в диаграмму оператор взаимодействия alt (сокращение от слова "alternatives" — альтернативы), как показано на рис. 5.48. Выбор альтернативы внутри цикла управляется условиями [Садовнический план выполняется]и [Садовнический план не выполняется]. Эти условия определяют, какая из ветвей цикла должна выполняться. Область оператора alt разделяется на две части, каждая из которых имеет свое собственное условие. Если такое условие является истинным, то выполняются функции, предусмотренные в соответствующей части.
Глава 5. Обозначения 245 : : ну ι Login loop [Для кв [ timeToHarvest(C) _ J жцого садовнического плана] InetCost(C) statusQ yield maturationTime() 0 Crop ^ ■ ^ yleld() U" \ r ] Рис. 5.47. Оператор взаимодействия loop Для манипулирования потоком управления на диаграмме последовательностей можно использовать многие другие операторы взаимодействия. Дальнейшую информацию можно найти в литературных источниках, перечисленных в приложении Б. 5.9 Диаграммы обзора взаимодействий Диаграммы обзора взаимодействий (interaction overview diagrams) — это комбинация диаграмм деятельности и диаграмм взаимодействий, предназначенная для обзора потока управления между элементами диаграмм. Несмотря на то что для создания диаграмм обзора взаимодействий можно использовать диаграммы взаимодействий любого типа (последовательностей, коммуникации или синхронизации), наиболее распространенной является диаграмма последовательностей. Основные элементы диаграмм обзора взаимодействий — рамка, элементы потока управления и элементы диаграмм взаимодействий.
246 Часть П. Метод PlanAnalyst piapMetrics ; GardeningPlan rof Login tlmeToHarve3t(C) loop Loop / [Для каждого садовнического плана] с; Crop С; oraln Crop alt [Садов! нический план выполняется] statusQ maturatlonTlmeQ [Садовнический план не выполняется]! yieldQ y'eidQ netCost(C) Ρ Рис. 5.48. Оператор взаимодействия alt Основы: рамки Диаграмма обзора взаимодействий обычно заключена в рамку (frame). Однако рамка является необязательной, если контекст диаграммы вполне ясен. На рис. 5.49 показана рамка с названием sd MaintainTemperature lifelines :En- vironmentalController, : Heater, : Cooler в левом верхнем углу. Эти имена имеют следующий смысл. • sd: дескриптор, означающий диаграмму взаимодействия. • MaintainTemperature (Поддержка температурного режима): имя, описывающее предназначение диаграммы. • lifelines :EnvironmentalController, rHeater, :Cooler ("линии жизни" '.Контроллер окружающей среды, -.Обогреватель, кондиционер): необязательный список "линий жизни", содержащихся в диаграмме.
Глава 5. Обозначения 247 sd MaintainTemperature lifelines :EnvironmentalController,:Heater,:Cooler J EvaluateTemperature О [нижний предел <= температура <= верхний предел] [иначе] [температура меньше нижнего предела] ® [температура больше верхнего предела] sd Heat Ζ , EnvironmentalController : Heater U heat(heatTime) Τ] sdCooiy : EnvironmentalController •Cooler ! coot(coolTime) ^ { D +U l> Рис. 5.49. Диаграмма обзора взаимодействий подсистемы MaintainTemperature Основы: элементы потока управления Альтернативные и параллельные пути потока управления в диаграмме обзора взаимодействий изображаются с помощью элементов диаграмм деятельности. Выбор альтернативного пути обеспечивается комбинацией узла принятия реше-
248 Часть П. Метод ний, в котором происходит разветвление, и соответствующего узла слияния (при необходимости) для объединения альтернативных путей. На рис. 5.49 такая комбинация встречается дважды. В первый раз узел принятия решения используется для того, чтобы выяснить, находится ли температура в требуемом диапазоне (т.е. никаких действий предпринимать не нужно) или выходит за его пределы (т.е. необходимо нагреть или охладить воздух). Для выбора правильной альтернативы проверяется ограничение взаимодействия [ нижний предел <= температура <= верхний предел]. Вторая комбинация узла принятия решений и узла слияния позволяет выбрать правильное действие — нагрев или охлаждение, — проверив условие [температура меньше нижнего предела] и [температура больше верхнего предела]. Параллельные потоки управления обеспечиваются с помощью узла разветвления (fork node), использующегося для расщепления путей, и соответствующего узла слияния (join node), соединяющего параллельные пути в один поток. Следует подчеркнуть, что при наличии параллельных путей их метки должны поступать в узел объединения до того, как поток управления получит разрешение следовать дальше. Это позволяет при блокировке потока управления вдоль одного из путей обработать метку одной из его альтернатив [25]. Основы: элементы диаграммы взаимодействий Диаграмма обзора взаимодействий содержит два вида элементов: обозначающие взаимодействие и использование взаимодействия. К первому виду относятся элементы диаграммы, описывающие детали взаимодействия. Как правило, они являются диаграммами последовательностей. Они могут быть как безымянными, так и именованными. Так, на рис. 5.49 показаны взаимодействия Heat и Cool. Использование взаимодействия подразумевает не описание самого взаимодействия, а ссылку на соответствующую диаграмму. На рис. 5.49 такая ссылка имеет имя EvaluateTemperature (Оценка температурного режима). Взаимодействие EvaluateTemperature характеризуется следующими свойствами. • Периодичность измерений температуры. • Защита компрессоров путем запрета на включение объекта : Cooler раньше, чем через пять минут после его выключения. • Настройка температуры в зависимости от времени дня. • Настройка температуры в зависимости от вида растений. 5.10 Диаграммы композитных структур Диаграмма композитной структуры (composite structure diagram) позволяет изобразить структурированный классификатор с помощью определения его внут-
Глава 5. Обозначения 249 реннего устройства, состоящего из частей и взаимодействий между ними. Структурированные классификаторы могут быть вложенными, т.е. каждая их часть сама может быть структурированным классификатором. Структурный классификатор может быть не только компонентом, но и классом. Таким образом, диаграмма сложной структуры представляет собой полезный инструмент проектирования, позволяющий провести декомпозицию классов на составные части и смоделировать их взаимодействие на этапе выполнения программ [26, 27]. Основными элементами сложной структуры являются части, порты, интерфейсы и соединительные звенья. Основы: части композитных структур На рис. 5.50 представлена диаграмма композитной структуры WaterTank, входящей в состав системы управления гидропонной теплицей. Ее имя указано в верхней части диаграммы. Для удобства группа проектировщиков должна использовать согласованные правила образования таких имен. Структура Water- Tank состоит из двух частей: Heater и Tank, взаимодействующих друг с другом и поддерживающих требуемую температуру воды для полива. h : Heater [1] t: Tank [1] э-0—О Ρ—Ρ u—0—о Electricity Рис. 5.50. Диаграмма композитной структуры WaterTank Имена составных частей композитной структуры имеют формат имя роли : Имя Класса [кратность]. Название роли определяет предназначение, которое имеет конкретная часть внутри структуры. Кратность является необязательным параметром. На рис. 5.50 она указана лишь для иллюстрации, поскольку структура WaterTank состоит лишь из одного компонента Heater и одного компонента Tank. Основы: порты и интерфейсы сложной структуры Композитная структура и ее части обмениваются информацией с внешней средой через порты, обозначаемые маленькими квадратиками на границе части или всей структуры. На рис. 5.50 показано, что компоненты Heater и Tank имеют порты, через которые они взаимодействуют друг с другом, обеспечивая работу структуры WaterTank. Кроме того, структура WaterTank имеет порт, через ко-
250 Часть П. Метод торый она получает электричество для питания компонента Heater, и порт, через который она передает нагретую воду от компонента Tank во внешнюю среду. Использование портов для обеспечения всех взаимодействий позволяет сохранить инкапсуляцию структурированного классификатора. По умолчанию все порты открыты для доступа. Скрытые порты изображаются маленькими квадратами, размещенными внутри структуры полностью так, что лишь одна из их границ соприкасается с внешней границей структуры. Эти порты можно использовать для закрытого тестирования системы. Имя и кратность порта не обязательны, но их использование повышает ясность проекта. Имена портов имеют следующий формат: имя порта : Тип Порта [кратность]. Указывать тип порта не обязательно [28, 29]. К портам присоединяются интерфейсы, определяющие детали взаимодействия между композитной структурой и внешней средой. Эти интерфейсы, как правило, изображаются в виде розетки (socket) и штепселя (ball). Требуемый интерфейс изображается как розетка. Он означает услуги, ожидаемые от внешней среды. Предоставляемый интерфейс изображается в виде штепселя и означает услуги, оказываемые внешней среде. Основы: соединительные звенья композитной структуры Соединительные звенья внутри диаграммы композитной структуры обеспечивают обмен информацией между структурой и внешней средой, а также между ее внутренними частями. На рис. 5.50 изображены три соединительных звена. Два из них заканчиваются на границе структуры. Такие звенья называются соединительными звеньями делегирования (delegation connectors). Звено между компонентами Heater и Tank называется соединительным звеном сборки (assembly connector), или соединительным звеном интерфейса (interface connector). На рис. 5.50 показано, что компонент Heater поставляет компоненту Tank тепло. Несмотря на то что на рис. 5.50 соединительное звено сборки обозначается прямой линией, как и соединительное звено делегирования, их можно было бы изобразить в виде розетки и штепселя. Имена соединительных звеньев не обязательны. Например, на рис.5.50 имена не указаны, поскольку схема ясна и без этого. Уточненные концепции: механизм сотрудничества Механизм сотрудничества (collaboration) — это разновидность структурированного классификатора, определяющего взаимодействие между его экземплярами в ходе выполнения программы. Механизм сотрудничества отличается от сложной структуры тем, что он не создает свои экземпляры, а лишь определяет их роли и соединительные звенья, с помощью которых они взаимодействуют друг с другом. Механизмы сотрудничества могут быть вложенными и позволяют сосредоточить внимание на главных вопросах, не обращая внимание на детали.
Глава 5. Обозначения 251 Детали механизма сотрудничества можно выразить с помощью диаграмм взаимодействий [31, 34]. Механизмы сотрудничества обычно используются для определения шаблонов, т.е. шаблонных ролей, объединенных соединительными звеньями. В ходе выполнения программы экземпляры классификатора обязаны исполнять указанные роли, обеспечивая требуемое функционирование системы. Например, на рис. 5.51 показан механизм сотрудничества TemperatureControl (Управление температурой), определяющий шаблон управления температурой в системе управления гидропонной теплицей. В этом шаблоне компонент TemperatureController (Контроллер температуры) использует компонент TemperatureRamp (Температурный график), определяющий точную температуру, требуемую в разные моменты времени для поддержания жизнедеятельности растений [83, 84]. „-** TemperatureControl г / г / / controller: TemperatureController [1] requiredTemp: TemperatureRamp [1..*] Рис. 5.51. Механизм сотрудничества TemperatureControl Имя механизма сотрудничества, указанное внутри пунктирного овала, можно отделить от определений ролей с помощью горизонтальной пунктирной линии (на рисунке не указана). В данном механизме сотрудничества предусмотрены две роли: TemperatureController и TemperatureRamp, соединенные линией. Поскольку имя соединительного звена не указано, считается, что оно будет задействовано в ходе выполнения программы как временный объект, например, как свойство или аргумент. Если бы оно имело имя, то его можно было бы считать экземпляром реальной ассоциации, например, связью [85, 86]. Имена и тип ролей указываются в формате имя роли : Тип Роли [кратность]. Имя роли описывает конкретный экземпляр классификатора, способного ее исполнить, а тип роли ограничивает свойства этого экземпляра классификато-
252 Часть П. Метод ра. Например, на рис. 5.51 указаны имена, типы и кратность ролей объектов TemperarureController и TemperatureRamp [97, 98]. Роль определяет свойства структурированного классификатора, необходимые для участия в механизме сотрудничества. Тип роли означает, что исполнить ее может любой экземпляр классификатора, имеющий соответствующий интерфейс. Функциональные свойства экземпляра классификатора могут быть шире, чем требует от него конкретная роль. Таким образом, он может одновременно играть несколько ролей в рамках одного и того же механизма сотрудничества и даже в разных механизмах сотрудничества [89, 90]. 5.11 Диаграммы конечных автоматов Диаграммы конечных автоматов (state machine diagrams) широко используются в промышленных отраслях, связанных с выполнением процессов в реальном времени. Они позволяют проектировать и анализировать системы реального времени, в которых последовательность и своевременность процессов имеют большое значение. Типичными примерами, в которых диаграммы конечных автоматов могут играть важную роль при анализе реакции систем на происходящие события, являются медицинские устройства, финансовые электронные системы, а также системы управления спутниками и вооружением. Диаграмма конечных автоматов выражает поведение системы в виде последовательности состояний, переключаемых событиями и связанных с ними действий. Такие конечные автоматы называются поведенческими (behavioral state machines). Как правило, они используются для описания поведения отдельных объектов. Однако с их помощью можно описывать поведение и более крупных элементов любой системы. (Напомним, что, как указывалось в главе 1, выбор уровня абстракции в сложной системе зависит от наблюдателя.) Диаграммы конечных автоматов отдаленно напоминают диаграммы деятельности. Однако диаграммы конечных автоматов сосредоточивают внимание на состояниях и переходах от одного состояния к другому, а не на потоках действий. Не каждый класс реализует поведение, зависящее от событий. По этой причине диаграммы конечных автоматов применяются только к тем классам, поведение которых определяется событиями. Кроме того, диаграммы конечных автоматов позволяют продемонстрировать реакцию всей системы на происходящие события в целом. На этапе анализа диаграммы конечных автоматов можно использовать для описания динамического поведения системы. На этапе проектирования диаграммы конечных автоматов позволяют отразить динамическое поведение отдельных классов или механизма сотрудничества между классами. Основными элементами диаграммы конечных автоматов являются состояния и переходы между ними.
Глава 5. Обозначения 253 Основы: начальное, конечное и простое состояния Состояние объекта представляет собой совокупный результат его поведения. Например, только что включенный в сеть телефон находится в холостом состоянии: его предыдущее поведение несущественно и он готов передавать и принимать звонки. Если кто-нибудь поднимет трубку, то телефон издаст зуммер (off-hook) и перейдет в состояние передачи сигнала (dialing state). В этом состоянии никто не ожидает, что телефон зазвонит, и готовится к беседе с абонентом. Если же телефон находится в состоянии отбоя (on-hook) и звонит, то, когда абонент поднимет трубку, телефон перейдет в состояние приема, и абонент сможет поговорить со звонящим человеком. В любой момент времени состояние объекта определяется набором его свойств (обычно статических) и их текущих значений (обычно динамических). Под "свойствами" подразумевается совокупность всех атрибутов объекта и его отношений с другими объектами. Понятие состояния отдельного объекта можно обобщить на класс объектов, так как все объекты одного класса существуют в одном и том же пространстве состояний. Это пространство содержит неопределенное, хотя и конечное, множество возможных (не всегда ожидаемых или желаемых) состояний. Когда объект пребывает в определенном состоянии, можно сделать следующее. • Выполнить какое-нибудь действие • Ожидать событие • Выполнить условие • Сделать что-нибудь из перечисленного выше или все сразу На каждой диаграмме конечных автоматов должно быть точно указано начальное состояние, предусмотренное по умолчанию. Оно обозначается с помощью неименованного перехода из специальной пиктограммы, представляющей собой закрашенный кружок. Иногда возникает необходимость обозначить конечное состояние. Как правило, конечный автомат, связанный с классом или системой, никогда не достигает конечного состояния. Он просто исчезает, когда содержащий его объект уничтожается. Конечное состояние изображается с помощью неименованного перехода на специальную пиктограмму, представляющую собой слегка увеличенный незакрашенный кружок. С формальной точки зрения, начальное и конечное состояния являются псевдосостояниями (pseudostates). На рис. 5.52 изображены элементы таймера в системе управления гидропонной системой. Имя простого состояния указывается внутри прямоугольника с закругленными углами. На рис. 5.52 приведены два простых состояния таймера — Initializing (Инициализация) и Timing (Отсчет времени). Простые состояния не имеют вложенных состояний (substates).
254 Часть П. Метод Начальное Конечное состояние состояние Q (инициализация! ί времГи | Состояние Состояние Рис. 5.52. Обозначения простых состояний Основы: переходы и состояния Изменение состояний называется переходом (transition). На диаграмме конечных автоматов переходы обозначаются направленными стрелками, соединяющими два состояния. На рис. 5.53 показан переход таймера из начального состояния в состояние Initialization (Инициализация), затем из состояния Initialization в состояние Timing (Отсчет времени), а затем из состояния Timing в конечное состояние. Изменение состояния называется запуском перехода (firing the transition). Состояние может иметь переход само в себя. Как правило, из одного и того же состояния можно перейти в несколько разных состояний, но все переходы должны быть однозначными, т.е. ни при каких обстоятельствах не может произойти одновременно несколько переходов из одного состояния. С ^ Инициализация Отсчет времени Переход , , , . Переход Переход Рис. 5.53. Переходы между состояниями таймера Существует много способов управления запуском переходов. Переход, не имеющий аннотации, называется безусловным (completion transition). Это значит, что после завершения исходного состояния переход в целевое состояние выполняется автоматически. На рис. 5.53 показан завершающий переход из состояния Initializing в состояние Timing. После инициализации таймер немедленно переходит в состояние отсчета времени. В других ситуациях для перехода в новое состояние необходимо, чтобы произошло определенное событие. Такие переходы сопровождаются комментариями. Событием называется явление, способное изменить состояние объекта. Например, в поведении гидропонной теплицы играют важную роль следующие события: • посажено новое растение; • урожай созрел; • из-за плохой погоды упала температура в теплице; • отказал кондиционер;
Глава 5. Обозначения 255 • наступил заданный момент времени. Каждое из первых четырех перечисленных выше событий является причиной определенных действий, например, начала или прекращения выполнения некоторого плана работ, включения нагревателя или посылки сигнала тревоги на пульт управления. Другим фактором является отсчет времени. Хотя секунды или минуты могут не иметь значения для системы (растения созревают намного медленнее), наступление нового часа или суток может быть сигналом для включения/выключения освещения и изменения температуры в теплице, чтобы имитировать смену дня и ночи, необходимую для роста растений. На рис/5.54 приведена диаграмма состояний таймера. Как следует из этой диаграммы, таймер можно перевести в состояние Paused (Остановлен), а затем возобновить его работу, в ответ на события pause (пауза) и resume (возобновить) соответственно. Рис. 5.54. Дополнительные состояния и события, связанные с таймером Переходы могут быть рекурсивными, т.е. описывать возврат в исходное состояние. Элементы языка UML, рассмотренные выше, относятся к основным элементам всех диаграмм состояния и переходов (state transition diagram). В совокупности они позволяют описывать простые конечные автоматы, пригодные для ситуации с конечным количеством состояний. Системы, имеющие много состояний либо связанные с большим количеством событий или зависящие от предыстории, требуют использования более сложных понятий. Уточненные концепции: вход, операция и выход из состояния Операции могут зависеть от состояния объекта. В частности, можно указать, какое действие следует выполнить, когда наступит определенный момент времени в зависимости от состояния, в котором будет находиться объект. • Выполнить определенное действие при входе в конкретное состояние.
256 Часть П. Метод • Выполнить определенное действие, находясь в конкретном состоянии. • Выполнить определенное действие, выходя из конкретного состояния. Эта концепция проиллюстрирована на рис. 5.55. Переходя в состояние Timing, объект инициализирует отсчет времени (этот факт обозначен пиктограммой в виде стрелки, упирающейся в две параллельные линии), а выходя из этого состояния (этот факт изображается в виде стрелки, находящейся между двумя параллельными линиями) — прекращает отсчет времени (этот факт не обозначается никакими пиктограммами). Находясь в состоянии Timing, таймер ведет отсчет времени (этот факт изображается с помощью круговой стрелки). о- Инициализация Отсчет времени fl| | Запустить таймер ^0 Отсчет времени |р\ Остановить таймер Остановить Возобновить Пауза Рис. 5.55. Вход, действие и выход Уточненные концепции: управляемые переходы Кроме событий, существуют и другие механизмы управления переходами из одного состояния в другое. Для управления этими переходами можно сформулировать определенные условия. Эти условия гарантируют, что при наступлении некоего события переход будет разрешен (если условие выполняется) или запрещен (если условие не выполняется). Кроме того, переходами можно управлять с помощью действий (effects). Действие — это функция (например, процесс или операция), выполняющаяся, когда происходит определенное событие. Таким образом, когда наступает такое событие, происходит запуск перехода и выполняется определенная функция. Каждый из этих механизмов управления можно использовать в сочетании с другими. Продемонстрируем концепцию действия на примере таймера. Предположим, что в системе управления гидропонной теплицей произошел отказ кондиционера. Вместо того чтобы надеяться, что этого никогда не случится, можно настроить
Глава 5. Обозначения 257 таймер так, чтобы он работал только одновременно с кондиционером. Цель такой настройки — напомнить о необходимости регламентного обслуживания кондиционера после определенного времени работы. Такое обслуживание должно предотвратить отказ оборудования. Таким образом, диаграмму конечных автоматов следует уточнить так, как показано на рис. 5.56. Инициализировать, жГ" очистить [кондиционер включен]/обнулить счетчик < Инициализация. Отсчет времени fit Запустить таймер Ό Отсчет времени f/»| Остановить таймер [продолжительность работы превышает срок обслуживания] Остановить^ Возобновить Пауза Выключить Выключить Рис. 5.56. Уточненная диаграмма конечных автоматов для таймера На этой диаграмме переход в заключительное состояние заменен условием, указывающим, что когда продолжительность работы превысит заданный период [продолжительность работы превышает срок обслуживания], таймер должен перейти в состояние Sounding Alarm (Сигнал тревоги) и выдать сигнал, предупреждающий о необходимости провести регламентные работы. Переход из состояния Сигнал в состояние Отсчет времени обусловлен сочетанием события, условия и действия. Как только регламентные работы будут завершены, условия должны быть аннулированы, а отсчет времени должен быть возобновлен. В этом сочетании есть событие очистить, защищенное условием, что кондиционер должен быть включен до того, как будет возобновлен отсчет времени (в квадратных скобках) — [кондиционер включен]. Если кондиционер окажется выключенным, переход не происходит. Если кондиционер будет включен, то выполняется действие, указанное после косой черты (показания таймера обнуляются — обнулить счетчик), запускается переход и отсчет времени начинается снова. Порядок проверки условий очень важен. При заданном состоянии S, из которого при событии Ε совершается переход Τ с условием С и действием А, операции выполняются в следующей последовательности. • Происходит событие Е.
258 Часть П. Метод • Проверяется условие С. • Если условие С выполняется, то осуществляется переход Τ и выполняется действие А. Это означает, что если условие С не выполняется, то переход не может быть осуществлен до тех пор, пока событие Ε не произойдет еще раз и условие С не будет проверено еще раз. Побочные эффекты при проверке условия или выполнении действия при выходе из состояния не влияют на переход. Например, предположим, что произошло событие Е, условие С является истинным, но действие А, выполняемое при выходе из состояния S, изменило ситуацию так, что условие С стало ложным. В этом случае переход Τ все равно будет выполнен. Уточненные концепции: сложные и вложенные состояния До сих пор мы рассматривали простые состояния и переходы между ними. В более сложных системах диаграммы конечных автоматов могут быть более крупными, запутанными и громоздкими. Возможность использовать вложенные состояния помогает избежать чрезмерного увеличения количества состояний и переходов между ними. На рис. 5.57 показаны вложенные состояния Отсчет времени, Сигнал и Остановлен. Такие состояния изображаются с помощью границы, охватывающей область (region). Как следует из рис. 5.57, сложное состояние Функционирование содержит вложенные состояния Отсчет времени, Сигнал и Пауза. Очевидно, что эта диаграмма имеет более простую структуру, поскольку в ней существует только один переход из сложного состояния Функционирование в заключительное состояние. Это значит, что когда в одном из вложенных состояний происходит событие выключить, осуществляется переход в заключительное состояние. Глубина вложения может быть произвольной. Таким образом, любое сложное состояние можно заменить совокупностью вложенных. На рис. 5.57 сложное состояние Функционирование имеет три вложенных состояния, реализующих семантику отношения XOR (исключительного ИЛИ). Если система находится в сложном состоянии Функционирование, то она может находиться в одном из трех вложенных состояний: Отсчет времени, Сингал или Пауза. Выбирая определенный уровень детализации, можно устанавливать как крупный, так и мелкий масштаб изображения. Укрупнение масштаба позволяет скрыть вложенные состояния, а уменьшение — показать их. Укрупнив масштаб диаграммы, представленной на рис.5.57, можно получить более простую диаграмму, изображенную на рис. 5.58.
Глава 5. Обозначения 259 Инициализировать очистить [кондиционер включен]/обнулить счетчик Отсчет времени f\\ Запустить таймер О Отсчет времени И Остановить таймер [продолжительность превышает срок обслуживания] Сигнал Остановить" Возобновить Выключить Выключить Рис. 5.57. Сложное состояние и вложенные состояния Инициализировать Рис. 5.58. Высокоуровневая диаграмма конечных автоматов для таймера Уточненные концепции: параллельность и управление Параллельные функциональные свойства можно изобразить на диаграмме конечных автоматов, просто разделив сложное состояние на несколько подобластей пунктирными линиями. Каждая из подобластей внутри сложного состояния описывает поведение, реализуемые параллельно. На рис. 5.59 показаны три подобласти параллельного поведения. В данном примере, когда истекает срок обслуживания кондиционера, таймер издает предупредительный сигнал. Ранее, на рис. 5.56, в этом случае конечный автомат переходил в состояние Сигнал. Предположим теперь, что вместо сигнала
260 Часть П. Метод [ Сложное состояние ^ [Подобласть А] I [Подобласть В] [ Подобласть С1 V J Рис. 5.59. Параллельные подобласти в диаграмме конечных автоматов таймера, по истечении срока обслуживания кондиционера таймер должен начать отсчет запаздывания. Как показано на рис. 5.60, для этого состояние Сигнал следует заменить сложным состоянием Просрочка обслуживания, состоящим из двух состояний: Сигнал и Измерение просрочки. Таким образом, при переходе в состояние Просрочка обслуживания оба вложенных состояния реализуются параллельно, т.е. таймер издает сигнал тревоги и отсчитывает продолжительность задержки одновременно. (На этой диаграмме исключен переход, позволяющий отключить сигнал тревоги без включения кондиционера — см. переход выключить из состояния Сигнал на рис. 5.56). Это гарантирует, что таймер не будет молчать, пока не будет проведено обслуживание. Поток управления через параллельные состояния можно изобразить разными способами, каждый из который имеет собственный смысл. Таким образом, выбирая способ представления потока управления, следует быть осторожным. Продемонстрируем это на примере обобщенного сложного состояния, показанного на рис. 5.61. Существует много способов перехода в сложное состояние. Например, можно перейти в сложное состояние так, как показано на рис. 5.62. В этом случае активизируются все параллельные подавтоматы. Каждая отдельная подобласть может иметь начальное состояние, заданное по умолчанию (псевдостационарное состояние). Рекомендуется явно указывать начальные состояния подобластей, чтобы не возникало недоразумений, хотя это и не обязательно. В сложное состояние можно перейти с помощью узла ветвления. Это состояние также относится к категории псевдостационарных (как начальное и конечное). Оно используется для расщепления входящего потока на несколько исходящих.
I a 0< S 8
262 Часть П. Метод Использование ветвления показано на рис. 5.63. Переход в область параллельных состояний может сопровождаться событием и/или дополнительным условием перехода. Выход нескольких потоков из области параллельных состояний не может сопровождаться событиями или условиями. В рассмотренном примере узел ветвления расщепляет поток управления в сложном состоянии и направляет его на целевые состояния А, В и С. Рис. 5.61. Обобщенное сложное состояние с параллельными подобластями Рис. 5.62. Переход в сложное состояние Аналогичную конструкцию можно использовать и для выхода из сложного параллельного состояния. На рис. 5.64 показан переход из сложного состояния в следующее. Переход из параллельного состояния осуществляется, когда потоки управления покидают состояния А, В и С. Кроме того, можно использовать узел объединения (еще одно псевдосостояние) для слияния потоков управления на выходе из сложного параллельного состояния. На рис. 5.65 показан множественный переход из отдельных параллельных состояний на узел, представленный в виде вертикальной черты, в котором
Глава 5. Обозначения 263 Рис. 5.63. Переход в сложное состояние с помощью ветвления • О *® -*CD *® Рис. 5.64. Выход из сложного состояния они сливаются в общий поток. Каждый из этих переходов может сопровождаться событием и дополнительным условием. В данном случае переход в состояние S происходит, когда все объединенные события A, D и С являются активными, выполняется оговоренное событие и удовлетворяется указанное условие. Ситуация, представленная на рис. 5.65, не равносильна ситуации, изображенной на рис. 5.66. На рис. 5.66 не происходит слияния потоков управления. В данном случае, если происходит один из переходов из состояний A, D или С, то все параллельные состояния прекращаются. Если некоторые подобласти явно не участвуют в объединении (как показано на рис. 5.67), то при объединении потоков управления на выходе состояния, не участвующие в объединении, прекращаются. И наоборот, если некоторая под-
264 Часть П. Метод Рис. 5.65. Объединение потоков управления на выходе из сложного состояния Рис. 5.66. Отдельные выходы из сложного состояния область явно не участвует в ветвлении, то потоки управления, не участвующие в ветвлении, будут выполняться, начиная с их начального состояния [8, 9]. ТП *э Рис. 5.67. Частичное участие в объединении и ветвлении
Глава 5. Обозначения 265 Уточненные концепции: состояние конечного автомата Наряду с простыми и сложными состояниями, существует третий тип состояния: состояние подавтомата. Эти состояния используются для упрощения диаграмм автоматов или представления общих функциональных свойств, предназначенных для повторного использования. Вернемся к рис. 5.56. Предположим, что по истечении срока обслуживания требуется сделать намного больше, чем просто издать сигнал тревоги. Допустим, что второй таймер должен отсчитывать время, в течение которого кондиционер ожидает обслуживания, а система должна записывать температуру, давление хладагента, моменты включения и выключения, а также влажность. Все это можно описать лишь с помощью более сложной диаграммы конечных автоматов. Как показано на рис. 5.68, для упрощения диаграммы конечных автоматов вложенное состояние Сигнал следует заменить состоянием подавтомата Функционирование : Запись. Это состояние подавтомата представляет собой совершенно отдельную диаграмму конечных автоматов. Таким образом, подавтоматы позволяют организовать сложную диаграмму конечных автоматов и упростить ее анализ. Уточненные концепции: дополнительные элементы диаграмм конечных автоматов Вероятно, диаграммы конечных автоматов являются наиболее богатыми инструментами языка UML с семантической точки зрения. Они могут быть чрезвычайно сложными. Диаграмма конечных автоматов может содержать много других элементов, помимо упомянутых выше (например, точки входа и выхода, короткие или длинные легенды, протоколы и т.д.). Более подробно все эти элементы описаны в работах, перечисленных в приложении Б. 5.12 Диаграммы синхронизации Любой человек, занимавшийся проектированием логических электрических схем, инженер-электронщик или даже простой радиолюбитель сталкивался с диаграммами синхронизации. Эти диаграммы десятилетиями использовались в электротехнике и других отраслях промышленности, где поведение элементов системы во времени имеет большое значение. Диаграммы синхронизации являются разновидностью диаграмм взаимодействий. Их цель — продемонстрировать, как изменяются состояния элементов системы со временем и как события влияют на эти изменения.
Глава 5. Обозначения 267 Основы: элементы диаграмм синхронизации Диаграммы синхронизации содержат много элементов, использующихся в других диаграммах языка UML. Они имеют одну или несколько "линий жизни", один или несколько объектов (или других классификаторов языка UML), два или больше состояний и т.д. Все эти элементы уже рассматривались выше. Основы: схема Диаграммы синхронизации содержат элементы языка UML и представляют их пользователю разными способами. Общая схема диаграммы синхронизации напоминает диаграмму последовательностей, повернутую на 180° (см. рис. 5.69). временная линия событие s МММ временные метки Рис. 5.69. Обобщенная диаграмма синхронизации Диаграммы синхронизации содержат одну или несколько "линий жизни" (выглядящих как прямоугольник) для каждого объекта диаграммы. Внутри каждой "линии жизни" указывается ее название (т.е. имя объекта), состояния объекта. Переходы от одного состояния к другому указываются с помощью временной линии (timeline), вдоль которой расположены события, влияющие на изменение состояний. Для того чтобы пользователь лучше понял смысл диаграммы синхронизации, вдоль горизонтальной линии откладываются временные метки. Например, на рис. 5.70 показана простая диаграмма синхронизации для объекта Valve (Клапан), управляющего заполнением объекта WaterStorageTank (Резервуар воды) в системе гидропонной теплицы. Как видим, объект Valve имеет два простых состояния: open (открыт) и closed (закрыт). Сама по себе эта диаграмма несет мало информации. (На самом деле она неполна.) Неясно, когда открывается клапан и когда он закрывается, а также какие события вызывают изменение его состояния. линия жизни время
268 Часть П. Метод открыт ι 1 Г закрыт i I ' 11111 м 11111111 г Рис. 5.70. Диаграмма синхронизации объекта Valve Основы: события События (и другие стимулы, например, сообщения), вызывающие изменение состояний объекта, показываются внутри "линии жизни" возле временной линии объекта. На рис. 5.71 приведена диаграмма синхронизации объекта Valve, содержащая два события, вызывающих изменение его состояния: TankLow и Tank- Full. TankLow TankFull открыт Ι Ι u I 5 закрыт ■ ' 1 11111 μ 111111111' Рис. 5.71. Диаграмма синхронизации объекта Valve, содержащая события Основы: ограничения Для уточнения условий, влияющих на изменение состояния объекта, используются ограничения (constraints). На рис. 5.72 показана диаграмма синхронизации объектов Valve и Heater, содержащая ограничения. На этой диаграмме показана зависимость между состояниями объектов Heater и Valve. Как показано на диаграмме, ограничение объекта Heater указывает, когда снова можно будет включить обогреватель. (Это ограничение предотвращает слишком частое включение и выключение нагревающих элементов, приводящее к его быстрому износу.) Ограничение показывает, что после выключения обогревателя его можно включить вновь не раньше, чем через три минуты.
Глава 5. Обозначения 269 TankLow открыт * закрьм alve α с > выключен TankFull ,*-"~{ >3 минут } ► ι ι ι ι ι ι м ι ι ι ι 1 1 II 1 1 1 1 1 1 мм I 1 I Рис. 5.72. Диаграмма синхронизации двух объектов, содержащая ограничения Уточненные концепции: альтернативное представление Если диаграмма синхронизации содержит слишком много объектов, имеющих много состояний, то вместо временных линий можно использовать более компактное представление, показанное на рис. 5.73. В этом случае состояния указываются внутри шестиугольников, а изменения состояний — между ними. состояния изменения состояний Рис. 5.73. Компактное представление вместо временной линии На альтернативных диаграммах синхронизации изменения состояний изображаются не в виде холмов и впадин на временной линии, а виде точек соприкосновения между шестиугольниками.
270 Часть П. Метод Уточненные концепции: события и сообщения Как уже указывалось, на изменения состояний могут влиять не только события, но и сообщения. Но какие и когда? Между событиями и сообщениями есть небольшая разница: событие имеет определенные пространственные и временные координаты, в отличие от сообщений. Например, на рис. 5.71 показаны два события: TankLow и TankFul 1, которые представляют собой физическое состояние резервуара. Вместо этих событий, для открытия или закрытия клапана можно использовать сообщения. Предположим, садовник решил добавить воды в резервуар, несмотря на то что ее уровень еще не достиг нижнего предела. Садовник просто хочет увеличить объем воды в резервуаре. В данном случае сообщение является более удобным инструментом, чем событие. На рис. 5.74 показаны два сообщения (OpenCmd и CloseCmd), представляющие собой команды открыть клапан для заполнения резервуара и закрыть клапан, чтобы прекратить наполнение резервуара соответственно. закрыт CD _> СО > открыт openCmd/ /closeCmd ι_ выключен ι Ό включен I ι— СО О ' и 111 м 111111 и ι' Рис. 5.74. Использование сообщений вместо событий Для выражения проектного решения на диаграмме UML можно использовать как события, так и сообщения. Однако если есть сомнения, то лучше проверить семантику сомнительных элементов (т.е. сообщений и событий) и действовать в соответствии с результатами этой проверки. Диаграммы UML — это не просто эскизы. Каждый элемент диаграммы имеет определенный смысл и предназначение.
Глава 5. Обозначения 271 5.13 Диаграммы объектов Диаграмма объектов (object diagram) показывает существующие объекты и связи между ними в логической схеме системы. Иначе говоря, диаграмма объектов представляет собой мгновенный снимок потока событий в определенной конфигурации объектов. Таким образом, диаграммы объектов являются своего рода прототипами: каждая из них представляет структурные отношения, которые могут возникнуть среди элементов данного множества экземпляров классов. В этом смысле отдельная диаграмма объектов представляет объектную структуру системы. На этапе анализа объектные диаграммы часто используются для указания семантики первичных и вторичных сценариев, описывающих поведение системы. На этапе проектирования диаграммы объектов используются для иллюстрации семантики механизмов в логической схеме системы. Независимо от стадии разработки на диаграммах объектов изображаются реальные объекты, помогающие визуализировать диаграммы соответствующих классов. Основными элементами диаграмм объектов являются объекты и отношения между ними. Основы: объекты На рис. 5.75 показана пиктограмма, изображающая объект на диаграмме объектов. Как и на диаграммах классов, текст, размещенный на этой пиктограмме, можно разделить на две части с помощью горизонтальной линии: над линией указывается имя объекта, а под ней — его атрибуты. Однако особенность пиктограммы объекта состоит в том, что эта горизонтальная линия не проходит от края до края. objectName :ClassName f attributeNamel = valueA Ρ attributeName2 = valueB | Рис. 5.75. Пиктограмма обобщенного объекта Имя объекта можно указать тремя способами. • имяОбъекта Имя объекта • :ИмяКласса Имя класса • имяОбъекта :ИмяКласса Имя объекта и класса Имена объектов всегда подчеркиваются, чтобы отличить их от имен классов. Если класс объекта никогда не указывается, то класс считается безымянным. Если
272 Часть П. Метод указывается имя класса, то объект считается безымянным. Каждая пиктограмма, не содержащая имени объекта, обозначает отдельный безымянный объект. Для некоторых объектов может оказаться полезным указать несколько их атрибутов. Слово "несколько" использовано потому, что объект отражает только один из аспектов структуры объектов. Имена каждого из этих атрибутов должны соответствовать атрибутам, определенным в классе объекта, или в любом из его суперклассов. Синтаксис имен атрибутов должен также включать возможность указывать их значения, как показано на рис. 5.75. Основы: отношения между объектами Как указывалось в главе 3, объекты взаимодействуют с другими объектами через связи, как показано на рис. 5.76, представляющем собой диаграмму объектов, соответствующую диаграмме классов. Связь — это экземпляр ассоциации, аналогично тому, как объект — это экземпляр класса. anthony nutritionist +assistant +lead -contributor susan :PlanAnalyst +lead +staff -userContributor +infoSource roger :PlanAnalyst -userContributor +infoSource +infoSource :CropEncyclopedia scientificName = Fragaria χ ananassa | Catalogs commercialStrawberry :Crop 1 Рис. 5.76. Отношения между объектами
Глава 5. Обозначения 273 Связь между двумя объектами может существовать тогда и только тогда, когда существует ассоциация между соответствующими классами. Ассоциация между классами может проявляться разными способами, например, как простая ассоциация, обобщение, агрегация или объединение. Следовательно, существование ассоциации между двумя классами означает существование канала связи между их экземплярами, по которому объекты могут посылать друг другу сообщения. Все классы неявно имеют ассоциации сами с собой и, следовательно, объект может послать сообщение сам себе. Уточненные концепции: имена и квалификаторы Как уже отмечалось, основными элементами диаграммы объектов являются объекты и отношения между ними. Однако для многочисленных очень запутанных проектов требуется нечто большее, чем эти простые обозначения. Напомним, что эти сложные свойства следует применять только тогда, когда возникает необходимость описать намеченную семантику сценария. На диаграмме классов при изображении ассоциации рядом с ней может быть указана ее роль, обозначающая цель или мощность связи одного класса с другим. Для некоторых диаграмм объектов полезно заново указать эту роль связи между объектами. Такая метка помогает объяснить, почему один объект взаимодействует с другим. Рис. 5.76 представляет собой пример использования такого дополнительного обозначения. На нем некоторый объект класса PlanAnalyst по имени Susan использует информацию, поступающую от безымянного объекта CropEncyclopedia (Справочник по растениям), и заносит информацию об определенном растении в этот объект, исполняя роль userContributor, как указано в соответствующей метке. Сравнивая рис.5.76 и 5.39, можно увидеть, что существует два экземпляра класса PlanAnalyst: один из них — Susan, исполняющий роль lead (руководитель) и взаимодействующий с объектом Roger, который исполняет роль staff (сотрудник) и относится к тому же самому классу. Кроме того, объект Susan играет роль руководителя по отношению к объекту Anthony (объект класса Nutritionist). На рис. 5.39 представлена категория меток, называемых квалификаторами (qualifiers), значения которых однозначно идентифицируют отдельный объект среди множества объектов, участвующих в ассоциации. В частности, класс CropEncyclopedia использует атрибут scientif icName для перемещения по элементам множества, управляемого экземплярами класса CropEncyclopedia. На рис. 5.76 показан экземпляр commercialStrawberry. Ему соответствует значение Fragaria x ananassa3, которое принимает квалификатор scien- tificName. 3 Растение Fragaria x ananassa имеет много названий, например, коммерческая клубника, садовая клубника, культивируемая клубника и просто клубника.
274 Часть П. Метод Помимо обозначений, используемых на диаграммах классов, на диаграммах объектов можно указывать ограничения, метки в виде ключевых слов, символы перехода и связи. 5.14 Диаграммы коммуникации Читатели, знакомые с предыдущими версиями языка UML, могут узнать в диаграмме коммуникации (communication diagram) ее предшественника — диаграмму взаимодействий (collaboration diagram). Диаграмма коммуникации — это разновидность диаграмм взаимодействий, в центре внимания которой находятся способы связи между объектами и сообщения, передаваемые объектами по этим линиям. Основы: объекты, связи и сообщения Связь между двумя объектами существует только тогда, когда между соответствующими классами существует ассоциация. Это значит, что между экземплярами этих классов существует канал для обмена сообщениями (т.е. связь). Предположим, что объект А имеет связь L с объектом В. Объект класса А может выполнять любую операцию, применимую к классу В и доступную для класса А. То же самое может сделать объект класса В по отношению к классу А. В этом случае говорят, что объект, вызывающий операцию, является клиентом (client), а объект, предоставляющий операцию, называется сервером (server). Как правило, отправитель сообщения знает получателя, но получатель не всегда знает отправителя. В стационарном состоянии структура классов и структура объектов системы должны быть согласованными друг с другом. Если известно, что операция Μ вызывается по связи L из объекта класса В, то спецификация класса В (или спецификация соответствующего суперкласса) должна содержать объявление операции М. На рис. 5.77 приведен пример диаграммы коммуникации в системе управления гидропонной теплицей. Эта диаграмма позволяет проиллюстрировать взаимодействие между объектами в ходе выполнения основной функции системы — предсказать урожай для конкретного растения. Как показано на рис. 5.77, возле каждой связи на диграмме можно указать сообщение, которое по ней передается. Направление передачи сообщения изображается стрелочкой. Чаще всего сообщения используются для вызова операций или в качестве сигнала. Вызовы операций могут содержать фактические параметры, соответствующие ее сигнатуре (см. сообщение timeToHarvest на рис. 5.77).
Глава 5. Обозначения 275 ▼ 1.5: netCost(C) JL :PlanAnaiyst 1.3: yield CrGrainCrop A 1.4: yield 1: timeToHarvest(C) :PlanMetrlcs План должен выполняться ■ 1.2: maturationTime 1.1: status :GardeniiiqPlan Рис. 5.77. Диаграмма коммуникации в системе управления гидропонной теплицей Основы: нумерация сообщений Предсказание урожая невозможно без взаимодействия между несколькими объектами. Для того чтобы продемонстрировать явный порядок событий, перед сообщением указывается его порядковый номер (начиная с 1). Эта нумерация определяет относительный порядок сообщений. Сообщения, имеющие более низкие последовательные номера, передаются раньше сообщений, имеющих более высокие последовательные номера. Последовательные номера, указанные на рис. 5.77, указывают порядок передачи сообщений в нашем примере. Используя вложенную схему десятичной нумерации (например, 4.1.5.2), можно показать глубину вложения сообщения внутри следующего высокоуровневого вызова процедуры. Каждое целое число означает уровень вложения внутри взаимодействия. Одинаковые целые числа означают, что соответствующие сообщения имеют одинаковые приоритеты. На рис. 5.77 сообщение с номером 1.3 следует за сообщением с номером 1.2, которое следует за сообщением 1.1. Все эти сообщения вложены в вызов операции timeToHarvest (т.е. сообщение с номером 1).
276 Часть П. Метод Из этой диаграммы видно, что сценарий начинается с того, что объект Plan- Analyst вызывает функцию timeToHarvest () из объекта PlanMetrics. Обратите внимание на то, что фактическим аргументом этой функции является объект С. Затем объект PlanMetrics вызывает операцию status () из объекта GardeningPlan. На диаграмме приведено примечание, указывающее на необходимость проверки того, что план действительно выполняется. В свою очередь, объект GradeningPlan вызывает операцию maturationTime () из выбранного объекта GrainCrop, запрашивая у него время, оставшееся до созревания растения. После выполнения оператора условного выбора управление возвращается объекту PlanAnalyst, который вызывает функцию yield (), рекурсивно вызываемую из объекта С: GrainCrop. Затем управление передается объекту Plan- Analyst, и выполнение сценария завершается вызовом функции netCost () из самого объекта PlanAnalyst. (На диаграмме показана связь между объектами PlanAnalyst и GardeningPlan. Несмотря на то что по этому каналу связи не передается ни одно сообщение, наличие этой связи подчеркивает существование семантической зависимости между этими двумя объектами.) На рис. 5.78 показаны те же сообщения, что и на рис. 5.77, но в другой последовательности. Здесь сообщения 1.1 и 1.2 вложены в сообщение timeToHarvest (1), а сообщение 2.1 — в сообщение yield (2). Несмотря на другую структуру, эта диаграмма описывает то же самое поведение системы. 2 yield Рис. 5.78. Вариант рис. 5.77 с другой последовательностью сообщений
Глава 5. Обозначения 277 Нумерация сообщений может также содержать имена, означающие параллельные сообщения на конкретном уровне вложения. Например, используя имена а и Ь, можно показать, что сообщения 7.2 аи7.2Ь передаются параллельно при передаче сообщения 7.2. Каждое из этих сообщений имеет отдельный поток управления. Уточненные концепции: сообщения и синхронизация H:Heater ■ 2: startup :EnvironmentalController C.'Cooler I 1: turnOn ■ <— 3 isReady Рис. 5.79. Объекты и синхронизация На рис. 5.79 продемонстрированы довольно запутанные способы синхронизации сообщений, возникающих в диаграммах коммуникации. Сообщение startup () является примером простого вызова. Оно изображается в виде направленной линии с закрашенной стрелкой. Сообщения такого вида называются синхронными. Передавая сообщения startup () и isReady (), клиент должен подождать, пока сервер полностью обработает сообщение, и лишь после этого может возобновить работу. Сообщение turnOn () имеет немного другую семантику. Она является примером несинхронного сообщения и изображается незакрашенной стрелкой. В данном случае клиент посылает сообщение серверу для обработки, сервер ставит сообщение в очередь, а затем клиент обрабатывает его, не ожидая ответа от сервера. Передача асинхронных сообщений напоминает обработку системных прерываний.
278 Часть П. Метод Уточненные концепции: итерационные выражения и дополнительные условия Для уточнения порядка передачи сообщений в нумерацию можно включать дополнительную информацию. Например, при передаче серии сообщений, в нумерацию можно добавить итерационное выражение. Внешний вид такого выражения зависит от программного обеспечения, но можно использовать и псевдокод. На рис. 5.80 итерационное выражение сопровождает передачу сообщения turnOn (). Итерационное выражение изображается в виде звездочки, за которой следует перечисление в квадратных скобках. Этот пример показывает, что сообщение turnOn() передается последовательно η раз. Если бы сообщения передавались параллельно, то после звездочки следовали бы две вертикальные черты (т.е. * I I [i=l. . η]). H.Heater - 2: [температура меньше минимальной] startup L:Li(iht * #" lEnvironmentalCoiitroller C:Cooler ι I 1:*[i=1 .n]:tumOn • 3. isReady Рис. 5.80. Итерационные выражения и предохранители на диаграмме коммуникации Сообщения могут сопровождаться дополнительными условиями. Они изображаются точно так же, как итерационное выражение, только без звездочки. Как показано на рис. 5.80, дополнительное условие заключается в квадратные скобки (см. сообщение startup). Это значит, что сообщение будет обработано, только если будет выполнено дополнительное условие, в данном случае, — если температура будет ниже установленного предела. Способ выражения дополнительного условия внутри квадратных скобок является индивидуальным.
Глава 5. Обозначения 279 Резюме • Проектирование — это не процесс рисования диаграмм; диаграммы просто отражают результаты проектирования. • При проектировании сложной системы важно рассмотреть ее с разных точек зрения — понятийной, логической и физической структуры, а также структурной и динамической семантики. • Язык UML содержит тринадцать видов диаграмм: диаграммы пакетов, диаграммы компонентов, диаграммы развертывания, диаграммы прецедентов использования, диаграммы деятельности, диаграммы классов, диаграммы последовательностей, диаграммы обзора взаимодействий, диаграммы композитных структур, диаграммы конечных автоматов, диаграммы синхронизации, диаграммы объектов и диаграммы коммуникации. • Диаграмма пакетов является инструментом организации артефактов про- уг ёктирования для анализа предметной области и представления проектных решений. Диаграмма пакетов позволяет сосредоточить внимание на физической структуре визуальной модели или представлении модели с разных точек зрения. • Диаграмма компонентов показывает внутреннюю структуру компонентов и их зависимости от других компонентов. Эта диаграмма позволяет представить компоненты, сотрудничающие с помощью точно определенных интерфейсов с целью обеспечения функционирования системы. • Диаграмма развертывания показывает расположение артефактов в узлах физического проекта системы. Отдельная диаграмма развертывания отражает структуру артефактов системы. На этапе проектирования диаграммы развертывания используются для указания физической совокупности узлов, являющихся платформой для реализации системы. • Диаграмма прецедентов использования отражает контекст, в котором создается система и обеспечивается ее функционирование. Они представляют элементы, взаимодействующие в системе, и показывают, что внешний мир ожидает от системы. • Диаграмма деятельности позволяет изобразить потоки операций в рамках системных, производственных, технологических и других процессов. Эти диаграммы сосредоточивают внимание на выполняемых операциях и распределении ответственности за их выполнение. β Диаграмма классов показывает существующие классы и связи между ними в логической структуре системы. На этапе анализа диаграмма классов отражает общие роли и обязанности сущностей, реализующих функциональные свойства системы. На этапе проектирования диаграмма классов отражает структуру классов, образующих архитектуру системы.
280 Часть П. Метод • Диаграмма последовательностей позволяет отследить выполнение сценария в том же контексте, что и диаграмма объектов. В большой степени диаграмма последовательностей просто является еще одним способом представления диаграммы объектов. • Диаграмма обзора взаимодействий — это сочетание диаграмм деятельности и диаграмм взаимодействий для обзора потоков управления между их элементами. Среди всех диаграмм взаимодействий наибольшее распространение получили диаграммы последовательностей. • Диаграммы композитных структур позволяют изображать структурные классификаторы и показывать их внутреннюю структуру. Эти диаграммы также полезны на этапе проектирования для декомпозиции классов на составные части и моделирования их взаимодействия на этапе выполнения программ. • Диаграммы конечных автоматов используются для проектирования и анализа систем реального времени. Эти диаграммы выражают поведение в виде серии состояний, переход между которыми управляется событиями, а также сопутствующих действий. • Диаграмма синхронизации — это разновидность диаграммы взаимодействий. Их цель — показать, как изменяются состояния системы во времени и как события изменяют эти состояния. • Диаграмма объектов показывает существующие объекты и связи между ними в логической схеме системы. Она позволяет представлять структуру объектов системы и обычно используется для описания сценариев. • Диаграмма коммуникации является разновидностью диаграмм взаимодействий. В центре ее внимания находятся способы связи между объектами и методы передачи сообщений между объектами, участвующими в конкретном взаимодействии.
ГЛАВА 6 ПРОЦЕСС Дилетанты постоянно ищут некий волшебный метод или инструмент, который мог бы сделать процесс разработки программ тривиальным. В отличие от них, профессионалы знают, что такой панацеи не существует. Дилетанты хотят иметь готовые рецепты; профессионалы знают, что такой подход ведет к негодным проектным решениям и нагромождению лжи, за которой разработчики скрываются от ответственности за ранее принятые неверные решения. Дилетанты либо игнорируют документацию вообще, либо делают из нее фетиш, заботясь больше о том, как их бумажный продукт выглядит в глазах заказчика, чем о его сути. Профессионал признает важность документации, но всегда отдает предпочтение разумным архитектурными новшествам. Процесс объектно-ориентированного анализа и проектирования невозможно описать с помощью рецептов, однако он определен достаточно хорошо, чтобы стать основой прогнозируемого и воспроизводимого процесса разработки программного обеспечения. В главе изучаются процессы анализа и проектирования (его цели, результаты, этапы и критерии успеха), а также приведен обзор процесса разработки программного обеспечения в целом. 6.1 Основные принципы Начнем обсуждение процессов анализа и проектирования с их основных принципов, т.е. критериев удачности проекта. Характерные черты удачных проектов Удачным называется проект, полностью или с избытком соответствующий ожиданиям заказчика, завершенный вовремя и в рамках сметы, а также легко
282 Часть И. Метод поддающийся изменению и адаптации. Пользуясь этим критерием, рассмотрим характеристики1, присущие удачным проектам и явно отсутствующие у неудачных: • Четкая архитектурная концепция. • Хорошо организованный итеративный и поступательный процесс проектирования. Четкая архитектурная концепция Четкая архитектурная концепция присуща практически всем удачным проектам. Что же такое архитектура проекта? В соответствии с рекомендациями IEEE Recommended Practice for Architectural Description of Software (IEEE 1471) архитектурой считается "фундаментальная организация системы, выраженная через его компоненты, отношения между ними и с внешней средой, а также принципы ее проектирования и развития" [20]. В настоящее время существуют и другие определения архитектуры, но большинство из них утверждает, что архитектура тесно связана со структурой и поведением системы, важными проектными решениями и стилем, зависит от организаторов проекта и их окружения, а также воплощает решения, основанные на логических рассуждениях [19]. Система, имеющая продуманную архитектуру, отличается концептуальной целостностью. Как утверждает Брукс (Brooks), "концептуальная целостность — наиболее важный аспект проектирования" [1]. Обычно конечный пользователь не интересуется архитектурой системы. Однако "ясная внутренняя структура" играет важную роль в построении понятных, тестируемых, устойчивых систем, допускающих расширение и реорганизацию [2]. Только ясность архитектуры дает возможность выявить общие абстракции и механизмы, позволяющие сделать систему проще, компактнее и надежнее. Как не существует единственного правильного способа классифицировать абстракции, так не существует единственного правильного метода разработки архитектуры. В любой предметной области всегда найдутся и глупые, и элегантные способы проектирования. Как же отличить хорошую архитектуру от плохой? Как правило, хорошая архитектура является объектно-ориентированной и структурированной по компонентам. Это не значит, что любая объектно-ориентированная архитектура хороша, или что хороша только объектно-ориентированная архитектура. Однако, как было показано в главах 1 и 2, применение принципов объектно- ориентированной декомпозиции приводит к архитектуре, обладающей требуемыми свойствами организованной сложности. Читатели могут возразить, что существует множество других признаков удачных проектов, и будут правы. Однако в данной главе мы выбрали характеристики, имеющие непосредственное влияние на процессы объектно-ориентированного анализа и проектирования.
Глава 6. Процесс 283 Хорошей архитектуре программного обеспечения присущи следующие свойства. β Хорошая архитектура представляет собой многоуровневую систему абстракций. На каждом уровне абстракции связаны друг с другом с помощью четко определенного и управляемого интерфейса, а также основываются на столь же хорошо продуманных абстракциях нижнего уровня. • В системах с хорошей архитектурой между интерфейсом и реализацией на каждом уровне абстракции существует четкая граница. Это позволяет изменять реализацию абстракции без нарушения предположений внешних клиентов. • Хорошая архитектура проста: общее поведение достигается общими абстракциями и механизмами. Архитектура, созданная таким способом, как правило, является менее сложной, а также более надежной и гибкой. Сторонники методов быстрой разработки систем отрицают важность предварительной разработки архитектуры. Вместо этого они выдвигают на передний план такие концепции, как простота, скорость и "удачливость" [25]. В таких проектах архитектура развивается со временем. Выбор архитектуры зависит от контекста проекта. В любом случае, время и способы разработки архитектуры не снижают важности самой архитектурной концепции. Без нее систему труднее совершенствовать и поддерживать. Итеративный и поступательный жизненный цикл В некоторых предметных областях решаемая задача с самого начала имеет четкую формулировку и много способов ее реализации. В этом случае процесс разработки можно практически полностью формализовать. Разработчики новых систем в таких предметных областях заранее знают наиболее важные абстракции, механизмы их реализации и ожидаемое поведение системы. Несмотря на то что творчество продолжает оставаться важным компонентом процесса разработки систем, такие задачи настолько точно поставлены, что выбор стратегических решений почти предопределен. В этих ситуациях можно достичь чрезвычайно высокой эффективности, поскольку риск, связанный с процессом разработки, сведен к нулю [3]. Чем больше разработчик знает о решаемой задаче, тем легче ее решить. Обычно промышленные задачи не обладают такими свойствами. Цель большинства из них — установить соответствие уникальных требований к функциональности и эффективности. Для этого требуется полная творческая отдача всей команды разработчиков. В таких условиях невозможно применять готовые рецепты. Разработка программного обеспечения, как и любая человеческая деятельность, требует творчества и инноваций, применения итеративного и посту-
284 Часть П. Метод пателыюго процесса, опирающегося на опыт, интеллект и талант каждого члена коллектива2. Итеративный и поступательный процесс разработки программного обеспечения предусматривает, что система разрабатывается в виде последовательных версий (в этом проявляется итеративный характер процесса), сложность которых постепенно возрастает (в этом проявляется его поступательность). Версия может быть внешней (т.е. доступной для пользователей) или внутренней (т.е. недоступной для пользователей). Выбор функциональных свойств, разрабатываемых на каждой итерации, зависит от того, какой вид риска уменьшается на данном этапе. Наиболее важные виды риска должны исключаться в первую очередь. Достижения и результаты, полученные на одной из итераций, используются на следующей. Это позволяет постепенно уточнять стратегические и тактические решения, приближаясь к простому, надежному и гибкому решению, удовлетворяющему требования заказчика (как правило, не имеющие точной формулировки). Итеративный и поступательный подход является основой современных методов разработки программного обеспечения, включая такие методы быстрого проектирования, как экстремальное программирование (Extreme Programming — ХР) и SCRUM. Он очень хорошо соответствует объектно-ориентированной парадигме и сулит много выгод, касающихся управления риском. Как уместно заметил Гилб (Gilb), "эволюционное 3 проектирование было изобретено для того, чтобы получать предупреждающие сигналы о надвигающейся опасности" [6]. Перечислим некоторые преимущества итеративного подхода к проектированию [23]. • Возможность учета изменяющихся требований. Каждая итерация ориентируется на определенную совокупность ограничений. • Отсутствие авральной интеграции элементов в конце проекта. Каждая итерация предусматривает интеграцию элементов, включаемых в очередную версию. Интеграция элементов проводится последовательно и постоянно. 2 Эксперимент "Один день" ("Day in the Life"), проведенный под руководством Буча (Booch), подкрепляет эти выводы. Этот эксперимент был проведен во вторник, 27 марта 2001 года. В нем участвовали 50 проектировщиков со всего мира. Буч исследовал работу группы профессиональных разработчиков программного обеспечения, наблюдая за их действиями и применением инструментов. В результате исследований Буч пришел к следующим выводам: "Отдельные проектировщики и коллективы разработчиков сталкиваются с большой неопределенностью, неоднозначностью и хаосом. Для того чтобы справиться с этим, необходимы творчество, предсказуемость и повторяемость. .. Проектирование — это командный вид спорта... Производительность труда коллектива разработчиков превосходит по важности эффективноть работы отдельных программистов" [18]. 3В рамках эволюционного проектирования решение вырабатывается постепенно, а не фиксируется заранее. Эволюционное проектирование хорошо согласуется с итеративным и поступательным подходом, поскольку каждая итерация предоставляет возможность для развития системы на основе обратной связи с предыдущей итерацией.
Глава 6. Процесс 285 • Риски исключаются на ранних стадиях проектирования. На первых итерациях исключаются основные риски и выявляются новые. Исключение рисков на ранних стадиях проектирования проще, чем на более поздних. • Появляется возможность повторного использования проектных решений. Основные компоненты архитектуры создаются на ранних этапах проектирования, поэтому идентификация повторно используемых элементов и возможность их применения упрощаются. • Появляется возможность выявить недостатки проекта на более ранних стадиях. На каждой итерации проводится тестирование, позволяющее выявить и устранить дефекты. Поиск ошибок не переносится на конец проектирования, когда времени на исправление ошибок может не хватить (или последствия ошибок слишком велики). • Возрастает производительность труда сотрудников. Итеративная разработка стимулирует применение модели, в которой члены коллектива играют несколько ролей, в отличие от конвейерной организации труда, в которой аналитик отделен от проектировщика, проектировщик — от программистов, а программисты — от испытателей и т.д. Итеративный подход позволяет учесть опыт членов команды и исключает перебрасывание ответственности с одного на другого. • Члены коллектива постоянно учатся. На каждой итерации они имеют возможность извлекать уроки из прошлых ошибок ("практика — путь к совершенству"). Вопросы, возникающие на одной итерации, можно решить на следующей. • Процесс разработки становится более точным и совершенным. На каждой итерации производится оценка работы системы с точки зрения процесса и ее организации. Результаты этих оценок используются для улучшения проекта на следующей итерации. Рассмотрим теперь характеристики, позволяющие отделить удачные проекты от неудачных. Для начала рассмотрим диапазон доступных в настоящее время методов проектирования и некоторые стратегии их совершенствования. Рациональный процесс проектирования Парнас (Parnas) и Клементе (Clements) утверждают, что "невозможно найти процесс, позволяющий рационально разрабатывать программное обеспечение" [4], поскольку в ходе проектирования необходимо проявлять творчество и изобретательность. Однако, как они говорят: "Есть и хорошие новости — эти качества можно имитировать... (Поскольку) дизайнеры нуждаются в руководящих принципах, сделать проектирование более рациональным можно, если следовать общим правилам, а не руководствоваться соображениями, продиктован-
286 Часть П. Метод ными спецификой конкретной задачи. Когда организация ведет много проектов, стандартная процедура облегчит ее работу... Если существует представление об идеальном проекте, то гораздо легче оценивать прогресс выполняемого в данный момент проекта. Как уже отмечалось, жизненный цикл проекта должен быть хорошо организованным, итеративным и поступательным. Проект считается хорошо организованным, если им легко управлять и существуют критерии измерения его успеха, но в то же время он является достаточно гибким, чтобы оставить разработчику простор для творчества и изобретательности. В разделе рассматриваются современные стили проектирования и формулируются некоторые рекомендации по выбору стиля, наиболее подходящего для конкретного проекта и конкретной организации. В настоящее время существует широкий диапазон стилей проектирования программного обеспечения: RUP, XP, SCRUM, Crystal и др. Выбор стиля оказывает сильное влияние на планирование и проектирование программного обеспечения, и даже может предопределить успех или провал проекта. Таким образом, решение следует принимать обдуманно. К счастью, выбор стиля может не быть однозначным. На самом деле в ходе проекта можно применять все современные стили: от ускоренных до планомерных4. Переход от одного стиля к другому зависит от конкретной задачи и общей стратегии проекта. Основной целью ускоренного проектирования (agile process) является создание системы, удовлетворяющей текущие потребности заказчика за кратчайшее время. Этот подход основан на принципе "все средства хороши". Таким образом, ускоренное проектирование характеризуется следующими свойствами. • Легковесность и разбросанность, неформальный характер (система делает только самое необходимое и ничего более). • Используются знания, которыми члены коллектива разработчиков должны обладать по умолчанию (а не хорошо документированный процесс разработки). • Проект носит тактический, а не стратегический характер (будущие возможности игнорируются, поскольку будущее еще не наступило). • Итеративный характер и поступательность (система поставляется частями). • Большая надежда на сотрудничество с заказчиком, принимающим активное участие в формулировке требований и их оценке. • Самоорганизация и эффективное управление (коллектив разработчиков организуется оптимальным образом). • Внезапность в противоположность предопределенности (процесс развивается спонтанно, а не планомерно). 4Различия между скоростными и планомерными подходами проанализированы в работе Бёма (Boehm) и Тернера (Turner) [16].
Глава 6. Процесс 287 Ускоренные процессы проектирования освобождают разработчиков от следования строго определенным предписаниям и позволяют им сконцентрироваться на творчестве. Планомерные процессы проектирования, кроме создания системы в оговоренные сроки, позволяют принимать предсказуемые и повторяемые проектные решения. В этом процессе не все средства хороши и он имеет самостоятельную ценность. Иначе говоря, кроме удовлетворения требований, выдвинутых заказчиком, основными результатами проектирования являются сам процесс проектирования и его артефакты. Планомерные процессы проектирования имеют следующие свойства. • Основательность и более формальный характер (процесс следует предписанным правилам и порождает хорошо документированные артефакты). • Опора на хорошо документированные процессы (в отличие от использования знаний, предполагаемых по умолчанию). • Стратегический, а не тактический характер (определение четких рамок, регламентирующих будущие изменения). • Опора на контракт с заказчиком (описание проекта разрабатывается и согласовывается с заказчиком заблаговременно). • Управляемость (процесс подчиняется детальному плану с ясно указанными контрольными точками и точками верификации как внутри команд разработчиков, так и между ними)5. • Проект формулируется заранее и постоянно уточняется (предусматривает явные процедуры и средства улучшения). Распространенное заблуждение гласит, что ускоренное проектирование не сводится к процессам и носит исключительно творческий характер, а планомерное проектирование, наоборот, сводится только к процессам и не дает простора для творчества. Это не совсем верно. Ускоренное проектирование не отбрасывает использование процессов. Оно предназначено для быстрого реагирования на изменение как самой задачи, так и процесса ее решения. Ускоренное проектирование нельзя назвать более творческим, чем планомерное. Итеративный и поступательный характер планомерного проектирования, предусматривающего использование прототипов, оставляет много места для проявления творческих способностей и изобретательности. Выбор наиболее подходящего стиля для конкретного проекта лучше всего делать в два этапа. Сначала следует определить характеристики вашего проекта и организации, и выбрать стиль проектирования. Затем необходимо уточнить 5Планомерные процессы не всегда носят итеративный и поступательный характер (например, проект может применять принцип "водопада"), но это свойство очень желательно.
288 Часть II. Метод правила проектирования, в частности, указать методы, характерные для других стилей, так чтобы ваш процесс проектирования сохранял баланс между методами ускоренной и планомерной разработки, соответствующим конкретной ситуации. Например, если вы склоняетесь к ускоренному проектированию, то вся стратегия проекта должна быть направлена на его скорейшее выполнение. Затем, в зависимости от того, насколько проект далек от применения планомерного подхода, следует выбрать, адаптировать и уточнить некоторые из планомерных методов. Следует подчеркнуть, что стиль проектирования может зависеть от стадии жизненного цикла проекта. На ранних этапах чаще применяются ускоренные методы, а на поздних — более формальные. Для того чтобы определить свое место на шкале процессов проектирования, следует сравнить характеристики проекта со свойствами разных стилей и выбрать наиболее близкий стиль. Основные свойства проектов, связанных со стилем проектирования, перечислены в табл. 6.1. Выбирая между ускоренным и планомерным проектированием, следует оценивать риск. С какими рисками сталкивается проект? Выберите стиль и соответствующие методы, минимизирующие эти риски. При этом следует выяснить, возрастает риск при выборе того или иного стиля или убывает. Всегда следует стремиться уменьшить риск. Кроме того, выбирая стиль, вы можете его настроить, руководствуясь собственным вкусом, доступными инструментами, имеющимся временем и намерениями заказчиков. В любом случае проект должен удовлетворять требованиям заказчика. Таким образом, каждый проект лишь выиграет, если частично будут использоваться средства ускоренного проектирования (что обеспечит гибкость и откроет простор для творчества и изобретательности) и частично — средства планомерного проектирования (что обеспечит предсказуемость, возможность повторного использования проектных решений и непротиворечивость). Используя упомянутые выше термины Парнаса и Клементса, можно сказать, что так имитируется процесс рационального проектирования объектно-ориентированных систем. Выбор процесса проектирования не означает, что работа сделана. Этот процесс следует уточнять на протяжении всего жизненного цикла проекта (в идеале, после каждой итерации). Инструменты, работающие хорошо, следует оставить, а инструменты, работающие плохо, — исключить. (А затем уточнить и повторить.) Целью должен быть непрерывный процесс усовершенствования, основанный на практическом опыте. В оставшейся части главы описывается среда для разработки программного обеспечения, настроенная для создания объектно-ориентированных систем. Процесс разработки программного обеспечения имеет два аспекта — общий жизненный цикл разработки программного обеспечения (макропроцесс), а также анализ и проектирование (микропроцесс). Обсуждение макропроцесса образует контекст
Глава 6. Процесс 289 Таблица 6.1. Характеристики ускоренных и планомерных проектов Ускоренный Планомерный • Проект небольшой (над ним работают 5-10 человек*) • Над проектом работают опытные разработчики с глубокими знаниями и большим опытом. • Команда разработчиков состоит из самостоятельных и независимых лидеров. • Проект является внутренним, а команда разработчиков состоит из штатных сотрудников. • Новая система порождает много неопределенностей. • Требования изобретаются заново. • Как требования, так и окружающая среда носят переменный характер. • Среда, в которой работают конечные пользователи, отличается изменчивостью. • Отношения с заказчиком носят характер плотного сотрудничества. • Заказчик доступен, охотно сотрудничает и расположен в том же месте. • Члены команды проектировщиков, разные команды проектировщиков и заказчик доверяют друг другу. • Требуется скорость исполнения и высокая ответственность. • Это большой проект (задействовано более 10 человек) • Над проектом работают разработчики, имеющие разную подготовку. • Члены команды находятся в географически удаленных друг от друга местах и/или являются сторонними подрядчиками. • Проект имеет стратегическое значение (например, является промышленной инициативой), а разработчики работают в разных организациях. • Система не представляет труда для понимания и обладает множеством знакомых свойств. • Требования стабильны, мало подвержены изменениям и формулируются заранее. • Система крупная и сложная. Основные требования сводятся к безопасности или высокой надежности. • Организаторы проекта слабо связаны с командой разработчиков. • Отношения между заказчиком и проектировщиками носят юридический характер (например, заключаются контракты, принимаются обязательства, предусматривается формальная сертификация в соответствии с конкретными промышленными стандартами). • Акцент делается на высококачественном выполнении объекта. • Важную роль играет формализация и управление проектом. • Большое значение имеет предсказуемость и устойчивость процесса проектирования. * Как определить количество специалистов, необходимое для ускоренного проектирования, обсуждается в работе Бёма (Boehm) и Тернера (Turner) [16].
290 Часть П. Метод для микропроцесса, который является истинным предметом изучения в данной главе. Основным вопросом, связанным с определением макро- и микропроцессов, является строгое разграничение этих понятий. Макропроцесс связан с общим жизненным циклом разработки программного обеспечения, а микропроцесс — с конкретными методами анализа и проектирования, т.е. методами, которые удовлетворяют требованиям заказчика. Выбор стиля для описания жизненного цикла (например, водопад, итеративный, ускоренный, планомерный и т.д.) относится к макропроцессу, а выбор методов анализа и проектирования (например, структурные, объектно-ориентированные и т.д.) — к микроанализу. Таким образом, независимо от того, какой стиль проектирования выбран — ускоренный или планомерный, — методы и правила объектно-ориентированного анализа и проектирования, описанные в разделе, посвященном микропроцессу, можно применять в любом случае. 6.2 Макропроцесс: жизненный цикл разработки программного обеспечения Макропроцесс представляет собой жизненный цикл разработки программного обеспечения и является контролирующим по отношению к микропроцессу. Макропроцесс описывает действия команды разработчиков и позволяет им правильно оценивать риск и вносить заблаговременные изменения в микропроцесс, чтобы сосредоточиться на коллективном анализе и проектировании. Как уже отмечалось, существует шкала стилей макропроцесса — от водопада до итеративного, от ускоренного до планомерного. Выбор правильного стиля зависит от масштаба и формы макропроцесса (например, определение и количество этапов, рекомендуемая продолжительность итераций, среднее количество итераций и т.д.). В разделе приводится пример планомерного макропроцесса, обладающего двумя свойствами, описанными в начале главы: строгая архитектурная концепция и итеративный характер жизненного цикла. Данный макропроцесс относится к стилю RUP [27]. Этот стиль будет использован в качестве эталона для сравнения с другими стилями. Подробное сравнение жизненных циклов разработки программного обеспечения и различных методов ускоренного проектирования проведено в работе Лармана (Larman) [24].
Глава 6. Процесс 291 Обзор Макропроцесс предназначен для руководства проектированием системы в целом, вплоть до ее реализации. Сфера макропроцесса велика: от формулировки идеи до ее воплощения в первой версии программного обеспечения. Проектирование дальнейших версий, как для развития, так и для поддержки, осуществляется в рамках другого макропроцесса (другого жизненного цикла). Продолжительность и форма жизненного цикла поддерживаемой программы зависит от первоначального жизненного цикла проекта. Более подробная информация на эту тему приведена во врезке "Эволюция и поддержка программного обеспечения на этапе эксплуатации". В рамках итеративного и поступательного макропроцесса проект постепенно уточняется и совершенствуется, превращаясь, в конце концов, в производственную систему Основным результатом этого процесса является поток версий (итераций), реализующих уточнения (усовершенствования) системы. К побочным результатам относятся поведенческие прототипы 6, применяемые при исследовании альтернативных проектов, а также документация, предназначенная для регистрации проектных решений и их обоснования7. Макропроцесс проектирования программного обеспечения можно описать в двух измерениях — содержания и времени, т.е. что сделано и когда сделано. Содержание включает в себя роли, задачи и результаты работы. Содержание можно представить с помощью терминов предметной области, описывающих его логику. Время показывает аспекты жизненного цикла процесса и может быть описано с помощью контрольных точек, этапов и итераций. Содержание макропроцесса — стадии Макропроцесс состоит из следующих стадий, перечисленных в порядке их относительной важности. 1. Формулировка требований. Заключение соглашений между заказчиками и другими организаторами проекта о том, что должна делать система. Определение границ системы. 6Более подробно поведенческие прототипы описаны во врезке "Разработка прототипов в процессе проектирования программного обеспечения". 7Многие разработчики игнорируют "излишнюю документацию", поскольку не чувствуют выгоды от ее использования. Однако следует отметить, что читателями этой документации редко становятся сами проектировщики. Обычно документация предназначена для других людей (интеграторов, администраторов баз данных, менеджеров проектов, команд оперативной поддержки, операторов справочной системы и др.), а также для сотрудников, которые могут присоединиться к коллективу разработчиков в будущем. Таким образом, документацию следует создавать, только если в будущем ее будет кто-то читать. После завершения разработки документация должна уточняться вместе с системой, а не оставаться вехой на пути ее развития. Она должна быть естественным артефактом процесса, создаваемым в полуавтоматическом режиме.
292 Часть П. Метод Эволюция и поддержка программного обеспечения на этапе эксплуатации После поставки программного обеспечения заказчику (этап эксплуатации (Post- Transition)) может возникнуть необходимость внести в программу определенные изменения: реализовать новые или улучшенные свойства (эволюция) или исправить обнаруженные ошибки (поддержка). Поддержка операционной системы без нарушения ее целостности всегда представляет собой сложную задачу. Леман (Lehman) и Белади (Belady) сделали несколько убедительных наблюдений, касающихся процесса развития внедренных систем программного обеспечения. 1. Программа, используемая в реальной среде, должна непрерывно изменяться. В противном случае она будет становиться все менее и менее полезной в этой среде (закон непрерывного изменения). 2. При изменении эволюционирующей программы ее структура становится более сложной, если не прилагаются активные усилия, чтобы этого избежать (закон возрастающей сложности) [11]. Уточнение внедренной системы программного обеспечения особенно важно для ускоренных проектов. Одним из основных принципов ускоренного проектирования является "удовлетворение заказчика путем своевременной и непрерывной поставки ценного программного обеспечения" [15]. В рамках ускоренного процесса внедряемые системы постоянно перерабатываются без нарушения их существующей реализации (например, программа должна по-прежнему проходить все предыдущие тесты). Изменения во внедренную систему можно проектировать и реализовывать путем повторения исходного жизненного цикла проекта, модифицировав его продолжительность и форму (т.е. оставив только необходимые этапы и требуемое количество итераций на каждом этапе) в зависимости от выдвинутых требований. В некоторых случаях достаточно внести локальные изменения, не затрагивающие архитектурной структуры системы (они относятся только к периоду сдачи программного обеспечения (Transition phase)). В других ситуациях изменения могут затрагивать цель и функциональные свойства системы, а также ее архитектурную структуру и риски (они относятся к этапам постановки задачи (Inception phase) и разработки проекта (Elaboration phase)). В последнем случае изменения считаются более важными, а их жизненный цикл напоминает полноценный процесс проектирования. Обсуждению жизненных циклов проектов посвящена работа Крухтена (Kruchten) [22]. Результаты жизненных циклов эволюции и поддержки похожи на результаты жизненного цикла исходной версии программного обеспечения, за исключением списка требуемых изменений. К моменту выпуска системы ее разработчики и конечные пользователи уже могут иметь список желательных улучшений или модификаций, которые они хотели бы видеть в следующих версиях и которые они были не в состоянии сформулировать раньше. Кроме того, чем больше пользователей работают с системой, тем больше обнаруживается ошибок и неожиданных способов ее использования. (Пользователи проявляют большую изобретательность
Глава 6. Процесс 293 и часто демонстрируют самые неожиданные способы использования систем.) Для регистрации дефектов и ожидаемых улучшений создается список требуемых изменений, который послужит основой для будущих версий программного обеспечения. Процессы, протекающие после сдачи системы, напоминают процессы на этапе ее проектирования. Однако, кроме обычных действий, связанных с проектированием программного обеспечения, разработка последующих версий предусматривает расстановку приоритетов требуемых изменений, оценку их важности и стоимости, а также оценку объемов работы. Кроме того, многие текущие проблемы должны быть решены в течение 24 часов (и даже раньше!). Таким образом, помимо обычного механизма выпуска версий очередных необходимо обеспечить поставку "заплаток" к поставленной системе. Конфигурация и тестирование таких изменений, а также их интеграция в текущую версию может потребовать значительных усилий. 2. Анализ и проектирование. Трансформация требований в проект системы, служащий спецификацией ее реализации в выбранном окружении. Разработка архитектуры системы и создание общих механизмов, используемых элементами системы. 3. Реализация. Воплощение, тестирование и интеграция проекта в виде исполняемой системы. 4. Тестирование. Проверка реализации, чтобы убедиться в выполнении требований (т.е. в том, что система удовлетворяет заказчика). Оценка системы путем демонстрации ее функций. 5. Развертывание. Поставка программного обеспечения (включая протестированную реализацию) конечным пользователям. В ходе жизненного цикла проекта осуществляются следующие действия. • Управление проектом. Методы управления проектом, включая планирование, подбор кадров и мониторинг, а также управление рисками. • Управление конфигурацией и изменениями. Идентификация элементов конфигурации, контроль их изменений и управление конфигурациями этих элементов. • Поддержка среды. Обеспечение среды функционирования программного обеспечения, включая процессы и средства поддержки проектирования. Относительный порядок и итеративная природа стадий макропроцесса показаны на рис. 6.1. Следует подчеркнуть, что несмотря на последовательный характер стадий (формулировка требований, анализ и проектирование, реализация и т.д.), макропроцесс не относится к "водопадным" процессам (хотя и может им быть).
294 Часть П. Метод Разработка прототипов в процессе проектирования программного обеспечения Разработка прототипов преследует несколько целей. Прежде чем перейти к обсуждению роли разработки прототипов, сначала следует дать определение прототипа, в частности, поведенческого прототипа. Поведенческий прототип исследует изолированный элемент системы, например, новый алгоритм, модель пользовательского интерфейса или схему базы данных. Его цель — быстрый анализ альтернативных проектных решений и исключение рисков на ранних стадиях проектирования, до выпуска производственных версий. По своей природе такие прототипы являются неполными, приблизительными и временными (после достижения поставленных целей они больше не используются). Первые поведенческие прототипы обычно появляются уже на ранних стадиях проектирования, когда разработчики пытаются понять, что можно сделать и какие технологии следует применить. Для совершенно новых систем создаются черновые прототипы, демонстрирующие их концептуальные особенности. Совершенно очевидно, что для очень крупных систем (например, национального масштаба) создание такого прототипа потребует больших усилий. Однако это очень желательно. Намного лучше обнаружить ошибочность предположений о функциональных свойствах, эффективности, размере или сложности системы на ранних стадиях проектирования, чем на поздних, когда отказ от текущего проекта может обернуться финансовым или социальным крахом. Кроме того, поведенческие прототипы можно использовать на протяжении всего процесса проектирования для того, чтобы глубже понять семантику поведения системы. Как правило, коллективы разработчиков используют поведенческие прототипы, для того чтобы разобраться с семантикой пользовательского интерфейса и предоставить его пользователям для ознакомления, а также для того чтобы достичь компромисса между реализациями конкретных механизмов. Все парадигмы программирования должны поддерживать разработку средств проверки понятий (proof-of-concept), чтобы помочь проектировщикам лучше понять идею и исключить риск. Однако часто оказывается, что даже при наличии достаточно глубоко разработанной объектно-ориентированной среды, прототипы позволяют быстрее решить задачу, чем любая другая альтернатива. Иногда средства проверки понятий разрабатываются на одном языке (например, на языке Smalltalk), а конечный продукт производится на другом (например, на языке Java). Нельзя допускать, чтобы прототипы становились непосредственной основой для производства системы, за исключением ситуаций, когда это не диктуется абсолютной необходимостью. Удобство не относится к таким уважительным причинам: экономия в этом случае является ложной, поскольку затраты на краткосрочное производство уменьшаются, но стоимость обладания программным обеспечением увеличивается. При разработке прототипов важно установить ясные критерии успеха и предназначение каждого прототипа. По завершении разработки необходимо решить, как внедрять прототипы в текущие или последующие выпуски программного обеспечения.
Глава 6. Процесс 295 ^-J Тпрбпняния I ►Анализ И J рряпйяяййя JTeCTMpO-l—J рооврптыняние \*^ Требования проектирование Реализация вание Развертывание Управление проектом Управление конфигурацией и изменениями Среда Рис. 6.1. Стадии макропроцесса В процессах водопадного характера стадии следуют одна за другой — формулируются требования, осуществляется анализ и проектирование всей системы и т.д. В рамках итеративного и поступательного макропроцесса один и тот же этап может выполняться несколько раз, а объем работы на каждом этапе зависит от состояния проектирования. Этот тезис станет яснее, когда будут рассматриваться контрольные отметки и этапы проекта. Многие элементы макропроцесса относятся к управлению программным обеспечением и в одинаковой степени характерны как для объектно-ориентированных, так и для других систем. К ним относятся эмпирические приемы формирования ограничений, управления конфигурацией, тестирования и гарантии качества работ, разработки кода и создания документации. Рассмотрев содержание макропроцесса, перейдем к анализу его временных координат, которые можно выразить с помощью контрольных отметок, этапов и итераций. Временные координаты макропроцесса — контрольные точки и этапы В итеративном и поступательном макропроцессе все этапы могут повторяться. Однако итеративный процесс проектирования представляет собой нечто большее, чем простой поток итераций. Должна существовать среда, в которой выполняются итерации, т.е. стратегический план проекта, а также цели и предназначение каждой итерации. Эту среду можно воплотить в виде ряда точно определенных контрольных отметок, в котором каждая отметка достигается путем выполнения одной или нескольких итераций8. По прохождении контрольной отметки разработчик должен понять, достигнута ли поставленная цель. Если это так, разработку системы можно продолжать и переходить на следующий этап. Контрольные отметки гарантируют, что итерации ведут к нужному решению, а не уходят в бесконечность. Их следует интерпретировать не как даты кален- 8"Водопадный" процесс также имеет контрольные отметки, но они представляют собой моменты завершения этапов в ходе разработки всей системы (например, окончательная формулировка требований, завершение анализа и проектирования и т.д.).
296 Часть П. Метод дарного плана, а как достижение определенного качества или зрелости проекта. Иначе говоря, достижение контрольной точки означает, что проект вышел на определенный уровень зрелости и понимания уточняющихся планов, спецификаций и завершенных решений. Если запланированные даты прошли, но проект не достиг установленного уровня зрелости и понимания, то контрольные даты следует перенести — можно изменять даты, но не критерии. На рис. 6.2 показано, как контрольные отметки и итерации согласуются друг с другом в рамках итеративного и последовательного процесса, а также как располагаются контрольные отметки на оси времени. Рассмотрим каждый из этих этапов более подробно. Начало В этом подразделе описываются цель, действия, результаты и контрольные отметки начального этапа проекта. Цель. Предназначение начального этапа — гарантировать, что проект окажется полезным и реальным (т.е. будет обладать ценностью как с предметной, так и с деловой точки зрения). Для каждой принципиально новой части программного обеспечения или даже для новой адаптации существующей системы в определенный момент времени в голову разработчика, архитектора, аналитика или конечного пользователя может прийти идея о каком-либо приложении. Это может быть новое деловое предприятие, дополнительное изделие на производственной линии или, например, новые функции существующей программной системы. На начальном этапе не обязательно доводить эту идею до конца. Скорее, цель этого этапа заключается в том, чтобы сформулировать взгляд на нее и оценить предпосылки для ее реализации. Даже при усовершенствовании существующей системы значимость начального этапа не снижается. В этом случае он сокращается, но по-прежнему в центре внимания остается деловая ценность и техническая осуществимость проекта. Виды деятельности. На начальном этапе необходимо выяснить основные требования к системе, установить их приоритеты, согласовать с заказчиком предмет разработки, осознать главные риски, угрожающие процессу конструирования системы, и сформировать среду разработки (т.е. определить процесс и инструменты). Принципы выбора оптимального процесса проектирования уже были рассмотрены. Начальный период разработки — это время принятия решения, уточнения процесса и выбора инструментов. Таким образом, на этом этапе нет ничего сугубо объектно-ориентированного. Результаты. Первичными результатами начального периода являются концепция системы, поведенческие прототипы, первоначальный список рисков, архитектурные компоненты и среда разработки. Концепция системы позволяет ясно описать,
i 2? CO > CD ί- ϋ s ϋ α ω со СО а *έ со о «- S ^ s 2 I ω α. CD с 2 ω .-ίο 5 £ 2- 2 = 5 и О О * 2 с CD S X СО Ш О Q. S >» Q. κ- ο χ s 1 £ со о 2 δ а з ΩΟ Χ ε] + 1 a \i cd о о & о 03 а7 0Q Л I S Си
298 Часть П. Метод что именно будет сконструировано в результате выполнения проекта, включая масштаб, основные характеристики, влияние на существующие системы и взаимодействие с ними, а также сформулировать ограничения на систему. Прототипы служат доказательством, что систему можно сконструировать в принципе. В списке рисков перечисляются основные факторы, которых следует избегать еще на ранних этапах жизненного цикла, чтобы увеличить вероятность успеха. Архитектурные конструкции определяют общие свойства системы, поддерживающие ее функциональность (например, парадигмы пользовательского интерфейса, средства выявления и обработки ошибок, способы поддержки персистентности, принципы управления памятью, параметры взаимосвязи между процессами, особенности управления транзакциями и обеспечения безопасности и т.д.). К среде разработки относятся процесс и инструменты проектирования. Контрольная отметка: масштаб определен. Начальный период можно считать успешно завершенным, если разработчики ясно понимают, что именно они проектируют (т.е. представляют себе масштаб и основные требования к системе), правильно оценивают относительные приоритеты ограничений и осознают убедительные причины для разработки этой системы. Кроме того, необходимо, чтобы проектировщики и заказчик согласовали масштаб системы и сроки ее сдачи в эксплуатацию. Разработка проекта В этом разделе рассматриваются цель, виды деятельности, результаты и контрольные отметки этапа разработки проекта. Цель. Как только масштаб системы определен и согласован, внимание разработчиков переключается на проектирование архитектурных конструкций, которые лягут в основу последующих итераций. Цель этапа — заранее идентифицировать дефекты архитектурных конструкций и выявить общие стратегии, упрощающие архитектуру. На этапе разработки проекта разработчики выбирают архитектуру системы и уточняют ее с помощью многочисленных итераций. Эта эволюция позволяет устранить наиболее серьезные риски и удовлетворить требования, имеющие самый высокий приоритет и архитектурную важность. Виды деятельности. На этапе разработки проекта принимаются архитектурные решения, а также определяется, реализуется, тестируется и уточняется архитектурная основа системы. Эволюция архитектуры в основном выражается в попытках удовлетворить многочисленные конкурирующие требования, касающиеся функциональных свойств, скорости работы и объема памяти — каждое из этих требований ограничивает другое. Например, если вес компьютера является критически важным фактором (как это бывает при проектировании космических кораблей), то следует учитывать вес каждого чипа памяти. В свою очередь совокупный вес чипов ограничивает размер программы, которую можно загрузить
Глава 6. Процесс 299 в такую память. Ослабив одно из ограничений, можно реализовать другую проектную альтернативу, а ужесточив требования, можно сделать проект нереализуемым. Эволюционный подход к проектированию, в отличие от монолитного, позволяет определить, какие ограничения являются наиболее важными, а какими можно пренебречь. В начале этапа разработки проектировщики, как правило, недостаточно хорошо представляют себе узкие места будущей системы. Создавая основные архитектурные элементы и измеряя результаты с помощью тестирования, коллектив проектировщиков может уточнять архитектуру с течением времени. Результаты. На этапе разработки проекта архитектура системы оценивается с помощью ряда вариантов, частично соответствующих семантике основных сценариев поведения конечных пользователей (сценариев, влияющих на выбор архитектуры). К ним относятся сценарии, предназначенные для реализации и тестирования основных элементов системы, способов взаимодействия между ними, а также для исследования рисков. Эти варианты представляют собой вертикальные срезы всей архитектуры и отражают основные (но не все) особенности семантики всех важных элементов системы. Таким образом, к результатам этапа разработки проекта относятся не только архитектурная документация, но и варианты системы, в которых эта архитектура реализована. Для того чтобы архитектуру можно было оценить, изучить и уточнить, эти варианты программного обеспечения должны быть исполнимыми. Контрольная отметка: архитектура стала устойчивой. Этап разработки проекта считается успешно завершенным, если проектировщики убедились (после проведенного реального тестирования и формального анализа), что архитектура системы соответствует всем основным требованиям, как функциональным, так и нефункциональным, а также в том, что все риски устранены, т.е. стоимость и график создания системы являются вполне предсказуемыми. Основным признаком устойчивости архитектуры (и успешного завершения проекта разработки) является слабая изменчивость архитектурных интерфейсов и механизмов или их постоянство [10]. Со временем изменчивость программного обеспечения должна снижаться. Слишком частые изменения архитектурных элементов системы свидетельствуют об определенных архитектурных проблемах, которые следует отнести к рискам. В этом случае этап разработки проекта следует продолжить. Конструирование В этом подразделе рассматриваются цель, виды деятельности, результаты и контрольные отметки этапа конструирования. Цель. Как только архитектура стабилизировалась, внимание переключается на анализ проблемы и идентификацию основных элементов решения, касающегося проектирования системы. Этап конструирования представляет собой переход
300 Часть П. Метод от исследования к производству, причем производством считается "управляемый методологический процесс повышения качества продукции до требуемого уровня" [8]. Виды деятельности. Этап конструирования завершает проектирование системы на основе архитектурных решений, принятых на этапе разработки проекта. Результаты. Этап конструирования состоит из многочисленных итераций, в ходе которых создается ряд вариантов системы, соответствующих семантике оставшихся сценариев поведения конечных пользователей. Эти варианты измеряются, изучаются и точно оцениваются по мере постепенного увеличения масштаба проекта и перехода к производству системы. Контрольная отметка: система готова к эксплуатационному тестированию. Этап конструирования считается успешно завершенным, если функциональные свойства и качество выпусков программного обеспечения достигли уровня, достаточного для развертывания на компьютерах конечных пользователей с целью эксплуатационного тестирования. Основными критериями качества программного обеспечения на этом этапе является степень их соответствия основным ограничениям, а также качество промежуточных выпусков. Важным индикатором качества на данном этапе является скорость выявления ошибок (defect-discovery rate) [9]. Инвестиции, вложенные в обеспечение качества на ранних этапах проектирования, позволяют установить определенные критерии качества для каждого промежуточного выпуска, которыми должны руководствоваться менеджеры при идентификации рисков и оценке эффективности работы команды проектировщиков. После появления очередного выпуска скорость выявления ошибок, как правило, возрастает. С одной стороны, постоянная скорость выявления ошибок обычно свидетельствует о нераспознанных дефектах. С другой стороны, чрезмерно высокая скорость выявления ошибок свидетельствует о нестабильности архитектуры либо о неправильном проектировании или реализации новых элементов. В обоих этих случаях система не готова к тестированию, выполняемому конечными пользователями, и этап конструирования следует продолжить. Передача в эксплуатацию В этом подразделе рассматриваются цель, виды деятельности, результаты и контрольные отметки этапа передачи программного продукта в эксплуатацию. Цель. Этап передачи в эксплуатацию наступает, когда проектировщики убеждаются в том, что программное обеспечение удовлетворяет требованиям конечных пользователей. Виды деятельности. На этапе передачи в эксплуатацию программное обеспечение передается пользователям для оценки и тестирования (например, альфа-
Глава 6. Процесс 301 тестирование, бета-тестирование и т.д.). После этого коллектив проектировщиков рассматривает сообщения, поступившие от пользователей. Цель данного этапа — точная настройка программного обеспечения, решение вопросов, связанных с конфигурацией, инсталляцией и удобством использования, а также устранение ошибок, выявленных первыми пользователями. Окончательный проект сопровождается документацией и обучающими материалами. Кроме того, на этом этапе решаются все вопросы, связанные с распространением продукции, например, упаковкой и маркетинговыми материалами. После этого окончательный вариант программного обеспечения подвергается приемочным испытаниям. Следует подчеркнуть, что несмотря на то что тестирование продолжается на всем протяжении жизненного цикла программного обеспечения, эксплуатационное тестирование и приемочные испытания тем не менее обладают большой важностью, поскольку они гарантируют, что разработанное программное обеспечение удовлетворяет выдвигаемым требованиям. Результаты. К результатам этапа передачи в эксплуатацию относятся упакованная продукция, сопровождающая документация, а также обучающие и маркетинговые материалы. Контрольная отметка: система готова к развертыванию. Этап передачи в эксплуатацию считается успешно завершенным, если функциональные свойства и качество выпусков соответствуют готовности продукции (т.е. система прошла приемочные испытания). Основной показатель качества продукции на этапе передачи в эксплуатацию — уменьшающаяся скорость обнаружения новых ошибок — аналогичен показателю качества, который используется на этапе конструирования. Однако на этом этапе источниками сообщений о дефектах являются первые приемщики продукции. 1. Выработка концепции, оценка реальности и определение масштаба системы. 2. Выпуск и планирование итераций. 3. Реализация и тестирование. 4. Производство и развертывание. Теперь, рассмотрев примеры этапов и контрольных отметок макропроцесса, перейдем к анализу итераций, осуществляемых на каждом этапе. Временной аспект макропроцесса — итерации Как показано на рис. 6.3, в итеративном макропроцессе итерации могут охватывать несколько стадий. Однако относительное время, затрачиваемое на эти действия, зависит от того, на какой стадии макропроцесса они выполняются. Если итерация выполняется на начальном этапе проектирования, то анализ требований
302 Часть П. Метод Этапы быстрого проектирования Методы быстрого проектирования также состоят из этапов. Перечислим основные из них [24]. Жизненный цикл ХР состоит из пяти этапов. 1. Исследование. На этом этапе выявляется реальность проекта, основные сценарии для первого выпуска и разработка опытных прототипов. 2. Планирование. Согласование дат и сценариев для первого выпуска. 3. Итерации. Реализация и тестирование избранных сценариев в ходе ряда итераций. Уточнение плана итераций. 4. Производство. Подготовка сопроводительных материалов (документация, обучение, маркетинг) и развертывание действующей системы. 5. Сопровождение. Исправление ошибок и модернизация развернутой системы. Жизненный цикл SCRUM состоит из четырех этапов. 1. Планирование. Формулировка концепции, выявление ожиданий пользователей, обеспечение надежного финансирования и разработка опытных образцов. 2. Подготовка производства. Расстановка приоритетов и составление плана для первой итерации. Разработка опытных прототипов. 3. Разработка. Удовлетворение требований в ходе серии попыток и уточнение плана итераций. 4. Выпуск. Подготовка сопровождающих вариантов (документации, а также обучающих и маркетинговых материалов) и развертывание действующей системы. Таким образом, этапы проектирования, предусмотренные методами планомерного (plan-driven) и быстрого проектирования, практически совпадают. В частности, все методы, описанные выше, включают в себя следующие этапы. займет наибольшее количество времени. Если же итерация выполняется на этапе разработки проекта, то больше времени понадобится потратить на анализ и проектирование (в частности, на разработку архитектуры). Если итерация выполняется на этапе конструирования, то основное время будет затрачено на реализацию и тестирование и т.д. Разумеется, некоторые виды деятельности, такие как управление конфигурацией и изменениями, среда разработки и управление проектом, выполняются на всем протяжении жизненного цикла программного обеспечения. На рис. 6.3 показано, как перемещается центр внимания в ходе последовательных итераций. Размер прямоугольников на каждой стадии иллюстрирует относительное время, затраченное на выполнение этого вида деятельности. Изменение
Глава 6. Процесс 303 Итерация 1 Требования Итерация 2 Требования Итерация 3 BL Анализ и проектирование Реализация Тестирование Развертывание Анализ и проектирование Реализация Тестирование Развертывание Требования Анализ и Реализация Тестирование Развертывание проектирование Рис. 6.3. Перемещение центра внимания в ходе итераций содержания анализа и проектирования на протяжении жизненного цикла обсуждается во врезке "Анализ, проектирование и итеративная разработка". В конце каждой итерации состояние разрабатываемой системы обсуждается в коллективе проектировщиков. Итерацию следует рассматривать как возможность уточнить проект как с функциональной точки зрения, так и улучшения среды разработки. Концепция итерации используется практически во всех методах разработки программного обеспечения. Они отличаются лишь рекомендуемой продолжительностью работ на каждой итерации [24]. • Метод ХР рекомендует, чтобы итерации по возможности продолжались от одной до двух недель. • Метод SCRUM предусматривает, что все итерации (попытки) должны продолжаться 30 дней. • Метод RUP рекомендует, чтобы итерации продолжались от двух до шести недель. Как уже отмечалось, в ходе макропроцесса осуществляются последовательные выпуски промежуточных вариантов программного обеспечения. Таким образом, раздел, посвященный макропроцессу, целесообразно завершить обсуждением методов планирования выпусков.
304 Часть П. Метод Анализ, проектирование и итеративная разработка Содержание анализа и проектирования на протяжении жизненного цикла программного обеспечения изменяется. Наиболее широко анализ применяется на ранних этапах проектирования (начальном этапе и этапе разработки проекта), в центре внимания которых находится архитектура системы. На этих этапах разработчики занимаются анализом требований, влияющих на выбор архитектурных компонентов. На более поздних этапах, когда реализация системы уже завершается, анализ относится лишь к немногим оставшимся требованиям, но уже не носит такой интенсивный характер, поскольку большинство основных элементов системы уже выявлено. Время, затрачиваемое на анализ на поздних стадиях проектирования, уменьшается, поскольку большинство требований уже рассмотрено и фокус внимания перемещается на реализацию. Однако даже на поздних этапах может понадобиться провести минимальный анализ, если в результате обратной связи с пользователями возникнет необходимость внести изменения в систему, хотя это и маловероятно. Как и содержание анализа, предмет проектирования на протяжении жизненного цикла программного обеспечения изменяется. Проектирование может начинаться на ранних этапах, когда выясняется масштаб системы, если разработчик, например, планирует, что решение будет основано на элементах уже существующей системы. При выборе архитектурных элементов работы, связанные с проектированием, расширяются. По мере перехода к более поздним этапам интенсивность проектирования затухает, поскольку фокус внимания переносится на периферические элементы и сопровождение программного обеспечения. Планирование выпусков Планируя выпуски, необходимо определить, что они собой представляют и что содержат. Цель планирования выпусков — идентифицировать серию последовательных выпусков с постепенно увеличивающейся функциональностью, которые в конце концов должны удовлетворить всем требованиям, предъявляемым к завершенной системе. Исходными данными для планирования выпусков являются масштаб разрабатываемой системы и все ограничивающие факторы (например, стоимость, время, качество). Деятельность, выполняемая в ходе планирования выпусков, включает в себя определение ритма проектирования, расстановку ограничений по приоритетам, распределение требований по итерациям, разделение выпуском на внутренние и внешние и, в завершение, разработку детального плана итераций. Результатом планирования выпусков является план разработки, в котором указана последовательность выпусков, работа команды проектировщиков и оценка рисков. Рассмотрим теперь каждый из этих видов деятельности более подробно. Первый этап планирования выпусков включает в себя определение ритма проектирования — определение средней продолжительности итераций (т.е. интерва-
Глава 6. Процесс 305 лов времени между выпусками). Продолжительность итераций является важным фактором. Даты выпусков должны быть установлены так, чтобы коллектив проектировщиков имел достаточно времени для работы и синхронизации выпусков с другими видами деятельности, например, с разработкой документации и эксплуатационными испытаниями. Для небольших проектов, разработка которых занимает от полугода до года, интервал между выпусками обычно составляет от двух до шести недель. Для проектов среднего размера, продолжительность разработки которых колеблется от года до полутора лет, интервал между выпусками может достигать от двух до трех месяцев. В более сложных проектах, связанных со значительным объемом работ, между выпусками может проходить шесть месяцев и более. Более растянутые периоды между выпусками выглядят подозрительно, поскольку они не согласованы с микропроцессом и могут скрывать вольно или невольно проигнорированные риски. Зная предполагаемую продолжительность итераций, следует упорядочить требования, предъявляемые к системе, по приоритетам. Эти приоритеты влияют на распределение требований по итерациям. Приоритеты требований зависят от количества факторов. К числу этих факторов относятся следующие. • Интересы организаторов проекта (например, насколько важным является требование для конечного пользователя или насколько важно продемонстрировать существенную часть функциональных возможностей системы потенциальному спонсору). • Архитектурное значение и масштаб (например, касается ли требование основных архитектурных аспектов, таких как доступа к базам данных, интеграции с существующими системами и т.д.). • Риски, устраняемые путем удовлетворения требования (например, предусматривает ли требование доступ к внешней системе, интерфейс которой не вполне понятен). В зависимости от этапа жизненного цикла каждый из этих факторов может иметь разный вес. Например, требование, имеющее высокий приоритет на этапе разработки проекта, отличается от требования, имеющего высокий приоритет на этапе конструирования (на этапе разработки архитектура имеет большую важность). Следует подчеркнуть, что приоритеты требований не устанавливаются раз и навсегда. Они изменяются на каждой итерации и уточняются по мере необходимости в зависимости от текущего статуса проекта, новых требований, выявления новых рисков или смягчения существующих рисков. Из-за влияния многочисленных факторов определение приоритетов требований лучше поручить команде, в которую входят представитель заказчика, эксперт в предметной области, аналитик, архитектор и персонал, контролирующий качество продукта.
306 Часть П. Метод После определения приоритетов требования распределяются по выпускам, причем требования с наиболее высоким приоритетом относятся к более ранним итерациям. Каждая итерация должна иметь предусмотренную характеристику, которую можно продемонстрировать, а также критерий оценки успеха. Содержание выпуска определяется масштабом итерации, который, в свою очередь, зависит от этапа жизненного цикла. Каждая итерация завершается выпуском, который может быть внутренним или внешним. Окончательный выпуск является внешним и представляет собой завершенную систему. Определение внешнего или внутреннего характера выпуска зависит от места итерации в жизненном цикле программного обеспечения. На ранних этапах проектирования выпуски, как правило, предназначены для внутреннего использования.. Большинство исполняемых выпусков передается членами коллектива проектировщиков персоналу, который обеспечивает качество продукции, тестирует выпуски в рамках установленных сценариев и собирает информацию о полноте, правильности и надежности программ. Эти данные позволяют выяснить проблемы уже на ранних этапах с тем, чтобы решить их в последующих выпусках. На дальнейших этапах выпуски обычно являются внешними и предназначены для конечных пользователей (альфа- и бета-пользователей) для работы в контролируемом режиме. Слово "контролируемый" означает, что коллектив проектировщиков тщательно составляет набор ожидаемых свойств для каждого выпуска и определяет аспекты, которые необходимо оценить. В целом, большинство выпусков являются внутренними и лишь несколько — внешними. Внутренние выпуски представляют собой разновидность непрерывной интеграции системы и предназначены для решения проблем, возникающих в основных областях системы. Следует подчеркнуть, что создание выпуска связано с довольно большими затратами (особенно внешними). На количество выпусков и интервал времени между ними могут также влиять такие ограничивающие факторы, как время, качество и масштаб системы. В таких ситуациях качество можно использовать как цель, достигаемую при фиксированных затратах денег, времени и масштабе. Это особенно важно при выполнении контрактов с фиксированной ценой. Последний вид деятельности, связанный с планированием выпусков, — разработка подробных планов итераций. Планируя итерации, необходимо составить подробный план проекта, разрабатываемого в рамках текущей итерации, и определить ресурсы, необходимые для выпуска. В отличие от общего плана выпусков (определенного заранее, содержащего контрольные отметки, предполагаемое количество итераций, и основанного на глубоком понимании содержания проекта), подробные планы итераций разрабатываются только тогда, когда начинается очередная итерация. Это позволяет менеджеру проекта вносить необходимые уточнения в план. "Неоправданная точность — в требованиях или планах — важный, хотя и незаметный фактор, препятствующий достижению успеха. Чаще всего слишком
Глава 6. Процесс 307 высокая точность на ранних этапах проекта носит мошеннический характер и демонстрирует желаемый прогресс и качество" [27]. В ходе итеративного проектирования планирование выпусков является постоянным и ориентированным на риски. После каждой итерации план следует пересмотреть и уточнить по мере необходимости. Часто это связано с пересмотром приоритетов, небольшими корректировками дат и переносом функциональных свойств с одной итерации на другую. На протяжении жизненного цикла проекта проводятся периодические оценки риска и план проектирования уточняется, чтобы смягчить или исключить самые серьезные риски. Это позволяет команде проектировщиков управлять будущими стратегическими и тактическими компромиссами. Выявление рисков на ранних этапах проектирования намного облегчает последующие архитектурные компромиссы. 63 Микропроцесс: анализ и проектирование В предыдущем разделе рассмотрен общий процесс разработки программного обеспечения (макропроцесс). В данном разделе описывается процесс анализа и проектирования (микропроцесс). Обзор Как показано на рис. 6.4, процесс анализа и проектирования выполняется в рамках общего процесса разработки программного обеспечения. Макропроцесс определяет масштаб микропроцесса, а также предоставляет ему входную информацию и обрабатывает результаты. В частности, микропроцесс принимает требования, сформулированные в рамках макропроцесса (а также спецификации анализа и проектирования, полученные на предыдущих итерациях микропроцесса) и создает спецификации проектирования (особенно архитектурные), которые реализуются, проверяются и разворачиваются в рамках макропроцесса. Требования Реализация | J Тести- I Л ^^ рование Развертывание Управление проектом Управление конфигурацией и изменениями Среда Рис. 6.4. Микропроцесс внутри макропроцесса
308 Часть П. Метод Макропроцесс описывается в двух измерениях: времени и содержания. Микропроцесс также можно описать в двух измерения: уровней абстракции и содержания (виды деятельности и результаты). После этого будет показано, как уровни абстракции влияют на эти виды деятельности и результаты. Уровни абстракции В микропроцессе традиционные этапы анализа и проектирования преднамеренно сделаны расплывчатыми и непрерывно выполняются на равных уровнях абстракции. На вход процесса анализа поступают требования к системе, а на выходе создается начальное решение. Результаты анализа поступают на вход процесса проектирования, в результате которого возникает спецификация, допускающая эффективную реализацию. Анализ считается завершенным, если он точно отражает требования к системе, непротиворечив и создает надежную основу для проектирования. Проектирование считается завершенным, если оно является достаточно подробным для реализации и тестирования. Как утверждает Меллор и соавторы, "цель анализа — создать описание задачи. Это описание должно быть полным, непротиворечивым, понятным и доступным для всех заинтересованных сторон, [и] допускать проверку в реальных условиях" [7]. Иначе говоря, цель анализа — создание модели поведения системы. В центре внимания анализа находится поведение, а не форма. Анализируя требования, разработчики пытаются создать модель реальной системы, идентифицируя элементы словаря предметной области и описывая их роли, обязанности и взаимодействие. На этапе анализа неуместно заниматься вопросами, связанными с представлением или реализацией системы. Анализ должен ответить на вопрос, что делает система, а не как она это делает. На этапе анализа любое утверждение, относящееся к вопросу "как", может считаться полезным только для демонстрации поведения системы, но не может рассматриваться как проверяемое требование. Анализ должен сделать решаемую задачу более понятной. Он является чрезвычайно важной частью общего процесса разработки программного обеспечения. В случае успеха проектирование системы станет более надежным и понятным, между понятиями будут проведены четкие границы, а распределение обязанностей между элементами окажется сбалансированным. В ходе проектирования разработчики изобретают элементы, обеспечивающие поведение, соответствующее требованиям анализа. Процесс проектирования следует начинать, как только будет завершена модель поведения системы. Следует избегать преждевременного проектирования и не начинать его до завершения анализа. Не менее важно не опоздать с проектированием и не пытаться создать идеальную модель анализа (это явление называется аналитическим параличом). На этапе анализа не стоит ожидать исчерпывающего понимания поведения системы. Действительно, не следует откладывать проектирование до тех пор, пока
Глава 6. Процесс 309 анализ не приведет к полному описанию системы. Само конструирование системы поднимает вопросы, касающиеся поведения системы, которые невозможно полностью осветить на этапе анализа. По этой причине на этапе анализа достаточно лишь описать все основные аспекты поведения системы и некоторые второстепенные факторы, для того чтобы убедиться, что все важные особенности поведения системы учтены. Поскольку архитектура играет важную роль в решении поставленной задачи, необходимо различать архитектуру и отдельные компоненты, проектируемые на этапе анализа и проектирования. Архитектура в основном имеет дело с отношениями между частями системы (например, компонентами), их обязанностями, интерфейсами и взаимодействием. Анализ и проектирование элементов систем сосредоточивают внимание на внутреннем устройстве этих компонентов и способах, с помощью которых они удовлетворяют требованиям, сформулированным на этапе анализа и проектирования архитектуры. Эти аспекты анализа и проектирования архитектуры и ее компонентов отражены на рис. 6.5. Стадия: Анализ Предмет: Архитектура Компонент Проектирование Цель: создать начальную архитектурную основу для архитектурного проектирования Цель: уточнить архитектуру на этапе архитектурного анализа, идентифицировав основные элементы системы, включая общие механизмы Цель: понять текущие требования, создать начальную версию системы, распределив конструктивные требования среди элементов системы Цель: уточнить элементы конструкции и создать ι спецификацию, допускающую эффективную реализацию с помощью специальных технологий Рис. 6.5. Разные аспекты анализа и проектирования, зависящие от выбранной точки зрения Архитектура описывает структуру и существо системы. Таким образом, архитектурные вопросы носят стратегический характер, а анализ и проектирование отдельных компонент — тактический. Выбор предмета для анализа и проектирования зависит от того, какие вопросы решает разработчик — связанные с архитектурой или с отдельными компонентами.
310 Часть П. Метод На протяжении всего жизненного цикла программного обеспечения анализ и проектирование выполняются на разных уровнях абстракции. Количество этих уровней заранее не определено. Оно зависит в основном от размера системы. Фактически со временем может выясниться, что, например, анализируемый компонент слишком велик. В этом случае можно сделать шаг назад и совершить еще один круг архитектурного анализа, разделив крупный компонент на более мелкие элементы, допускающие более эффективное управление и анализ. Рассмотрим теперь виды деятельности, связанной с микропроцессом, а также его результаты. Виды деятельности Микропроцесс состоит из следующих видов деятельности, имеющих определенный масштаб и уровень абстракции. • Идентификация элементов9. Выявление (или изобретение) элементов системы. Проведение объектно-ориентированной декомпозиции. • Определение взаимодействий между элементами. Описание взаимодействия идентифицированных элементов, удовлетворяющих требованиям системы. • Определение отношений между элементами. Определение отношений между взаимодействующими элементами. • Определение семантики элементов. Определение поведения и атрибутов идентифицируемых элементов. Подготовка элементов для следующего уровня абстракции. Эти виды деятельности в рамках микропроцесса показаны на рис. 6.6. Идентификация элементов Определение взаимодействия между элементами Рис. 6.6. Виды деятельности в рамках микропроцесса 9На протяжении главы термин элемент относится к сущностям, с которыми проектировщик работает на текущем уровне абстракции. Таким образом, элементом может быть класс анализа, компонент, класс проектирования и т.д. Более подробная информация об элементах, идентифицируемых на этапе анализа и проектирования, приведена в табл. 6.2. Уточнение семантики if ВиДы элементов J 4деятельности у в рамках микропро Определение \ V Ц?сса отношений между элементами
Глава 6. Процесс 311 Несмотря на то что на рисунке эти виды деятельности показаны в последовательном порядке, на практике они выполняются параллельно. Например, проектировщик может идентифицировать элементы и определять способы их взаимодействия одновременно. Кроме того, можно идентифицировать поведение и атрибуты, одновременно определяя способы взаимодействия между элементами. Способность к параллельному выполнению разных заданий вырабатывается с опытом. Микропроцесс можно представить как последовательность выполнения разных видов деятельности в разном масштабе. Однако, приобретя достаточно большой опыт, можно уменьшить количество этих проходов. Виды деятельности, связанные с микропроцессом, будут рассмотрены далее, а пока опишем его результаты. Результаты Как и следовало ожидать, основные результаты микропроцесса отражают разные аспекты анализа и проектирования. • Описание архитектуры (architecture description) системы включает в себя описание общих механизмов. Это описание содержит аспекты модели анализа/проектирования, важные с архитектурной точки зрения. • Модель анализа/проектирования (analysis/design model) содержит элементы анализа и проектирования программного обеспечения, а также описание того, как эти элементы обеспечивают требуемое поведение системы. Выбор уровня детализации при описании архитектуры зависит от природы самой системы и типа выбранного процесса проектирования. Архитектура, описанная в документации, должна быть известна всем членам коллектива разработчиков. Кроме того, эта документация отражает архитектурную концепцию системы, важность которой обсуждается в подразделе "Ясная архитектурная концепция" раздела 6.1. Рекомендации, относящиеся к документированию архитектуры программного обеспечения, изложены во врезке "Документирование архитектуры программного обеспечения". Включение в микропроцесс модели анализа/проектирования дает значительные преимущества. Во-первых, поддержка модели анализа/проектирования позволяет установить общий и согласованный словарь, используемый на протяжении всего проекта. Модель анализа/проектирования является основным хранилищем элементов, их семантики и отношений. Со временем модель анализа/проектирования уточняется путем добавления новых элементов, исключения ненужных и консолидации похожих элементов. Таким образом, коллектив проектировщиков продолжает уточнять согласованный язык выражения своих концепций. Кроме того, центральное хранилище элементов обеспечивает не только согласованность элементов, но и позволяет эффективно просматривать все элементы проекта. Это особенно важно, когда в команду входят новые члены, которые должны быстро
312 Часть П. Метод Документирование архитектуры программного обеспечения Документирование архитектуры программного обеспечения имеет большое значение как для самих архитекторов, так и для организаторов проекта. Причем важным является не только результат документирования, но и сам процесс. Архитектура представляет собой часть проекта, которая должна быть известной всем участникам разработки, а не только коллективу проектировщиков. Архитектурную документацию читают проектировщики, занимающиеся вопросами развертывания и разработкой сети, персонал, осуществляющий поддержку программного обеспечения, операторы справочной системы и даже менеджеры проекта, но лишь некоторые из них изучают подробные описания программного обеспечения. Документация, описывающая архитектуру программного обеспечения, исчерпывающим образом излагает основные аспекты системы и гарантирует, что система удовлетворяет предъявляемым требованиям. Документирование архитектуры вынуждает проектировщиков очень тщательно рассматривать разные ее аспекты. Во врезке изложены некоторые предложения, касающиеся архитектуры и ее документирования. Как уже отмечалось, архитектура описывает набор проектных решений, правил и моделей, а также набор ограничений, характеризующих среду, в которой происходит проектирование и реализация системы. Архитектура системы имеет несколько ракурсов, поэтому этот факт следует отразить в ее описании. Как отмечалось в рекомендациях комитета IEEE 1471 [20], архитектор может изложить свою концепцию. Концепция должна содержать следующие описания. 1. Описание одной или нескольких моделей системы, а также разных ракурсов (проекций) этих моделей. 2. Описание организаторов проекта, заинтересованных в этих проекциях. 3. Задачи организаторов проекта, которые можно решить с помощью этих проекций. Архитектура программного обеспечения описывается с разных точек зрения, определяющих разные проекции. Эти проекции включают в себя артефакты проектирования, представляющие важность для архитектуры. Рассмотрим простой набор проекций, используемых при описании архитектуры программного обеспечения. Этот набор проекций впервые был предложен Кручте- ном (Kruchten) [21] и называется архитектурной моделью 4 + 1. 1. Проекция требований (так называемая проекция сценариев). Эта проекция описывает функциональные и нефункциональные требования, важные с архитектурной точки зрения. Функциональные требования, влияющие на выбор архитектуры, определяют сценарии, имеющие архитектурную важность и анализируемые на ранних этапах проектирования. Нефункциональные требования, влияющие на выбор архитектуры, содержат перечень архитектурных качеств системы (например, удобство, гибкость, производительность, размер, масштабируемость, безопасность, секретность, ясность), экономические и технологические ограничения (например, использование
Глава 6. Процесс 313 готовых программ, интеграция с существующими системами, стратегия повторного использования, требуемые инструменты, структуру коллектива разработчиков и график работ), а также юридические ограничения (например, соответствие определенным стандартам и нормативам). Эти требования наиболее сильно влияют на выбор архитектуры и архитектурных механизмов, перечисленных в логической концепции системы. 2. Логическая проекция. Эта проекция описывает элементы анализа и проектирования, важные с архитектурной точки зрения, отношения между ними, их организацию в виде компонентов, пакетов и уровней приложения, а также немногочисленные избранные реализации, иллюстрирующие взаимодействие архитектурных элементов в рамках сценариев, связанных с проекцией требований. Кроме того, логическая проекция описывает основные механизмы и модели, определяющие структуру системы. 3. Проекция реализации. Эта проекция описывает основные элементы реализации (исполняемые модули и каталоги), а также связи между ними. Эта проекция важна, поскольку структура реализации сильно влияет на параллельное проектирование, управление конфигурацией, интеграцию и тестирование. 4. Проекция процессов. Эта проекция описывает независимые потоки управления в системе и логические элементы этих потоков. 5. Проекция развертывания. Эта проекция описывает узлы системы (например, компьютеры, маршрутизаторы и виртуальные машины-контейнеры). Название 4+1 является следствием споров, касающихся архитектурной концепции. Проекцию требований следует рассматривать с архитектурной точки зрения. Она включает в себя описание требований, влияющих на выбор архитектуры, и качеств, которые должна иметь система. Таким образом, требования сильно влияют на архитектуру. Наиболее важные требования рекомендуется выявлять и отслеживать на ранних этапах проектирования. Буч (Booch), Рамбо (Rumbaugh) и Якобсон (Jacobson) считают, что каждую из архитектурных проекций можно изучать отдельно от остальных. В этом случае все участники проекта могут сосредоточиться на той проекции, которая интересует его больше [17]. Эти пять архитектурных проекций могут взаимодействовать друг с другом (например, узлы из проекции развертывания содержат элементы проекции реализации, которые, в свою очередь, относятся к физической реализации логической проекции и проекции процессов). Архитектор может свободно выбирать любое количество проекций, которое сочтет нужным для описания архитектуры программного обеспечения (например, добавить проекцию данных и проекцию опыта пользователя), а также сокращать их число. Многочисленные архитектурные концепции, как простые, так и сложные, имеют общие характеристики. Среди них наиболее известны концепция Захмана (Zach-
314 Часть П. Метод man) [12], архитектурная концепция Министерства обороны (Department of Defense Architecture Framework — DoDAF) [13] и федеральная концепция (Federal Enterprise Architecture) [14]. В некоторых случаях, в зависимости от проекта и используемого процесса, целесообразно собрать всю требуемую информацию в описании архитектуры программного обеспечения (software architecture document — SAD). Этот документ становится основным артефактом, в котором описана архитектура системы. Он содержит ссылки на все другие артефакты, относящиеся к архитектуре. Чтобы понять архитектуру системы, следует обратиться к документу SAD. Этот документ должен демонстрировать, как решены основные архитектурные задачи, поэтому его следует организовать в соответствии с архитектурными проекциями. Документ SAD должен изучаться всем коллективом разработчиков и обновляться по мере развития проекта. сориентироваться в принятых решениях. Модель анализа/проектирования также позволяет архитектору охватить проект единым взглядом, что дает возможность выделить общие свойства, которые в противном случае были бы пропущены. Как легко догадаться, использование языка UML для описания модели анализа/проектирования открывает много новых возможностей. Этот язык не только реализует принцип "лучше один раз увидеть, чем сто раз услышать", но и позволяет выявить несогласованность между элементами модели. (Описание языка UML изложено в главе 5.) Решение, касающееся того, следует ли разрабатывать модели анализа и проектирования отдельно друг от друга, зависит от разрабатываемой системы и типа выбранного процесса проектирования10. Раздельный анализ моделей может оказаться полезным, если система будет работать много десятилетий, иметь много вариантов или функционировать в разных средах, каждая из которых обуславливает отдельную архитектуру. В таких ситуациях модель анализа принимает вид абстракции (платформно-независимого представления) конкретных (платформно- зависимых) моделей проектирования. Это является основным принципом модельной архитектуры (Model Driven Architecture — MDA), выдвинутым Группой объектного управления (Object Management Group) [26]. Отдельную модель анализа можно также использовать для концептуального обзора сложной системы. Однако этой цели можно достичь и с помощью хорошо документированной архитектуры. Достижение точного согласования между моделями анализа и проектирования может оказаться очень дорогостоящим. Если вы решили разделить модели анализа и проектирования, имейте в виду, что для согласования и балансирования этих моделей понадобится выполнить дополнительную работу, стоимость которой может 10Более подробное описание процесса разработки проектирования программного обеспечения изложено в разделе "Процесс рационального проектирования".
Глава 6. Процесс 315 превысить выгоду от разделения. Наоборот, модель анализа можно рассматривать как временный артефакт, который постепенно может перерасти в модель проектирования (в таком случае модель анализа можно интерпретировать как исходную модель проектирования). Микропроцесс и уровни абстракции В микропроцессе участвуют как архитектор проекта, так и инженер, специализирующийся в конкретной предметной области. Разница между ними заключается лишь в уровне абстракции. С точки зрения архитектора, микропроцесс создает среду, в которой развивается архитектура и исследуются альтернативные схемы. С точки зрения инженера, микропроцесс — это принципы, которым подчиняются многочисленные тактические решения, принимаемые в ходе производства программного продукта и адаптации архитектуры. Детали микропроцесса зависят от предмета исследования (т.е. архитектуры или компонента (см. рис. 6.5)). Рассмотрим цели микропроцесса для каждой из описанных выше ситуаций. β В рамках архитектурного анализа (architectural analysis) содержание микропроцесса сводится к созданию первоначального варианта архитектуры, основанного на существующих архитектурных решениях или структурах, а также идентификации других конструкций, приемлемых для использования в качестве строительных блоков. К таким конструкциям относится общая структура системы, а также ее ключевые абстракции и механизмы. Проводя архитектурный анализ, целесообразно разработать абстрактное представление о каждой архитектурной концепции. Результат этого анализа используется при создании архитектурного проекта. • В ходе архитектурного проектирования (architectural design) уточняется первоначальная архитектура, разработанная в процессе архитектурного анализа. Микропроцесс сводится к уточнению архитектурных элементов, элементов проекта, а также диапазона их обязанностей и взаимодействий. На этом уровне основными элементами проекта являются ключевые строительные конструкции в масштабе всей архитектурной структуры, а также отношения, определяющие общую структуру системы. Механизмы анализа превращаются в механизмы проектирования, а влияние параллельности и распределения на архитектуру рассматривается более подробно. Важную роль играет также исследование возможности повторного использования решений, что позволяет объединить готовые элементы проекта (и их реализацию). • В ходе компонентного анализа (component analysis) центр внимания микропроцесса перемещается на идентификацию элементов анализа, их обя-
316 Часть И. Метод занности и взаимодействия. К элементам анализа относятся первые приближения компонентов системы, которые на этапе компонентного анализа используются для идентификации элементов проектирования. Важно помнить, что цель анализа, выполняемого в рамках микропроцесса, — создать концепцию компонента. Следует избегать искушения начать проектировать компоненты уже на этой стадии, поскольку необходимо учитывать проблемы, которые могут возникнуть на этапе проектирования. • На этапе проектирования компонентов (component design) уточняется схема компонентов в терминах классов проектирования, которые можно непосредственно реализовать с помощью выбранной технологии. На этапе детального проектирования продолжается уточнение классов проектирования, т.е. определяется их содержание, поведение и зависимости. Уточнение следует остановить, когда собранных деталей станет достаточно для реализации класса. Затем следует собственно реализация, представляющая собой часть макропроцесса. Может показаться, что микропроцесс представляет собой простое продвижение от высокого уровня абстракций к более низким, однако это не так. Как показано на рис. 6.4, микропроцесс начинается с анализа набора требований, сформулированных в рамках макропроцесса (например, вариантов использования, сценариев, функциональных точек, пользовательских описаний и дополнительных спецификаций)11. Затем выполняются несколько итераций микропроцесса. На вход каждой итерации поступают понятия, относящиеся к определенному уровню абстракции, а на выходе получаются их реализации на следующем уровне абстракции. В результате выполнения итераций микропроцесса создается подробная проектная реализация исходных требований, которая становится основной для реализации проекта в рамках макропроцесса. В ходе выполнения итерации микропроцесса выбор низкоуровневых элементов всегда является компромиссным и рискованным. Так, проводя архитектурный анализ в определенном масштабе, проектировщик может "углубиться" (например, выполнить проектирование компонентов) в изучение элементов, о которых еще мало известно, чтобы снизить риск, а затем вернуться к исследованию архитектуры. Рассмотрим этот пример подробнее и поясним, что имеется в виду. Представьте себе, что вы находитесь на этапе разработки проекта в рамках макропроцесса, а важные с архитектурной точки зрения требования должны быть выявлены лишь после анализа и проектирования (относящихся к микропроцессу). Возможные ситуации описаны в следующем сценарии. 11 Независимо от способа представления требований, важно, чтобы они были подробно документированы и точно описывали, что система должна делать с точки зрения пользователя, включая функциональные и нефункциональные свойства. В данной главе термин сценарий означает точку зрения пользователя на требования к системе.
Глава 6. Процесс 317 1. Проводится архитектурный анализ всех важных сценариев. В результате формируется набор элементов, имеющих значение для архитектуры системы. 2. Осуществляется архитектурное проектирование, входной информацией для которого являются все элементы, прошедшие архитектурный анализ. На этой итерации выявляются недостаточно понятные элементы проекта и проводится компонентный анализ и проектирование этих элементов. В результате на уровне архитектурного проектирования потребуется уточнение некоторых элементов. Результатом этих итераций является набор элементов, имеющих значение для архитектуры. 3. Выполняется анализ компонентов для каждого сценария, имеющего важность с архитектурной точки зрения. Входной информацией для этого анализа являются элементы архитектурного проекта. В результате этих итераций создается совокупность элементов проекта, поддерживающих изученные сценарии. 4. Выполняется проектирование компонентов для каждого элемента, имеющего архитектурную важность и прошедшего анализ компонентов. 5. Выполняются дополнительные итерации микропроцесса на более низких уровнях абстракции (например, переход от уровня предприятия на уровень системы, подсистемы, компонента, подкомпонента т.д.). Результатом этих итерация является множество подробно описанных элементов проекта, готовых для реализации в рамках макропроцесса. Отношения между макропроцессом, микропроцессом и итерациями микропроцесса описаны на рис. 6.7. Требования (от макропроцесса) Определение отношений между элементами Спецификации проекта Идентификация (макропроцессу) элементов с> Определение взаимодействия между элементами Рис. 6.7. Итерации микропроцесса На этом обсуждение микропроцесса и уровней абстракции завершается. Теперь более подробно изучим виды деятельности в рамках микропроцесса и рассмотрим, какие действия выполняются, что производится и как оценивается качество того, что производится в ходе микропроцесса.
318 Часть П. Метод Идентификация элементов Идентификация элементов — это главный вид деятельности в ходе объектно- ориентированной декомпозиции системы. Таким образом, цель этой деятельности — выявление ключевых элементов, используемых для описания решения на конкретном уровне абстракции. Слово идентификация в этом контексте является не совсем точным. На самом деле происходит переход элементов с одного уровня абстракции на следующий. Идентификация элементов на одном уровне абстракции связана с пересмотром элементов предыдущего уровня, что приводит к появлению новых элементов. Элементы, выявленные на одном уровне абстракции, затем становятся входной информацией для идентификации элементов на следующем уровне. Осуществляя идентификацию, важно соблюдать точный баланс между выявлением элементов и уточнением их семантики. Смысл этого вида деятельности заключается именно в выявлении элементов системы и их описании на высоком уровне абстракции (т.е. кратко). Семантика выявленных элементов должна постепенно уточняться в рамках микропроцесса. Результаты Результатами идентификации элементов является модель анализа/проектирования, включающая в себя выявленные элементы и их краткое описание на конкретном уровне абстракции. Элементы, идентифицируемые в ходе анализа и проектирования, перечислены в табл. 6.2. Этапы В главе 4 описаны конкретные методы классификации, используемые для идентификации объектно-ориентированных элементов (в частности, классический объектно-ориентированный анализ, анализ сценариев, CRC-карточки, неформальное описание на естественном языке и структурный анализ). Идентификация объектно-ориентированных элементов обычно связана с двумя видами деятельности: открытием и изобретением. Идентификация элементов в ходе анализа в основном связана с открытием, а в проектировании более важную роль играет изобретение. Анализируя систему, проектировщик сотрудничает с экспертами предметной области. Он должен быть способен распознавать абстракции, представлять себе задачу в контексте предметной области и находить осмысленные элементы анализа. В ходе проектирования архитекторы и проектировщики идентифицируют элементы и должны уметь разрабатывать новые элементы проекта, порожденные предметной областью. На этапе проектирования некоторые элементы, идентифицированные в ходе анализа, могут воплотиться в реальные классы, а другие — стать простыми атрибутами или другими абстракциями. Кроме того, некоторые элементы анализа, идентифицированные на предыдущих стадиях, могут оказаться ошибочными, но
Глава 6. Процесс 319 Таблица 6.2. Элементы, идентифицируемые в ходе анализа и проектирования Цель Идентифицированные Цель и комментарии элементы Архитектурный Основные абстракции · Сформировать словарь предметной об- анализ ласти Идентификация основных абстракций заранее уменьшает вероятность того, что ключевые концепции в дальнейшем станут противоречить друг другу, когда на основе отдельных требований будут выявлены элементы системы. Архитектурные части β Разделить сферы ответственности внутри системы и провести кластерный анализ элементов. • Представить логическую организацию системы на высоком уровне абстракции. Разделение системы может основываться на существующей архитектурной конструкции. В послойной архитектуре разделами являются слои. Архитектурные · Представить основные услуги, инфра- механизмы структуру и общие стратегии. Некоторые из них являются фундаментальными, т.е. не зависят от предметной области, например, методов управления памятью, выявления и обработки ошибок, поддержки персистентно- сти, обеспечения связей между процессами, управления транзакциями и гарантии безопасности. Другие относятся к предметной области, а также включают идиомы и механизмы, соответствующие этой области, например, стратегии управления в системах реального времени, а также транзакции и методы управления базами данных в информационных системах. Механизмы анализа описываются абстрактно, независимо от конкретных методов реализации.
320 Часть П. Метод Окончание табл. 6.2 Цель Идентифицированные Цель и комментарии элементы Архитектурный проект Анализ компонентов Элементы, важные с архитектурной точки зрения Архитектурные части Механизмы проекта Классы анализа* Проектирование компонентов Классы проекта • Поддержка согласованности работ в ходе анализа (чтобы решение одного аналитика не противоречило решению другого). Идентификация общих механизмов на ранних этапах позволяет снизить риск принятия неверного тактического решения, касающегося общих стратегий и способного оказать негативное влияние на архитектуру всей системы. • Инкапсуляция бизнес-свойств и/или обеспечение доступа к данным системы и управление ими. Представление спецификаций, допускающих эффективную реализацию с помощью конкретных технологий. • Уточнение логического архитектурного разделения системы в ходе архитектурного анализа. Кластеризация элементов проекта. • Уточнение механизмов анализа для конкретных технологий. • Представление исходной объектно- ориентированной композиции желательного решения, обеспечивающего требуемое поведение. Описание отдельных элементов со связанными обязанностями. • Цели этой стадии совпадают с целями архитектурного проектирования, за исключением того, что работа выполняется на более низких уровнях абстракции (элементы проектирования компонентов, а не элементы архитектурного проектирования). Эти элементы проекта уточняются и конкретизируются до уровня, доступного для реализации. * Некоторые исследователи не согласны с использованием термина класс в данном контексте. Однако важно не то, как называется идея, а что она собой представляет.
Глава 6. Процесс 321 это не всегда плохо. На этапе анализа важно сохранить возможность последующего уточнения решения. Многие объекты и роли, идентифицированные на ранних этапах жизненного цикла программного обеспечения, достигают этапа реализации именно потому, что они имеют фундаментальное значение для концептуальной модели решаемой задачи. По мере углубления в проблему границы некоторых элементов могут измениться: элементы могут объединяться с похожими элементами в более крупные образования или — что происходит намного чаще — разделяться на более мелкие группы, взаимодействующие друг с другом и образующие единый механизм. Итак, элементы анализа часто бывают изменчивыми и нечеткими, они уточняются по мере развития проекта. Общий подход к идентификации элементов, по существу, одинаков на всех уровнях абстракций. Отличается лишь стартовая точка (абстракции, уже имеющиеся в распоряжении проектировщика), критерий (важен элемент с архитектурной точки зрения или нет), а также степень углубления в предмет (знает ли проектировщик внутреннее устройство элемента и различает ли он элементы, содержащиеся в нем). Например, стартовой точкой архитектурного проектирования являются результаты архитектурного анализа. В центре внимания архитектурного проектирования лежат элементы, важные с архитектурной точки зрения. Кроме того, на этом этапе проектировщик может изучать внутреннее устройство элементов, чтобы убедиться в том, что он правильно понимает их поведение, и исключить связанный с этим риск. Выполняя анализ и проектирование компонентов, разработчик в качестве стартовой точки использует результаты архитектурного анализа и проектирования. На этом этапе он идентифицирует оставшиеся элементы проекта, которые необходимы для реализации, в том числе уточняет мелкие элементы проекта, образующие более крупные компоненты (например, классы, обеспечивающие поведение компонента). Рекурсивное повторение идентификации элементов позволяет изобрести более подробные абстракции, на основе которых разрабатываются абстракции более высокого уровня, и открыть общие свойства среди существующих элементов, с помощью которых можно упростить систему. В ходе идентификации элементов проекта в первую очередь, как правило, идентифицируются крупномасштабные элементы, поскольку именно они образуют ядро логической структуры системы. Эти элементы состоят из более мелких структурных частей. Однако на самом деле элементы проектирования, имеющие разную степень детализации, могут идентифицироваться одновременно, хотя между ними все равно существует последовательная зависимость (например, невозможно идентифицировать классы, конкретизирующие реализацию определенного компонента, пока не будет идентифицирован сам компонент). Основными кандидатами на уточнение в рамках элементов проектирования являются следующие классы.
322 Часть П. Метод • Классы анализа с нетривиальными наборами требований. • Группы классов анализа, представляющих информацию, подлежащую совместной обработке. Элементы, информация которых должна обрабатываться совместно, принадлежат одному и тому же элементу проектирования, а обязанности, связанные с манипуляциями этой информации, должны быть возложены на этот элемент. • Группы классов анализа, взаимодействующих с целью обеспечения конкретного поведения или связанных с ним поведенческих свойств (например, классы анализа, участвующие в одной и той же или связанных реализациях). Сотрудничающие элементы должны принадлежать одному и тому же элементу проекта. • Группы классов анализа, имеющих одинаковые обязанности. Аналогичные (или связанные) обязанности должны быть возложены на один и тот же элемент проекта. Уточнение элементов анализа и их превращение в элементы проектирования зависит также от выбранных архитектурных и/или проектных шаблонов (особенно отражающих выбранный архитектурный стиль), а также от общих принципов проектирования. К таким шаблонам относятся стили ЮМ для электронной коммерции [28], архитектурные шаблоны [29] и шаблоны проектирования [31]. Некоторые примеры принципов проектирования, включающих в себя принципы проектирования промышленных компонентов, изложены в работе Чизмана (Cheesman) и Дэниелса (Daniels) [30], а лучшие приемы разработки бизнес-компонентов описаны в книге Херцума (Herzum) и Симса (Sims) [32]. В ходе идентификации элементов всегда целесообразно исследовать похожие системы, находящиеся на одинаковых уровнях абстракции. Таким образом проектировщик достигает преимуществ благодаря опыту, приобретенному при осуществлении других проектов, в рамках которых были приняты аналогичные проектные решения. В целом, на этапе идентификации элементов важно выявить возможность повторного использования существующих элементов, гарантируя, что контекст использования таких элементов не противоречит контексту разрабатываемого проекта. Логическое разделение, выявленное на этапе архитектурного анализа, обычно основывается на выборе конкретного архитектурного шаблона. Эти разделения уточняются на этапе проектирования в виде идентифицированных и сгруппированных элементов проекта. Некоторые принципы логического разделения системы предполагают кластеризацию элементов, обеспечивающих выполнение одной и той же функции. Функции, построенные из других функций, должны относиться к разным логическим частям. Функции, взаимодействующие в обеспечении определенного поведения на одном и том же уровне абстракции, должны относиться к разделам, предоставляющим эквивалентные услуги. Эти решения имеют стра-
Глава 6. Процесс 323 тегические последствия. В некоторых случаях такая кластеризация выполняется "сверху-вниз", в соответствии с глобальным представлением о системе и разделении абстракций, соответствующих основным логически связанным между собой функциям системы и/или предполагающих независимое изменение. Архитектура может также уточняться "снизу-вверх" с помощью семантически близких кластеров классов. Как только существующие разделы проекта превысят допустимые разделы или новые кластеры станут очевидными, проектировщик может ввести новое разделение проекта или реорганизовать существующие части. Такое уточнение является типичным для технологий ускоренного проектирования. Механизмы, идентифицированные на этапе архитектурного анализа, считаются хранилищами общих стратегий и инфраструктуры, необходимой для поддержки всех элементов системы. Эти механизмы выявляются на основе изучения основных услуг, которые могут потребоваться от системы, и описываются в довольно расплывчатых терминах. (Методы идентификации механизмов рассматриваются в главе 4.) Решения, касающиеся того, как будут проектироваться и реализовы- ваться эти механизмы, принимаются на этапе архитектурного проектирования. В частности, на этапе проектирования механизмы описываются в терминах конкретных возможностей, обеспечиваемых выбранной технологией реализации. Иногда элементы должны находиться на разных уровнях абстракции (т.е. элементы анализа и проектирования отделяются друг от друга), в противоположность ситуации, когда элементы просто переходят с одного уровня абстракции на другой. В таком случае, с точки зрения управления требованиями и изменениями, целесообразно отслеживать связи между разными уровнями абстракции. Эта возможность является чрезвычайно важной для эффективной и точной оценки последствий. Контрольные отметки и критерии успеха Идентификация элементов в рамках проекта считается завершенной успешно в определенном масштабе и на конкретном уровне абстракций, если проектировщик разработал подробный набор согласованных и подробно описанных абстракций. Другим критерием успеха является устойчивость модели анализа/проектирования. Иначе говоря, идентификацию элементов можно считать успешной, если модель анализа/проектирования не подвергается слишком резким изменениям на каждой итерации микропроцесса. Например, выявление элементов, важных с архитектурной точки зрения, на более поздних этапах жизненного цикла программного обеспечения, означает, что в требованиях, анализе или проекте кроется недоработка. Внезапное изменение модели анализа/проектирования является признаком того, что либо коллектив разработчиков недостаточно сосредоточился на решаемой задаче, либо архитектура является неверной. В ходе разработки проекта устойчивость низкоуровневых частей архитектуры можно отслеживать с помощью наблюдения за локальными изменениями взаимодействующих абстракций.
324 Часть П. Метод Определение взаимодействия между элементами Цель второго вида деятельности в рамках микропроцесса — определения взаимодействия между элементами — описать, как идентифицированные элементы сотрудничают между собой, обеспечивая требуемое поведение системы. Выполняя эту задачу, проектировщики уточняют идентифицированные элементы, разумно распределяя их обязанности. Результаты Основными результатами этого вида деятельности являются описания (realizations), показывающие, как идентифицированные элементы взаимодействуют друг с другом, обеспечивая требуемое поведение системы. Эти документы описывают, как выполняются требования к свойствам системы с помощью взаимодействующих элементов, находящихся на конкретном уровне абстракции. Они отражают явное распределение обязанностей среди взаимодействующих элементов и обеспечивают связь между требованиями к поведению системы и программным обеспечением. Вначале эти описания формулируются в терминах элементов анализа, а позднее — в терминах элементов проектирования. Описания и обязанности элементов документируются в модели анализа/проектирования. Уровень детализации и представления зависит от уровня абстракции, на котором работает проектировщик. На этапе анализа обязанности можно описывать в свободной форме. Как правило, для этого достаточно фразы или одного предложения. Если для описания обязанности элемента требуется больше слов, то это значит, что данная обязанность слишком сложна и должна быть разделена на более мелкие части. На этапе проектирования создаются спецификации каждого элемента, в которых указываются именованные операции, образующие протокол элемента. В ходе детализированного проектирования эти операции формально интерпретируются как интерфейсы с полными сигнатурами на выбранном языке реализации. Способы взаимодействия также документируются с помощью простых диаграмм. Чрезвычайно эффективным инструментом для этого являются диаграммы взаимодействия на языке UML (в частности, диаграммы последовательностей и связей). Кроме того, для описания элементов, состояние которых зависит от сотрудничества с другими элементами, можно использовать диаграммы конечных автоматов, отражающие изменения основных состояний. Диаграммы конечных автоматов являются очень эффективным средством для описания таких элементов. Более подробно этот вопрос освещен в разделе "Подробная семантика элементов", а также в главе 5. Этапы Анализ требований к поведению системы является отличным методом для распределения работ, которые следует поручить идентифицируемым элементам.
Глава 6. Процесс 325 Определение семантики набора элементов на конкретном уровне абстракции осуществляется так. 1. Анализ поведения — распределение обязанностей между элементами, обеспечивающими требуемое поведение (т.е. между элементами, идентифицированными на предыдущих этапах микропроцесса). При этом следует рассматривать как исключительное, так и ожидаемое поведение. Если жизненный цикл определенных элементов играет особую роль, то для этого элемента следует разработать конечный автомат. Результатом этого этапа является описание поведения в терминах сотрудничающих элементов и взаимодействий между ними. 2. Поиск шаблонов среди описаний и выражение этих шаблонов в терминах более абстрактных и обобщенных описаний. Этот подход одинаково хорош для всех уровней абстракции, как при анализе поведения системы, выраженного в виде сценариев или вариантов использования (анализ), так и при анализе поведения компонентов, выраженных в терминах обязанностей/интерфейсов (проектирование), а также при анализе поведения архитектурных механизмов, выраженных в текстуальном описании (анализ и проектирование). Рассмотрим каждый из этих этапов более подробно. Анализ поведения. Анализ поведения позволяет понять, как элементы решения обеспечивают выполнение требований. Основной результат анализа сценария является набор описаний, которые создаются с помощью методов анализа сценариев (настоятельно рекомендуется), анализа поведения или CRC-карточек, описанных в главе 4. Типичный порядок событий в ходе анализа сценариев имеет следующий вид. 1. Выбирается сценарий или набор сценариев для рассматриваемых требований. 2. Идентифицируются элементы, относящиеся к сценарию. (Эти элементы могут быть идентифицированы на предыдущих этапах микропроцесса.) 3. Просматривая сценарий, проектировщик присваивает каждому элементу его обязанности, чтобы добиться требуемого поведения системы. При необходимости указываются атрибуты — структурные элементы, обеспечивающие выполнение обязанностей. Примечание: на этом этапе следует сосредоточиться на поведении, а не на структуре. Поскольку атрибуты представляют собой структурные элементы, существует опасность преждевременного связывания решений, особенно на ранних стадиях анализа. На этом этапе атрибуты должны указываться лишь в той степени, в которой это требуется для построения концептуальной модели сценария.
326 Часть П. Метод 4. По мере анализа сценария обязанности перераспределяются так, чтобы сохранить разумный баланс. При возможности следует повторно использовать или адаптировать существующие обязанности. Очень часто происходит разделение крупных обязанностей на более мелкие. Намного реже тривиальные обязанности объединяются в более крупные. Анализ отдельного сценария может выявить соединение несопоставимых обязанностей в одном элементе. Такие элементы следует разделить на более мелкие элементы с согласованным и связанным набором обязанностей. 5. На этапе проектирования следует рассмотреть вопросы, связанные с параллельным и распределенным выполнением функций. Там, где есть возможности параллельно выполнять работу, следует указать действующих лиц, агентов и серверы, а также средства их синхронизации. Анализ может выявить необходимость новых связей между объектами, а также исключения или консолидации ненужных или избыточных элементов. Анализируя сценарий, проектировщик может выяснить, что состояние (или жизненный цикл) одного или нескольких элементов играет важную роль в общей реализации сценария. В таких случаях стоит затратить время и внимательнее изучить состояние видимых элементов и убедиться, что сценарий правильно отражает это состояние. Для точного описания этих состояний и переходов из одного состояния в другое следует использовать диаграммы конечных автоматов. Выявление шаблонов. На этом этапе распознается важность общих свойств. Идентифицируя семантику элементов, следует внимательно относиться к шаблонам поведения, открывающих возможность для повторного поведения элементов. Типичный порядок событий при выявлении шаблонов имеет следующий вид. 1. Выполняется поиск шаблонов взаимодействия между элементами системы на данном уровне абстракции. Эти взаимодействия могут представлять собой неявные идиомы или механизмы, которые необходимо проверить и убедиться, что между ними нет нежелательных различий. Нетривиальные шаблоны взаимодействия следует явно описать в документации в качестве стратегических решений, поскольку их можно повторно использовать, а не изобретать заново. Это позволяет сохранить целостность архитектурной концепции. 2. Выполняется поиск шаблонов поведения в полном наборе обязанностей, разработанных на данном уровне абстракции. Общие роли и обязанности следует унифицировать в форме общих элементов, имеющих общие обязанности. 3. На более низком уровне абстракции, когда конкретные операции уже заданы, выполняется поиск шаблонов среди сигнатур операций. Если сигна-
Глава 6. Процесс 327 туры повторяются, то следует устранить любые нежелательные различия и разработать общие классы. Выявленные шаблоны взаимодействия следует выразить в терминах более абстрактных и обобщенных описаний. Контрольные отметки и критерии успеха Определение взаимодействия между элементами в рамках микропроцесса считается успешно завершенным, если разработан набор элементов и обязанностей, обеспечивающих требуемые функциональные свойства системы в указанном масштабе на конкретном уровне абстракции, а также достигнуто сбалансированное распределение обязанностей между этими элементами. В результате должны быть созданы и обоснованы описания, в которых отражаются фундаментальные особенности поведения в указанном масштабе. Термин фундаментальный означает, что это свойство играет центральную роль в достижении цели приложения. Критериями успеха при разработке таких описаний являются полнота и простота. Каждое описание должно точно отражать семантику отдельных элементов, участвующих в системе. Хороший набор описаний должен охватывать все первичные сценарии и статистически важные вторичные сценарии. Описывать все без исключения сценарии не обязательно. Достаточно рассмотреть только первичные и несколько вторичных сценариев. Кроме того, хороший набор описаний должен также отражать шаблоны поведения и структуру решения, использующего общие свойства разных сценариев. При анализе обязанностей отдельных элементов следует иметь в виду, что в центре внимания должно находиться взаимодействие между элементами и определение "кто что делает". На этой стадии достаточно просто распознать обязанности элементов. На более высоких уровнях абстракции можно использовать неформальное описание обязанностей. На более низких уровнях абстракции требуется уточнить семантику, не слишком углубляясь в детали, поскольку явное определение семантики отдельных элементов является целью четвертого вида деятельности в рамках микропроцесса, описанного в разделе "Детализация семантики элементов". Перечислим несколько простых и полезных контрольных отметок, необходимых для оценки результатов. • Распределение обязанностей между элементами должно быть сбалансированным. Один элемент не должен выполнять все обязанности. • Обязанности элементов должны быть согласованными. Если обязанности отдельного элемента не связаны друг с другом, то их следует разделить среди нескольких элементов. • Не должно быть двух идентичных или очень похожих элементов.
328 Часть П. Метод • Обязанности, возложенные на элемент, должны поддерживать потоки, в которых он участвует. • Сложные или неясные обязанности означают, что абстракция определена неудачно. Итак, мы идентифицировали элементы и определили взаимодействия между ними. Настало время переключить внимание на отношения между элементами, обеспечивающими и поддерживающими эти взаимодействия. Определение отношений между элементами Цель третьего вида деятельности в рамках микропроцесса — определить отношения, обеспечивающие взаимодействие между элементами, определенными на предыдущем этапе. Определение отношений между элементами создает форму решения. В частности, на архитектурных уровнях абстракции отношения между основными элементами и частями системы определяют общую структуру системы и образуют базис для всех остальных отношений между элементами системы. Идентификация отношений позволяет очертить границы элементов и ясно указать, какие элементы взаимодействуют друг с другом. Это формализует разделение понятий среди элементов, которое было достигнуто на этапе определения взаимодействий между элементами. Результаты Основным результатом этого вида деятельности являются отношения между элементами на текущем уровне абстракции. Определенные отношения включаются в развивающуюся модель анализа/проектирования. Несмотря на то что эти отношения выражаются в конкретной форме (а именно с помощью языка программирования), рекомендуется представлять их визуально, используя либо диаграммы UML, либо произвольные диаграммы. Визуальные диаграммы позволяют шире взглянуть на архитектуру и выразить отношения, которые невозможно выразить с помощью языка программирования. Эти диаграммы позволяют визуализировать и оценить отношения, связывающие физически или логически удаленные элементы. Построив эти диаграммы, разработчик может выявить ранее скрытые шаблоны взаимодействия и осуществить тонкую настройку иерархии наследования. Нежелательно создавать слишком большой набор диаграмм, отражающих всевозможные точки зрения на отношения между элементами. Мы рекомендуем сосредоточиться лишь на самых важных диаграммах, причем слово важный относится к любому набору связанных элементов, отношения между которыми выражают некое фундаментальное архитектурное решение или деталь, необходимую для реализации. В частности, можно ограничиться изучением диаграмм, связанных с идентификацией взаимодействий между ними. Такие диаграммы должны
Глава 6. Процесс 329 содержать элементы, упомянутые в описаниях, а также отношения между ними, отражая структурный аспект системы. Этапы В целом определение отношений между элементами осуществляется в два этапа. 1. Идентификация связей — первоначальная идентификация семантических связей между элементами. 2. Уточнение связей — выявление семантики отношений (например, агрегация, зависимость и т.д.). Идентификация связей осуществляется на этапе анализа и ранних этапах проектирования. На этапе архитектурного анализа она позволяет уточнить отношения между высокоуровневыми частями архитектуры и основными абстракциями. На этапе архитектурного проектирования ее целью является определение отношений между основными компонентами, а также высокоуровневое объединение элементов проекта в разделы проекта. На этапе анализа компонентов идентификация связей выполняется для того, чтобы указать отношения между элементами анализа (включая связи, некоторые важные виды наследования и агрегацию). Типичный порядок событий при идентификации связей между элементами имеет следующий вид. 1. Собирается набор элементов, существующих на данном уровне абстракции или связанных конкретным сценарием или описанием. 2. Рассматривается семантическое отношение между любыми двумя элементами и устанавливается связь, если между ними существует зависимость. Определение связей обусловлено необходимостью переходить от одного элемента к другому и/или выявлять особенности поведения элементов. Если два элемента должны взаимодействовать друг с другом, то между ними должно существовать отношение. 3. Для каждой связи указывается роль каждого участника, а также их кратность и другие виды ограничений. Эти подробности следует включать в описание, только если они являются очевидными, поскольку их уточнение производится на следующем этапе. 4. Достигнутое решение проверяется путем анализа сценариев, в ходе которого разработчик должен убедиться, что указанные связи являются необходимыми и достаточными для навигации по элементам и исследования их поведения в рамках сценария. Как указывалось в главе 3, связи — это наиболее семантически слабые отношения: они представляют только определенный вид общей зависимости. Однако
330 Часть П. Метод на стадии анализа и ранних этапах проектирования достаточно просто указать интересные детали, касающиеся отношения между двумя абстракциями, предотвращая преждевременные выводы относительно подробного проекта. Уточнение связей относится как к анализу, так и к проектированию. На протяжении анализа связи могут уточняться и конкретизироваться, отражая процесс все более глубокого познания предметной области. На этапе проектирования можно добавлять новые конкретные отношения, чтобы обеспечить успешную реализацию. Основными видами отношений являются агрегация, композиция и зависимость. Они дополняются именами, ролями, кратностью и другими свойствами. Типичный порядок событий при уточнении связей между элементами имеет следующий вид. 1. Выполняется поиск набора элементов, объединенных определенными связями (например, элементы, перечисленные в конкретном описании), изучается семантика каждой связи и при необходимости уточняется ее тип. Представляет ли связь простое использование другого объекта? Если да, то связь должна быть уточнена как отношение зависимости. Представляет ли связь конкретное структурное отношение между исследуемыми элементами? Если да, то связь следует уточнить как отношение агрегации или композиции. Каждое из существующих отношений следует изучить с целью идентификации и документации их природы. 2. Выполняется поиск структурных шаблонов среди элементов. Если поиск завершается успешно, следует рассмотреть возможность создания новых элементов, обладающих общей структурой, с помощью наследования (размещение класса в существующей иерархии наследования или создание иерархии, если существующая иерархия не соответствует поставленной цели) или агрегации. 3. Выполняется поиск шаблонов поведения среди элементов. Если поиск завершается успешно, рассматривается возможность создания новых параметризованных элементов, обладающих общим поведением. 4. Изучается возможность навигации по существующим связям и устанавливаются соответствующие ограничения. Если двусторонняя навигация не обладает желательными свойствами, используются односторонние отношения. 5. По мере развития проекта в него включаются новые детали, например, роли, кратность и т.д. Каждую деталь описывать нежелательно. Достаточно просто включить информацию, важную для анализа или проектирования или необходимую для реализации.
Глава 6. Процесс 331 Контрольные отметки и критерии успеха Определение отношений между элементами в рамках микропроцесса считается успешно завершенным, если разработчик указал отношения между элементами на конкретном уровне абстракции. На этом этапе разработчики стремятся согласовать отношения между элементами, перечисленными в описании системы. В частности, в каждом описании отношения между элементами и взаимодействия между элементами должны быть согласованы (если есть сотрудничество, то должно существовать и отношение). Критериями успеха являются связность, связанность и полнота. Изучая отношения, идентифицированные на этапе анализа, разработчики ищут логически связные и слабо связанные элементы. Кроме того, должны быть найдены все важные отношения, существующие на данном уровне абстракции, так чтобы на следующем уровне абстракции не требовалось вводить новые отношения или выполнять неестественные действия, связанные с уже существующими отношениями. Трудности, связанные с указанием элементов, и отношения свидетельствуют о том, что разработчикам пока не удалось выявить осмысленное множество отношений между элементами. Детализация семантики элементов До сих пор нас интересовало, как элементы взаимодействуют друг с другом. Настало время внимательнее изучить семантику каждого элемента снизу вверх, чтобы убедиться, что она является непротиворечивой и ясной. Цель четвертого вида деятельности в рамках микропроцесса заключается в уточнении поведения и атрибутов каждого идентифицированного элемента на конкретном уровне абстракции, чтобы определить семантику, согласованную со всеми сценариями, в которых участвуют эти элементы, и гарантировать достаточный объем информации о каждом элементе для их использования на следующем уровне абстракции. На этой стадии семантика элемента уточняется на текущем уровне абстракции так, чтобы детализированной информации было достаточно для идентификации элементов на следующем уровне абстракции. Например, на этапе анализа целью детализации семантики элементов является информация, достаточная для идентификации элементов проектирования. В свою очередь, на этапе проектирования целью детализации семантики элементов является информация, достаточная для поддержки реализации. Этот вид деятельности намеренно поставлен на последнее место, поскольку микропроцесс сосредоточен, в первую очередь, на поведении элементов и взаимодействиях между ними, а решения, касающиеся подробной семантики отдельных элементов, откладываются на как можно более долгий срок. Такая стратегия предотвращает принятие преждевременных решений и оставляет свободу для изменения внутреннего представления элементов, необходимых для обеспечения
332 Часть П. Метод эффективности, хотя и ограниченную существующей архитектурой. В то время как первые три вида деятельности в рамках микропроцесса сосредоточены на внешнем представлении элементов и способах их взаимодействия, четвертый вид деятельности связан с изучением отдельных элементов, указанием их явного внешнего вида и уточнением их внутреннего представления. Результаты Основной результат детализации семантики элементов — уточненная модель анализа/проектирования, содержащая подробную семантику элементов. Уровень детализации и представления в документации зависит от уровня абстракции, на котором работают проектировщики. На этапе анализа результат детализации семантики элементов является довольно абстрактным. Разработчиков интересуют не столько представление элементов, сколько выявление новых абстракций и установление их обязанностей. Детализация семантики на уровне анализа связана с разработкой подробного описания этих обязанностей в виде диаграмм процессов, демонстрирующих общий поток операций. Для элементов, обязанности которых связаны с поведением, которое зависит от событий или порядка, в описание следует включать конечные автоматы, описывающие семантику каждого протокола элемента12. На этапе проектирования и особенно на его последних стадиях, связанных с детальным проектированием, необходимо принимать все более конкретные решения, касающиеся представления элементов. Уточняя протокол отдельных элементов, проектировщик может указывать имена конкретных операций, игнорируя их полную сигнатуру. Однако на практике полную сигнатуру каждой операции указывать не запрещается. Кроме того, на этапе проектирования можно указать на использование определенных алгоритмов. На низких уровнях абстракции, когда используется конкретный язык программирования (т.е. на этапе детального проектирования), подробная семантика может содержать даже псевдокод или выполняемый модуль. Создав формальный интерфейс класса, можно начинать его программирование, чтобы проверить и реализовать проектные решения. Основное преимущество формализации на этом этапе заключается в том, что они вынуждают разработчиков исследовать прагматику протоколов каждой абстракции. Невозможность определить ясную семантику элемента является признаком неудачной абстракции. 12 Протокол указывает, какие определенные операции и в каком порядке должны вызываться. Для большинства классов, кроме самых простых, операции обычно имеют предусловия, которые должны выполняться и часто связаны с вызовом других операций.
Глава 6. Процесс 333 Этапы Детализация семантики элементов связана с выбором структур и алгоритмов, описывающих структуру и поведение элемента. Типичный порядок событий в ходе детализации семантики элементов выглядит следующим образом. 1. Перечисляются роли и обязанности элемента. Собираются и консолидируются результаты отдельных описаний, созданных на предыдущих этапах в ходе выявления взаимодействия между элементами (второй вид деятельности в рамках микропроцесса). Эти описания помогают идентифицировать обязанности элементов. Обязанности элемента определяются путем просмотра всех взаимодействий, связанных с ним. (К обязанностям элемента относятся все услуги, которые запрашивают у него другие элементы.) 2. Каждая обязанность описывается более подробно. Для описания общего потока операций создается диаграмма процессов или последовательностей, для описания состояния элементов используются диаграммы конечных автоматов и т.д. По возможности указывается подходящий алгоритм для реализации каждой обязанности/операции. На этапе проектирования рассматривается возможность введения новых операций, позволяющих разделить сложные алгоритмы на более простые и повторно используемые части. Рассматриваются компромиссы между требованиями к памяти и вычислениями, связанными с элементом. 3. На этапе проектирования предметом изучения является наследование. Для этого выбираются подходящие абстрактные классы (или создаются новые, если задача носит достаточно общий характер), после чего уточняется иерархия наследования. Изучаются элементы, которым можно делегировать обязанности. В оптимальном варианте для этого может потребоваться минимальное уточнение обязанностей и/или протокола низкоуровневых элементов. Если наследование, конкретизация или делегирование обязанностей не поддерживает семантику элемента, следует рассмотреть подходящее представление элемента на следующем уровне абстракции (например, если разработчик находится на этапе проектирования, можно использовать примитивы языка реализации). Следует иметь в виду важность операций с точки зрения клиентов элемента и выбрать представление, оптимизирующее ожидаемые способы использования. Однако необходимо помнить, что невозможно оптимизировать элемент для всех способов использования. Собирая эмпирическую информацию, поступающую от пользователей, можно выявить неэффективные элементы и внести локальные изменения, не боясь нарушить предположения клиентов об абстракциях. 4. После определения обязанностей каждого клиента рассматриваются атрибуты, необходимые для их выполнения.
334 Часть П. Метод 5. На этапе проектирования изобретается совокупность операций, обеспечивающих выполнение обязанностей элемента. По мере возможности следует повторно использовать операции, связанные с концептуально похожими ролями и обязанностями. Для отдельного класса обязанности документируются как операции, а для компонента они представляют собой предоставляемые услуги и документируются как операции интерфейса. • Поочередно рассматривается каждая операция — вы должны убедиться, что она является элементарной. Если операция не является элементарной, то ее следует изолировать и разделить на более простые операции. Сложные операции могут инкапсулироваться в самом элементе (если операция носит достаточно общий характер или это требуется для обеспечения эффективности) или описываться в общем классе (особенно если операция подвергается частым изменениям). Декомпозиция операции позволяет повысить степень ее общности. • Рассматриваются потребности в конструировании, копировании и разрушении объектов [5]. Для этих видов операций следует придерживаться общей стратегии, не допуская, чтобы отдельные классы использовали свои собственные идиомы, если для этого нет разумных причин. • Рассматривается потребность в полноте. К элементу добавляются элементарные операции, которые не являются обязательными, но позволяют придать элементу завершенный вид и подготовить его для будущего использования. Следует понимать, что совершенства не существует, поэтому вы должны стремиться к простоте, а не усложнять работу. Детализируя обязанности элемента, можно выявить новые элементы, (например, создавая более полное описание обязанностей элемента, можно обнаружить, что при его разработке была пропущена важная информация, а для ее представления нужен новый элемент). Эти элементы и их обязанности следует указать в документации, а затем повторить описанные выше этапы применительно к новым элементам. По мере уточнения семантики отдельных элементов может выявиться их общность. В результате у проектировщика может возникнуть искушение начать разработку отношения наследования среди этих элементов, чтобы отразить их общее поведение или общую структуру. Однако важно избежать слишком преждевременного поиска отношений наследования, поскольку это может привести к потере целостности типа элемента. Использование наследования на этапе проектирования является широко распространенным, поскольку на этом этапе разработчик более глубоко понимает семантику элементов и может точнее определить их место
Глава 6. Процесс 335 в иерархии наследования. На этапе проектирования общность классов можно выразить с помощью иерархии обобщения/специализации. Определяя иерархию наследования, следует соблюдать баланс (иерархия не должна быть слишком длинной, слишком короткой, слишком широкой или слишком узкой). Если в структуре или поведении классов обнаруживаются шаблоны, следует изменить иерархию, чтобы общность стала максимальной (но не за счет простоты). Дополнительная информация, касающаяся конструирования иерархии наследования, представлена в главе 3. На ранних стадиях разработки, пока наследование еще не используется, семантика каждого элемента документируется отдельно. Однако если иерархия наследования уже создана, документирование семантики элемента должно предусматривать указание места этого элемента в иерархии. Рассматривая операции, связанные с данным элементом, важно решить, на каком уровне иерархии наследования их следует разместить. Операции, которые могут использоваться классами, расположенными на одном и том же уровне иерархии, следует помесить в суперклассе. Возможно, для этого понадобится создать новый промежуточный класс. Детализируя элементы семантики, вы должны оставаться на текущем уровне абстракции. Идентификация элементов на следующем уровне абстракции является первым видом деятельности на следующей итерации микропроцесса (или на этапе реализации). Контрольные отметки и критерии успеха Детализация семантики элемента в рамках микропроцесса считается завершенной успешно, если разработчик достиг полного понимания семантики элементов на заданном уровне абстракции (т.е. информация является достаточно подробной, чтобы можно было перейти на следующий уровень абстракции) и эта семантика выражена в форме, согласованной с указанным уровнем абстракции. Поскольку этот вид деятельности завершает микропроцесс, его целью является совокупность четких абстракций, сильно связных и слабо связанных абстракций. Оценка успеха детализации семантики элемента связана с анализом семантики отдельных элементов. Завершив этот этап, проектировщик должен сформулировать достаточный, элементарный и полный набор семантических свойств каждого элемента на заданном уровне абстракции. Эта информация должна быть достаточно подробной, чтобы идентифицировать элементы на следующем уровне абстракции. Например, на этапе анализа детализацию семантики можно считать успешно завершенной, если разработчик создал неформальное описание обязанностей и атрибутов элементов анализа и знает достаточно много, чтобы перейти на этап проектирования. На этапе проектирования детализация семантики считается успешной, если она сформулирована настолько подробно (в терминах операций и атрибутов), что допускает реализацию и тестирование (т.е. ее структуру
336 Часть П. Метод и способы использования можно воплотить с помощью конкретного языка программирования). Это не значит, что элементы должны быть описаны максимально подробно. Просто информации должно быть достаточно много, чтобы компетентный программист мог выполнить свою работу. Основным критерием качества этого процесса является простота. Сложная, запутанная или неэффективная семантика свидетельствует о том, что сам элемент сконструирован неудачно или выбран неверный способ его представления. На этом обсуждение видов деятельности, связанных с микропроцессом, и глава, посвященная проектированию программного обеспечения, завершается. Теперь вы знаете, как отличать общий жизненный цикл проекта (макропроцесс) от видов деятельности, связанных с анализом и проектированием (микропроцесс), а также понимаете связи между этими процессами. Для успешности проекта необходимо правильно выбрать процесс проектирования и согласовать его с поставленной целью на уровне как макро-, так и микропроцесса. Резюме • Успешные проекты обычно имеют четкую архитектурную концепцию, а также хорошо управляемый итеративный и поступательный цикл разработки. • Архитектура описывает важные решения, касающиеся структуры и поведения. Она, как правило, отражает архитектурный стиль проекта. Четкая архитектурная концепция упрощает конструкцию системы, повышает ее надежность и гибкость, допускает эффективное повторное использование решений и облегчает сопровождение. • Итеративный и поступательный процесс разработки обеспечивается с помощью реализации функциональных свойств системы в виде последовательных все более полных выпусков (внутренних или внешних). Каждый новый выпуск завершает очередную итерацию. Выбор функционального свойства, разрабатываемого на каждой итерации, зависит от вида риска, который должен быть снижен. Самые опасные риски должны быть устранены в первую очередь. Итеративный и последовательный подход являются основой наиболее современных методов проектирования программного обеспечения, поскольку они эффективно снижают риски, связанные с управлением и изменением проекта. • Все процессы, связанные с разработкой программного обеспечения, образуют шкалу процессов, на одном конце которых находятся методы ускоренного проектирования, а на другом — планомерные методы. Выбор правильного процесса разработки для конкретного проекта зависит от характеристик
Глава 6. Процесс 337 проекта (и организации) и должен обеспечить баланс между ускоренными и планомерными процессами. • Процесс разработки программного обеспечения описан с двух точек зрения — общего жизненного цикла проекта (макропроцесса), а также процесса анализа и проектирования (микропроцесса). Выбор стиля процесса (например, водопад, итеративный, ускоренный, планомерный и т.д.) влияет на макропроцесс, а выбор методов анализа и проектирования (например, структурный, объектно-ориентированный и т.д.) — на микропроцесс. Объектно-ориентированные методы анализа и проектирования в рамках микропроцесса работают одинаково эффективно независимо от того, какой стиль выбран для макропроцесса — ускоренный или планомерный. • Цель микропроцесса — удовлетворить требования, сформулированные на этапе макропроцесса (а также спецификации анализа и проектирования, созданные на предыдущих итерациях микропроцесса), и создать спецификации анализа и проектирования, необходимые для макропроцесса в качестве обратной связи. В конце концов микропроцесс приводит к формулировке спецификаций для реализации, создаваемой, тестируемой и разворачиваемой в рамках макропроцесса. • Микропроцесс сводится к четырем видам деятельности (идентификации элементов, определению взаимодействия между элементами, определению отношений между элементами и детализации семантики элементов). Каждая итерация микропроцесса предусматривает итеративное повторение этих действий, в результате которых формируются спецификации функциональных свойств системы на заданном уровне абстракции. Основные этапы и результаты этих видов деятельности на всех уровнях абстракции примерно одинаковы. Они отличаются лишь степенью детализации (чем ниже уровень абстракции, тем более подробными являются результаты).
ГЛАВА 7 ПРАКТИЧЕСКИЕ ВОПРОСЫ В настоящее время разработка программного обеспечения является многомиллиардным, конкурентным и общемировым бизнесом, распространенным от Северной Америки до Западной и Восточной Европы, Азии и Тихоокеанского региона. Несмотря на существование инструментов, поддерживающих выполнение основных функций объектно-ориентированного проектирования, — управление требованиями, управление конфигурацией, проектирование, кодирование и тестирование — в ходе разработки программного обеспечения остается много проблем. Графики работ нарушаются. Сметы перерасходуются. Функциональные свойства не обеспечиваются. Десятки и сотни миллионов долларов теряются в результате неудачных попыток проектирования. Ярким примером провала является система Virtual Case File, заказанная ФБР, которая должна была стать важным инструментом в борьбе с терроризмом. После более трех лет работы в апреле 2005 года "бюро решило прекратить проект стоимостью 170 млн долларов, включая 105 млн долларов, затраченных на ненужные программы [1]. 16 марта 2006 года ФБР выделило 305 млн долл. на разработку системы Sentinel, которая должна была заменить систему Virtual Case File [2]. Это лишь один из многочисленных примеров провальных попыток разработки программного обеспечения [3]. Ситуация осложняется тем, что проектирование программного обеспечения не является точной наукой. Рассмотрим, например, проектирование сложной базы данных с помощью моделирования производственных отношений — одного из основ объектно-ориентированного проектирования. Как отметил Гав- ришкевич (Hawryszkiewych): "Хотя все выглядит очень просто, проектирование сильно зависит от персональной оценки важности различных объектов на предприятии. В результате процесс проектирования становится непредсказуемым:
Глава 7. Практические вопросы 339 разные проектировщики могут создать разные модели одного и того же предприятия" [4]. Таким образом, независимо от сложности метода проектирования и глубины теоретического фундамента нельзя игнорировать практические соображения, продиктованные реальностью. Следовательно, необходимо учитывать практический опыт управления, касающегося подбора кадров, планирования выпусков и контроля качества программного обеспечения. Технологам это кажется крайне нудным занятием, но разработчики понимают, что это — реальные проблемы, которые необходимо успешно решить, чтобы создавать сложные программные системы. По этой причине эта глава посвящена прагматике 1 объектно-ориентированной разработки и влиянию объектной модели на реальные методы управления. 7.1 Управление и планирование На протяжении итеративного и поступательного жизненного цикла проекта очень важно обеспечить уверенное руководство, чтобы активно управлять работами и правильно определять их направление. Слишком много проектов потерпели крах из-за неспособности сосредоточиться на главном, и только сильная команда менеджеров может решить эту проблему. Управление риском В принципе, менеджер программного проекта обязан управлять нетехническим риском, в то время как технический риск входит в сферу компетенции архитектора проекта. Технические риски, существующие в объектно-ориентированных системах, связаны с выбором структуры наследования, обеспечивающей наилучший компромисс между удобством и гибкостью программного обеспечения, а также выбором механизмов, гарантирующих приемлемую производительность системы за счет упрощения архитектуры. К нетехническим рискам относятся вопросы контроля своевременности поставки программного обеспечения от субподрядчиков, а также управление отношениями между заказчиком и командой разработчиков, необходимое для выяснения реальных требований к системе на этапе анализа. Как указано в предыдущей главе, микропроцесс объектно-ориентированного проектирования по существу неустойчив и требует активного планирования. К счастью, макропроцесс объектно-ориентированного проектирования позволяет решить поставленную задачу благодаря многочисленным материальным объектам, поддающимся изучению, и методам управления, с помощью которых мене- 1 Словарь Webster's New World Dictionary определяет слово "прагматичный" так: "связанный с реальностью, а не с теорией или рассуждениями; практичный".
340 Часть П. Метод джер проекта может, при необходимости, перераспределить имеющиеся ресурсы. Эволюционный подход к проектированию, характерный для макропроцесса, означает, что существует возможность идентифицировать проблемы на ранних этапах жизненного цикла и разумно смягчить риски прежде, чем успех проекта окажется под угрозой. Многие приемы управления разработкой программного обеспечения, например, планирование заданий и сквозной контроль, не связаны с объектно-ориентированной технологией. Однако управление объектно-ориентированным проектом имеет свои особенности, в частности, поставленные задачи и промежуточные результаты не такие, как в других системах. Планирование заданий Выполняя многие средние и крупные проекты, целесообразно периодически организовывать совещания разработчиков, чтобы обсудить выполненную работу и наметить план на следующий период. Необходимо установить некую минимальную частоту совещаний, чтобы поощрять общение между членами коллектива. В то же время, слишком частые встречи снижают производительность труда и фактически являются признаком растерянности. Объектно-ориентированное проектирование программного обеспечения требует, чтобы отдельные разработчики имели достаточно много времени для размышлений, изобретения, конструирования и неформального общения с коллегами, когда необходимо обсудить технические подробности. Менеджеры команды должны планировать это время. Совещания разработчиков являются простым, но эффективным средством для согласования планов работ в рамках микропроцесса и выявления рисков, маячащих на горизонте. В результате таких совещаний распределение заданий может слегка корректироваться, обеспечивая устойчивость процесса: ни один проект не может допустить, чтобы одна часть разработчиков простаивала, ожидая, пока другие члены команды стабилизируют свою часть архитектуры. Это особенно верно для объектно-ориентированных систем, в которых архитектура пронизана классами и механизмами. Если основные классы постоянно изменяются, проект может зайти в тупик. В широком смысле, планирование заданий связано с расписанием результатов макропроцесса. В интервалах между очередными выпусками программного обеспечения менеджеры команды должны оценить близкие и долгосрочные риски, угрожающие проекту, сконцентрировать ресурсы, необходимые для устранения этих рисков 2, а затем управлять следующей итерацией микропроцесса. В результате происходит стабилизация системы, удовлетворяющей требованиям сценариев, запланированных для нового выпуска. Планирование заданий на этом 2Гилб (Gilb) замечает: "Если вы вяло боретесь с рисками, они сами станут активно атаковать вас" [6].
Глава 7. Практические вопросы 341 уровне очень часто оказывается неудачным из-за слишком оптимистических планов [5]. Разработка, которая казалась "делом техники растягивается на многие недели и месяцы. Кроме того, если разработчик, проектируя одну часть системы, предполагает, что остальные части системы работают в соответствии с определенным протоколом, а вместо этого получает неполно или неправильно изготовленные классы, то календарные планы выбрасываются в корзину. Еще более коварными являются ситуации, в которых расписание оказывается под угрозой из-за плохой производительности программного обеспечения. Для разрешения этих проблем часто приходится жертвовать некоторыми тактическими проектными решениями. Для того чтобы, планируя работу, не впасть в излишний оптимизм, следует инспектировать команду проектировщиков и их инструменты разработки. Как правило, планирование заданий протекает следующим образом. Вначале команда менеджеров направляет энергию разработчиков на конкретные части системы, например на проектирование классов для интерфейса с реляционной базой данных. Разработчики анализируют масштаб работ и оценивают время для их выполнения, которое менеджеры учитывают в ходе дальнейшего планирования. Проблема заключается в том, что эти оценки не всегда являются надежными, поскольку чаще всего они предполагают наиболее благоприятное развитие событий. Один разработчик может запросить на решение задачи неделю, а другой для выполнения этого же задания потребует месяц. Когда работа реально выполнена, может оказаться, что оба разработчика затратили на ее выполнение три недели. Это значит, что первый разработчик недооценил объем работ (общая проблема большинства программистов), а второй разработчик оценил задание более реалистично (как правило, потому, что проектировщики понимают разницу между рабочим и календарным временем, которое часто заполняется множеством действий, не имеющих отношения к проекту). Для того чтобы разработать надежный календарный план, необходимо ввести коэффициенты для пересчета оценок разработчиков. Это не признак недоверия к разработчикам, а просто признание реального факта, что большинство программистов специализируются на решении технических проблема, а не на планировании заданий. Менеджер должен помогать разработчикам учиться эффективно планировать свою работу — этот навык приходит только с опытом. Для того чтобы сократить объем неэффективного планирования, требуется адекватное обучение и принципы оценки объема работ. Объектно-ориентированный процесс разработки очевидным образом помогает установить коэффициенты пересчета. Итеративный и поступательный жизненный цикл проекта предполагает существование множества промежуточных контрольных отметок, устанавливаемых на ранних этапах. Менеджеры могут накапливать данные о работе каждого разработчика, определяя, насколько правильно он рассчитывает объем работ и выполняет календарный план. В ходе эволюции проекта менеджеры со временем все лучше понимают реальную производительность тру-
342 Часть П. Метод да каждого разработчика, а разработчики учатся более точно оценивать объем работ. То же самое можно сказать и об инструментах проектирования: предусматривая архитектурные выпуски на ранних этапах проекта, объектно-ориентированный подход к проектированию стимулирует раннее использование инструментов разработки, позволяющих своевременно выявить структурные ограничения. Инспектирование проекта Инспектирование проекта (development reviews) является общепринятой практикой, которой должен придерживаться каждый коллектив разработчиков. Как и планирование заданий, инспектирование проекта программного обеспечения слабо связано с объектно-ориентированной технологией. Однако инспектирование объектно-ориентированных и других систем производится по-разному. Менеджеры должны соблюдать баланс, избегая слишком частых или слишком редких проверок. За исключением систем, для которых надежность является критически важным свойством, проверять каждый аспект проекта просто неэкономично. Следовательно, менеджеры должны направить свои ограниченные ресурсы на проверку лишь стратегически важных аспектов проекта. Для объектно- ориентированных систем это означает проведение строгих формальных проверок сценариев использования и архитектуры системы и гораздо менее формальную проверку тактических решений. Для проверки следует выбирать первичные сценарии использования системы, а также альтернативные сценарии, реакция на которые является очень важной. Как указано в предыдущей главе, прецеденты использования (use case scenarios) являются первичными результатами анализа в рамках объектно-ориентированной разработки и предназначены для описания желательного поведения системы в терминах ее функциональных свойств с точки зрения пользователя. Формальные проверки прецедентов использования проводятся аналитиками команды (имеющими опыт проведения такой экспертизы), совместно с экспертами предметной области или конечными пользователями при участии других разработчиков, включая персонал, занимающийся проверкой качества (тестеров). Такие проверки лучше всего регулярно проводить на стадии анализа, не ожидая массовой проверки в конце этого этапа, когда будет уже слишком поздно переориентировать усилия аналитиков. Опыт показывает, что даже люди, не являющиеся проектировщиками, могут понять прецеденты использования, представленные в виде текста или визуальных диаграмм, например, диаграмм последовательностей3. В конечном счете, проверка помогает выработать общий словарь, который понимают как разработчики, так и пользователи системы. Привлечение к проверке других чле- 3При проверке проекта могут использоваться системы обозначений из самых разных предметных областей: астрономии, биологии, метеорологии, медицины и банковского дела.
Глава 7. Практические вопросы 343 нов команды помогает им уже на ранних этапах разработки уяснить реальные требования, предъявляемые к системе. При проверке архитектуры внимание нужно сосредоточить на общей структуре системы, включая ее структуру классов и механизмы. Как и проверка прецедентов использования системы, проверка архитектуры, выполняемая архитектором или другими проектировщиками, должна производиться на протяжении всего проекта. Ранние проверки должны концентрироваться на решении архитектурных проблем, а поздние могут переключить внимание на конкретные компоненты или механизмы. Основная цель таких проверок — оценка решений, принятых на ранних этапах жизненного цикла проекта. Это позволяет выработать архитектурную концепцию. Вторичной целью этих проверок является улучшение архитектуры путем выявления шаблонных классов и взаимодействий между объектами, которые впоследствии можно использовать для упрощения архитектуры. Неформальные проверки следует проводить регулярно в соответствии с процессом разработки. Как правило, в ходе таких проверок исследуются конкретные компоненты или механизмы нижнего уровня. Основная цель таких проверок состоит в оценке тактических решений, а побочная — обеспечить возможность обучения новичков более опытными разработчиками. 1.2 Подбор кадров Подбор кадров для объектно-ориентированного проектирования ничем не отличается от подбора кадров для выполнения традиционных проектов. Разница между этими видами проектирования обычно связана с распределением кадров на протяжении жизненного цикла проекта. Например, архитекторы и проектировщики играют главные роли на ранних этапах проектирования. Распределение ресурсов Одним из наиболее замечательных аспектов управления объектно-ориентированными проектами является тот факт, что в устойчивом состоянии, как правило, происходит сокращение общего объема необходимых ресурсов, а график их расходования отличается от традиционных методов, например, "одиночного водопада". Ключевыми словами в этом предложении является фраза "в устойчивом состоянии", т.е. когда команда проектировщиков состоит из опытных профессионалов. Вообще говоря, первый объектно-ориентированный проект, предпринятый организацией, потребует больше ресурсов, чем традиционный метод, в основном потому, что существует кривая обучения, описывающая адаптацию к новой технологии. Экономия ресурсов благодаря объектной модели проявится лишь во втором или третьем проекте, когда разработчики освоят методы объектно-ориентированного анализа и проектирования, научатся создавать архитектуру, проектировать
344 Часть П. Метод классы, находить общие абстракции и механизмы, а менеджеры научатся управлять итеративным и последовательным процессом проектирования. На стадии анализа потребность в ресурсах при переходе на объектно-ориентированные методы обычно не изменяется. Однако, поскольку объектно-ориентированный процесс акцентирует внимание на проектировании архитектуры, архитекторы и другие проектировщики должны привлекаться намного раньше, иногда начиная архитектурные исследования уже на последних этапах анализа. На более поздних этапах, как правило, требуется меньше ресурсов, в основном потому, что общие абстракции и механизмы, изобретенные в ходе архитектурного проектирования или на предыдущих итерациях, облегчают работу. Тестирование может также требовать меньше ресурсов, главным образом потому, что добавление новых функциональных свойств классов или механизмов обычно происходит путем модификации структуры, о которой известно, что она работает правильно. Таким образом, тестирование начинается на более ранних этапах жизненного цикла и носит поступательный, а не монолитный характер. Интеграция также обычно требует меньше ресурсов по сравнению с традиционными методами, в основном потому, что она тоже происходит постепенно, а не одним махом. Таким образом, в устойчивом состоянии, когда проектированием занимается команда опытных профессионалов, стоимость рабочей силы при объектно-ориентированном проектировании обычно оказывается меньше, чем при традиционных подходах. Более того, если учесть эксплуатационные затраты, связанные с объектно-ориентированным программным обеспечением, то окажется, что весь жизненный цикл часто стоит дешевле, поскольку конечный продукт, как правило, имеет более высокое качество и легче поддается изменениям. Роли разработчиков Следует подчеркнуть, что в конечном счете программное обеспечение создают люди. Разработчиков нельзя рассматривать как взаимозаменяемых членов коллектива. Успешное создание любой сложной системы требует уникальных и разнообразных навыков от всех членов целеустремленного коллектива. Опыт показывает, что объектно-ориентированный процесс требует несколько иного разделения труда по сравнению с традиционными методами. В объектно- ориентированном проекте основными считаются следующие три роли: 1. Архитектор проекта. 2. Разработчик компонентов. 3. Специалист по применению. Архитектор проекта (project architect) — это впередсмотрящий. Он отвечает за эволюцию и сопровождение архитектуры системы. Для малых или средних систем архитектурное проектирование обычно выполняется несколькими особенно
Глава 7. Практические вопросы 345 проницательными специалистами. Для больших проектов эта обязанность может быть распределена среди многих разработчиков. Архитектор проекта не всегда является самым главным разработчиком. Однако архитектором проекта всегда становится один из наиболее квалифицированных специалистов, имеющих опыт принятия стратегических решений, как правило, благодаря большому опыту в построении систем такого типа. Благодаря своему опыту, разработчики интуитивно знают общие архитектурные шаблоны в данной предметной области и умеют определять эффективность определенных архитектурных вариантов. Кроме опыта в области анализа и проектирования архитекторы должны уметь программировать, поскольку их решения в конце концов воплощаются с помощью классов и объектов. Ни в коем случае не следует нанимать архитектора со стороны, который, образно выражаясь, влетает на белом коне, провозглашает некую архитектурную концепцию, а затем скачет прочь, оставляя других расхлебывать последствия его решений. Гораздо лучше вовлечь архитектора в активную работу уже на этапе анализа и пользоваться его услугами как можно дольше, вплоть до полного завершения проекта. В этом случае архитектор лучше сможет понять потребности системы и со временем испытает на себе последствия своих решений. Кроме того, возлагая ответственность за архитектурную целостность на одного человека или небольшую группу разработчиков, проектировщик повышает шансы разработать более гибкую архитектуру. Разработчики компонентов (component leads) являются главными создателями абстракций в рамках проекта. Они отвечают за проектирование компонентов в целом. В сотрудничестве с архитектором проекта каждый разработчик компонентов должен изобретать, обосновывать и согласовывать интерфейсы компонентов, а затем руководить их реализацией. Таким образом, разработчики компонентов являются окончательными владельцами кластеров классов и связанных с ними механизмов, а также отвечают за тестирование и выпуск промежуточных вариантов системы в ходе ее эволюции. Разработчики компонентов должны хорошо знать систему обозначений и процесс объектно-ориентированной разработки программного обеспечения. Они могут быть более умелыми проектировщиками и программистами, чем архитектор проекта, но не иметь такого широкого кругозора. В среднем, разработчики компонентов составляют от трети до половины численности команды. Специалисты по применению — это подчиненные участники проекта, на которых возложена одна из двух обязанностей. Некоторые из них отвечают за реализацию компонентов под руководством их разработчиков. Эта работа может быть связана с разработкой определенных классов, но в основном она сводится к реализации и тестированию классов и механизмов, разработанных другими проектировщиками. Вторая категория специалистов по применению состоит из членов команды, отвечающих за сборку классов, созданных архитектором и раз-
346 Часть П. Метод работниками компонентов в рамках определенных прецедентов использования системы. Иначе говоря, эти программисты пишут небольшие программы на языке предметной области, определенном классами и механизмами архитектуры. Кроме того, иногда специалистам по применению поручают создавать более подробные классы под внимательным руководством разработчиков компонентов. Специалисты по применению знакомы с системой обозначений и объектно- ориентированным процессом проектирования, но не обязаны быть экспертами в этих областях. Однако они должны быть очень хорошими программистами, знающими основные идиомы и слабые места выбранных языков программирования. В среднем специалисты по применению составляют половину или более половины команды разработчиков. Разрыв в квалификации специалистов усложняет подбор кадров в организациях, разрабатывающих программное обеспечение. Обычно в них работают несколько профессиональных проектировщиков и много менее опытных сотрудников. Социальная польза предлагаемого подхода к подбору кадров состоит в том, что он открывает путь для карьеры более молодым сотрудникам. В этом случае начинающие специалисты работают под руководством более опытных разработчиков, вступая с ними в отношение мастер/подмастерье. По мере приобретения опыта в использовании хорошо спроектированных классов, они смогут сами создавать такие классы. Таким образом, хотя не все разработчики должны быть экспертами по абстракциям, каждый из них может со временем этому научиться. В больших проектах для выполнения работы могут потребоваться дополнительные роли. Большинство из них (например, роль системного администратора) не связаны с использованием объектно-ориентированной технологии, хотя некоторые имеют к ней непосредственное отношение (например, инженер, отвечающий за повторное использование). • Менеджер проекта Отвечает за активное управление поставками, заданиями, ресурсами и графиком работ в рамках проекта. • Аналитик Отвечает за развитие и интерпретацию требований конечных пользователей; должен быть экспертом в предметной области, но работать в тесном контакте с остальными разработчиками. • Инженер, ответствен- Управляет хранилищем классов, компонентов и схем; ный за повторное участвуя в проверках и других работах, активно ищет использование общие свойства и настаивает на их использовании; приобретает (например, из коммерческих библиотек), разрабатывает или адаптирует классы и компоненты для общего использования в рамках проекта или всей организации.
Глава 7. Практические вопросы 347 • Контролер качества Оценивает качество результатов проектирования; определяет общую стратегию тестирования всех прототипов и выпусков. • Менеджер по Отвечает за сборку совместимых друг с другом вер- интеграции сий компонентов в форме выпусков программного обеспечения; поддерживают конфигурацию выпусков. • Ответственный за Готовит для конечного пользователя документацию документацию по программному обеспечению и его архитектуре. β Системный Отвечает за создание и адаптацию инструментов программист программирования, облегчающих производство программ в рамках проекта. • Системный Управляет физическими компьютерными ресурсами администратор в проекте. Разумеется, не каждый проект требует исполнения всех этих ролей. В небольших проектах участники разработки могут совмещать обязанности. В более крупных проектах каждую из ролей может играть целая организация. В еще более крупных проектах возникают дополнительные роли, такие как архитектор предметной области, методист, ответственный за управление конфигурацией и бизнес- аналитик. Некоторые из этих ролей, например, методист, могут одновременно охватывать несколько проектов [29]. Как показывает опыт, объектно-ориентированная разработка позволяет уменьшить количество разработчиков по сравнению с традиционными методами. Действительно, команда, состоящая из 30-40 разработчиков, вполне способна за один год создать высококачественную программу объемом в несколько сот тысяч строк. Однако мы согласны с Боемом (Boehm), полагающим, что "наилучших результатов достигают небольшие группы высококвалифицированных разработчиков" [7]. К сожалению, попытка уменьшить количество разработчиков может вызвать сопротивление. Этот подход нарушает планы некоторых менеджеров построить империю. Кроме того, менеджеры любят скрываться за спинами многочисленных служащих, так как чем больше подчиненных, тем больше власти. Если же проект потерпит крах, у менеджера найдется масса возможностей возложить ответственность на кого-нибудь другого. Каким бы изощренным ни был метод проектирования и какими бы современными ни были инструменты разработки, менеджер не освобождается от ответственности за подбор сотрудников, способных мыслить, и не имеет права "включать автопилот" [8].
348 Часть II. Метод 7.3 Управление выпусками Управление версиями.в рамках объектно-ориентированного проектирования напоминает традиционную разработку программного обеспечения. Версии создают основу для развития проекта. Команда разработчиков должна управлять конфигурацией системы, интегрируя и проверяя части созданного программного обеспечения: от классов до компонентов, вплоть до окончательной версии. Управление конфигурацией и контроль версий Представим себе разработчика, ответственного за создание конкретного компонента. Он должен иметь рабочую версию этого компонента, т.е. разрабатываемую версию. Для дальнейшей работы ему потребуются как минимум интерфейсы всех импортируемых компонентов. Как только рабочая версия стабилизируется, она передается команде, занимающейся интеграцией и собирающей совместимые компоненты в целую систему. В конце концов этот набор компонентов фиксируется и становится базой для внутреннего выпуска. Таким образом, внутренний выпуск становится текущей оперативной версией программного обеспечения, доступной всем разработчикам, обязанным уточнить свои части этой реализации. Тем временем, наш проектировщик может работать над новой версией своего компонента. Таким образом, разработка может вестись параллельно и оставаться устойчивой благодаря четко определенным и защищенным интерфейсам компонентов. В этой модели скрыта идея, что основной контролируемой единицей является не отдельный класс, а группа классов. Опыт показывает, что управление версиями классов слишком трудоемко, так как они слишком взаимосвязаны. Лучше выпускать версии связанных между собой групп классов. Это не значит, что контроль версий классов проводить не стоит — просто это не является первоочередной задачей. Иначе говоря, следует поддерживать контроль версий компонентов, поскольку на основе групп классов создаются компоненты. В любой момент эволюции системы могут существовать несколько версий конкретного компонента: версия для текущего разрабатываемого выпуска, версия для текущего внутреннего выпуска и версия для последнего выпуска, предназначенного для заказчика. Это усиливает необходимость достаточно мощных средств управления конфигурацией и контроля версий. "Исходный код" — это не только результат проектирования, но и все остальные продукты объектно-ориентированной разработки, например, технические требования, визуальные модели и архитектурная документация.
Глава 7. Практические вопросы 349 Интеграция Промышленные проекты предусматривают создание семейств программ. На любом этапе процесса разработки существует множество прототипов и выпусков, а также вспомогательных инструментов. Часто каждый разработчик имеет свое собственное представление о разрабатываемой системе. Как указывалось в предыдущей главе, итеративная и поступательная природа объектно-ориентированной разработки означает, что интеграцию нельзя проводить "одним махом" (хотя в случае авральных работ это происходит именно так). Как правило, интеграция выполняется в виде последовательных небольших этапов, каждый из которых завершается созданием нового прототипа или варианта архитектуры. Каждая новая версия поступательно уточняет предыдущие стабильные версии. Как указывают Дэвис (Davis) и его соавторы: "При поступательной разработке сначала сознательно создается первоначальный программный продукт, удовлетворяющий нескольким техническим требованиям, причем сконструированный так, чтобы облегчить инкорпорацию новых требований и обеспечивающий более высокую приспособляемость" [9]. С точки зрения конечного пользователя, макропроцесс выглядит как поток последовательных версий, постепенно расширяющих функциональные возможности, превращаясь в конечном итоге в окончательную версию системы. С точки зрения человека, наблюдающего процесс изнутри, количество версий намного больше, но только некоторые из них фиксируются, чтобы стабилизировать важные интерфейсы системы. Такая стратегия снижает риск, связанный с разработкой проекта, ускоряя выявление архитектурных проблем и обнаружение проблем на ранних стадиях разработки. Разрабатывая проект среднего размера, организация может готовить внутренние версии каждые два-три месяца. Для более сложных проектов интервал между версиями может увеличиться до шести месяцев, в соответствии с потребностями проекта. В стабильном состоянии версия состоит из множества совместимых компонентов вместе с соответствующей документацией. Создание версии становится возможным лишь при условии, что главные компоненты проекта достаточно устойчивы и работают согласованно, обеспечивая новый уровень функциональности. Тестирование Принцип непрерывной интеграции можно применить и к тестированию, которое также должно производиться в течение всего процесса разработки. В контексте объектно-ориентированной архитектуры тестирование должно производиться в трех направлениях. • Тестирование модулей предполагает проверку отдельных классов и механизмов. Оно является обязанностью инженера, который их создал.
350 Часть П. Метод • Тестирование компонентов предполагает тестирование завершенных компонентов. Оно проводится регрессивно для каждой вновь выпускаемой версии подсистемы и является обязанностью разработчика компонентов. Следует подчеркнуть, что термин компонент является обобщенным и может означать как отдельную составную часть малого проекта, так и подсистему крупного проекта. • Тестирование системы предполагает проверку системы как единого целого. Оно входит в обязанности контролеров качества и осуществляется, как правило, в виде регрессивных тестов при сборке новых версий. На каждом уровне тестирование в первую очередь должно быть сосредоточено на внешнем поведении системы, а во вторую — на определении границ системы, чтобы понять, в каких условиях она может выйти из строя. 7.4 Повторное использование Одним из наиболее важных свойств объектно-ориентированной разработки является возможность повторного использования проектных решений. Однако для этого менеджеры должны понимать важность этих преимуществ. Элементы повторного использования Любой продукт проектирования (сценарий, как для проверки технических требований, так и для тестирования, схема, код и документация) может быть использован повторно. Как указывалось в главе 3, первичным лингвистическим средством повторного использования являются классы: они могут порождать подклассы или расширять базовый класс. Кроме того, как отмечалось в главе 4, можно повторно использовать шаблоны классов, объектов и схем в виде идиом, механизмов и сред разработки. Повторное использование взаимодействующих классов в виде компонентов обеспечивает наибольшие преимущества. Повторное использование сред разработки и шаблонов находится на более высоком уровне абстракции по сравнению с использованием индивидуальных классов и приносит больший выигрыш (хотя достигается труднее). Не следует слепо доверять цифрам, характеризующим степень повторного использования [10]. В удачных проектах, с которыми нам приходилось сталкиваться, количество повторно использованных элементов доходило до 70% (т.е. почти три четверти программного обеспечения системы было позаимствовано из других источников), а иногда равнялось нулю. Степень повторного использования не следует считать целевым показателем. Возможность повторного использования сильно зависит от предметной области и нетехнических факторов, таких, например, как
Глава 7. Практические вопросы 351 напряженность рабочего графика, отношения с субподрядчиками и соображения безопасности. В конечном счете, любое повторное использование лучше, чем его полное отсутствие, так как оно экономит ресурсы, которые иначе пришлось бы потратить на "изобретение велосипеда". Как осуществить повторное использование? Повторное использование решений в пределах проекта или даже целой организации не должно протекать случайным образом. Следует активно искать возможности для этого и поощрять его осуществление. Действительно, именно поэтому поиск повторяющихся шаблонов явно выделен как отдельная стадия макропроцесса. Программа повторного использования становится более эффективной, если руководство этой работой поручено конкретному лицу, а все остальные участники проекта обязаны участвовать в ней. Эта работа сводится к идентификации возможной общности объектов при проверке архитектуры, реализации этих возможностей путем создания новых или адаптации старых компонентов и распространению их среди других разработчиков. Для этого необходимо ввести явное поощрение повторного использования проектных решений. Даже простые формы поощрения, такие как признание равных прав автора первоначального кода и открывателя возможности его повторного использования, оказываются хорошими стимулами. Кроме самостоятельной разработки повторно используемых проектных решений, можно покупать коммерческие библиотеки классов и компонентов у поставщиков. Однако это не снимает с проектировщиков ответственности за эффективность разработки в рамках выбранной архитектуры. Эта задача не сводится к простому соединению классов и компонентов [30]. Повторное использование может не принести краткосрочных выгод, но обязательно окупится в долгосрочной перспективе. Повторное использование проектных решений будет успешным только при условии, что организация имеет далеко идущие планы разработки программного обеспечения и стремится оптимизировать ресурсы не только в рамках текущего процесса. 7.5 Гарантия качества и его показатели Обеспечение качества программного обеспечения — это "систематическая работа, гарантирующая готовность всего программного продукта к использованию" [11]. Для оценки качества программного обеспечения необходимо иметь количественные критерии. В качестве критериев оценки качества объектно-ориентированных систем можно использовать традиционные показатели.
352 Часть П. Метод Качество программного продукта Шульмейер (Schulmeyer) и МакМанус (McManus) определяют качество программного обеспечения как "пригодность всего программного продукта к использованию" [12]. Качество программного обеспечения не возникает самопроизвольно: оно должно создаваться. Действительно, сама по себе объектно-ориентированная технология не гарантирует качества автоматически: можно использовать методы объектно-ориентированного анализа и проектирования и тем не менее создавать неудачные проекты, а также писать очень плохие программы на объектно- ориентированных языках программирования. По этой причине в процессе объектно-ориентированного анализа и проектирования огромное значение придается архитектуре программного обеспечения. Простая и адаптируемая система занимает центральное место в любой качественной программной системе. Ее качество обеспечивается простыми и согласованными тактическим проектными решениями, на основе которых принимаются стратегические решения. Как уже указывалось, даже при разработке объектно-ориентированных систем необходимо систематически проводить проверки и другие виды инспекции, связанной с оценкой качества. Вероятно, наиболее важным количественным показателем качества программного обеспечения является скорость выявления ошибок (defect-discovery rate). В ходе эволюции системы разработчики отслеживают дефекты программного обеспечения, ранжируя их по степени серьезности последствий и местоположению. Скорость обнаружения ошибок — это показатель, позволяющий оценить, как быстро обнаруживаются дефекты, изображаемые в виде графика. По мнению Доббинса (Dobbins), "наклон этого графика важнее, чем фактическое количество ошибок" [13]. Если процесс разработки находится под контролем, то этот график имеет колоколообразную форму, а его пик находится примерно в средней точке периода тестирования, а затем снижается до очень низкого уровня. Процесс, вышедший из-под контроля, характеризуется кривой, очень слабо убывающей со временем или не убывающей вообще. Одна из причин, по которым макропроцесс объектно-ориентированной разработки оказался настолько успешным, заключается в том, что он позволяет вести своевременный и постоянный сбор данных о количестве обнаруженных ошибок. Каждый следующий выпуск подвергается тестированию системы, на основе которого конструируется график скорости обнаружения ошибок, зависящей от времени. Несмотря на то что ранние выпуски не имеют всех функциональных свойств системы, если процесс разработки выполняется правильно, для него также характерна колоколообразная кривая скорости выявления ошибок. Другим количественным показателем качества является плотность ошибок (defect density). Как правило, для ее оценки используется количество ошибок в расчете на одну тысячу исходного кода (KSLOC). Если проект находится под кон-
Глава 7. Практические вопросы 353 тролем, то плотность ошибок "стабилизируется после проверки примерно 10 000 строк исходного кода и остается практически постоянным независимо от общего объема программы" [14]. В объектно-ориентированных системах плотность ошибок полезно измерять, определяя среднее количество ошибок в классе. Для этого целесообразно применять правило 80/20: 80% обнаруженных ошибок должно быть сосредоточено в 20% классов системы [15]. Объектно-ориентированные показатели Британский физик лорд Кельвин (Kelvin), в честь которого названа шкала температуры, однажды так высказался об измерении: "Если вы можете измерить то, о чем говорите, и способны выразить это в числах, то вы знаете кое-что об изучаемом предмете. Однако если вы не способны измерить его, то ваши знания недостаточны и неудовлетворительны. Вы можете находиться в начале исследования, но вряд ли сможете продвинуться дальше"4. Таким образом, для того чтобы оценить объектно-ориентированную разработку, необходим количественный показатель качества анализа и проектирования. Показатели, позволяющие оценить качество программного обеспечения, можно разделить на две категории: характеристики процесса и характеристики продукции. Характеристики процесса (process metrics), которые иногда называются характеристиками проекта (project metrics), помогают менеджерам оценивать прогресс в зависимости от используемого метода объектно-ориентированной разработки. К характеристикам процесса относятся количество затраченных человеко-часов, объем выполненной работы и количество затраченных долларов. Все они сравниваются с плановыми показателями. Кроме того, существуют показатели, более тесно связанные с объектно-ориентированной разработкой, такие как показатели, предложенные Лоренцом (Lorenz) и Киддом (Kidd) [16]. • Размер приложения ■ Количество сценариев (NSS) ■ Количество основных классов (NKS) ■ Количество вспомогательных классов (NKC) ■ Количество подсистем (NOS) • Количество сотрудников ■ Количество человеко-часов, затраченных на класс (PDC) 4Лорд Уильям Кельвин высказал эту мысль в журнале Popular Lectures and Addresses, издававшемся в 1981-1984 гг. Он также считал, что машины тяжелее воздуха летать не могут. Мы согласны лишь с первым из его утверждений.
354 Часть П. Метод ■ Количество классов в расчете на одного разработчика (CPD) • Расписание ■ Количество основных итераций (NMI) ■ Количество выполненных контрактов (NCC) Прогресс разработки целесообразно оценивать количеством завершенных и работоспособных классов и компонентов в логической схеме и физической модели соответственно. Как указывалось в предыдущей главе, другим показателем прогресса является устойчивость основных интерфейсов (т.е. частота их изменений). Сначала интерфейсы всех основных абстракций изменяются ежедневно, чуть ли не ежечасно. Со временем первыми стабилизируются наиболее важные из основных интерфейсов, затем менее важные и т.д. По мере приближения к концу жизненного цикла проекта изменения должны касаться только самых несущественных интерфейсов, так как основные усилия направляются на то, чтобы согласовать работу разработанных классов и компонентов. Иногда возникает необходимость внести изменения в критически важные интерфейсы, но обычно они являются совместимыми снизу вверх. Даже в этом случае изменения следует вносить только после тщательного анализа их последствий. Такие изменения можно постепенно вносить в промежуточные версии разрабатываемой системы. Наиболее важными являются характеристики продукции (иногда называемые характеристиками проекта), позволяющие разработчикам оценить артефакты анализа и проектирования. Правильно выбранные показатели могут помочь архитекторам и разработчикам компонентов оценить качество проекта. Например, с их помощью можно выяснить, насколько полно выполняются критерии проекта, например, насколько большой является глубина дерева наследования. Измеряя и сравнивая количественные показатели с характеристиками других проектов, выполненных ранее, можно оценить качество текущего проекта. Чидамбер (Chidamber) и Кемерер (Kemerer) предложили несколько показателей качества проекта, независящих от языка программирования, которые можно непосредственно применить к объектно-ориентированным системам [17]. • Средневзвешенное количество методов в классе (WMC). • Глубина дерева наследования (DIT). • Количество потомков (NOC). • Связанность объектов (СВО). • Отклик на класс (RFC). • Недостаток связности среди методов (LCOM). Средневзвешенное количество методов в классе позволяет оценить сложность методов в классе. Если все методы имеют одинаковую сложность, то этот показатель равен количеству методов в классе. Особенно полезен этот показатель,
Глава 7. Практические вопросы 355 если методы имеют разную сложность. Однако для обеспечения гибкости Чидам- бер и Кемерер не стали регламентировать способы оценки сложности методов. В целом, чем больше методов в классе, тем он сложнее, специфичнее и сильнее подвержен ошибкам [17]. Глубина дерева наследования и количество потомков позволяют оценить форму и размеры структуры классов. Как указывалось в главе 3, хорошо структурированная объектно-ориентированная система обычно представляет собой лес классов, а не одно очень большое дерево. Глубина дерева наследования, отсчитываемая от изучаемого класса до базового класса на самом высоком уровне, характеризует влияние наследуемых свойств на этот класс. Чем глубже дерево наследования, тем сложнее класс, поскольку он наследует функциональные свойства своих суперклассов. Спускаясь по дереву наследования, можно обнаружить производные классы, являющиеся потомками базового класса. Чем больше потомков имеет класс, тем сильнее его влияние на проект системы. Это объясняется возможностью повторного использования классов [17]. Связанность объектов оценивает их взаимозависимость. Как и в традиционном программировании, проект должен состоять из слабо связанных объектов, повышающих возможность повторного использования. Отклик на класс — это количество методов, которые могут вызываться в ответ на сообщение, посланное экземплярами этого класса. В целом, если класс содержит значительно больше методов, чем вызывает сам, он считается сложным. Недостаток связности методов позволяет оценить степень целостности абстракции. Класс со слабой связностью методов, скорее всего, реализует случайную или неприемлемую абстракцию. Такой класс следует разделить на несколько классов или делегировать его обязанности другим существующим классам [17]. В статье, посвященной оценке качества программного обеспечения, Кан (Кап) рассматривает примеры использования характеристик продукции, предложенные Лоренцем (в работе Лоренца и Кидда, опубликованной в 1994 году), а также Чидамбером и Кемерером. В работе Лоренца предложены одиннадцать показателей, среди которых есть несколько объектно-ориентированных характеристик проекта, а также правила их применения. Кан отметил, что эти правила весьма полезны: "Они являются результатом большого опыта в области разработки объектно-ориентированных проектов. Их можно считать ориентирами для сравнения и интерпретации проектов." [18] Относительно показателей Чидамбера и Кемерера (показатели СК), Кан отметил, что "для их достоверной оценки необходимо провести больше эмпирических исследований" [18]. Чидамбер и Кемерер считают, что пороговые показатели качества следует устанавливать для каждого проекта отдельно. Как указал Кан: "На практике эти показатели можно использовать как индикатор того, что класс требует повышенного внимания" [18].
356 Часть П. Метод Недавно Кемерер и Дарси (Darcy) привели несколько примеров использования показателей СК на практике. Исходя из полученных результатов, они сформулировали следующие выводы [19]. • Показатели СК хорошо зарекомендовали себя в нескольких предметных областях. • Они тесно связаны с показателями качества проекта (например, стоимостью, количеством ошибок, степенью повторного использования и легкостью сопровождения). • Особенно полезными характеристиками являются размер (WMC), связанность (СВО или RFC) и связность (LCOM). • Отношения между показателями качества и прогнозными характеристиками должны учитывать особенности проекта. Споры о связи между принципами объектно-ориентированной разработки и качеством программного обеспечения не затихают. Особенно интенсивно ведутся дебаты об оптимальном составе объектно-ориентированных показателей качества. Мы полагаем, что перечисленные выше характеристики вполне разумны и позволяют архитекторам и разработчикам компонентов правильно оценить качество объектно-ориентированного проекта. 7.6 Документация Кроме исходного текста программ, существует еще несколько артефактов разработки, крайне важных для завершения жизненного цикла системы. Эти артефакты, такие как технические требования и проект, должны быть документированы, чтобы поддержать процесс разработки и сопровождения системы. Наследие разработки Разработка системы программного обеспечения не ограничивается созданием исходного кода программ. Некоторые артефакты проектирования должны обеспечивать менеджерам разработки и ее пользователям возможность оценивать прогресс разработки. Необходимо также сохранять данные о решениях, принятых на этапе анализа и проектирования, для сотрудников, которые будут осуществлять сопровождение системы. Результатами объектно-ориентированного анализа и проектирования обычно являются визуальные модели, представляемые в виде многочисленных диаграмм. К ним относятся диаграммы прецедентов, процессов, классов, конечных автоматов и компонентов. В сочетании с разумными правилами работы эти диаграммы позволяют проследить выполнение технических требований, предъявляемых к системе. Диаграммы прецедентов (вместе с их спецификациями) демонстрируют высокий уровень функциональности, определенной
Глава 7. Практические вопросы 357 техническими требованиями, а диаграммы процессов детализируют их выполнение. Диаграммы классов изображают основные абстракции, образующие словарь предметной области. Классы, обладающие сложным поведением, зависящим от состояния системы, изображаются в виде диаграмм конечных автоматов. Диаграммы последовательностей демонстрируют взаимодействие между объектами, обеспечивающими функциональные свойства системы. Диаграммы компонентов показывают, как классы образуют компоненты. Содержание документации Документация, описывающая архитектуру системы и ее реализацию, несомненно, важна, но ее составление никогда не должно превалировать над самим процессом разработки. Документация — это существенный, но вторичный продукт разработки. Необходимо помнить, что документация должна постоянно изменяться и эволюционировать вместе с поступательным развитием версий системы. Наряду с проектом и исходными текстами программ сопроводительная документация служит основой для большинства формальных и неформальных проверок. Что именно следует документировать? Очевидно, необходимо разрабатывать документацию для конечных пользователей, содержащую инструкции по инсталляции версий и работе с ними5. Кроме того, следует документировать результаты анализа, чтобы отразить семантику функциональных свойств системы в виде разнообразных сценариев. Необходимо также создавать документацию, описывающую архитектуру и реализацию системы, чтобы архитектурная концепция и детали были известны команде разработчиков, а информация обо всех стратегических решениях облегчала адаптацию и эволюцию системы. В целом, документация по архитектуре и реализации системы (не обязательно в письменном виде) должна состоять из следующих частей. • Документация по общей архитектуре системы. • Документация по главным абстракциям и механизмам архитектуры. • Документация по сценариям, иллюстрирующим основные аспекты поведения системы. Изолированные описания семантики каждого метода в каждом классе — это худший вид документации об объектно-ориентированной системе. Такой подход порождает массу бесполезных документов, которые никто не читает и которым никто не доверяет, и приводит к потере наиболее важных архитектурных сведе- 5 Существует неписаное правило, в соответствии с которым система, вынуждающая пользователя все время обращаться к инструкциям, является недружелюбной к пользователю. В частности, объектно-ориентированные пользовательские интерфейсы следует разрабатывать так, чтобы работа с ними была интуитивно понятной и самосогласованной, тем самым минимизируя или исключая необходимость в пользовательской документации.
358 Часть И. Метод ний, выходящих за рамки отдельных классов, в частности, информации о взаимодействии классов, объектов и особенно компонентов. Для документирования структуры верхнего уровня лучше всего использовать диаграммы языка UML, отсылая разработчиков к интерфейсам важнейших классов для уточнения тактических деталей. 7.7 Инструменты Практика разработки объектно-ориентированных систем изменила состав инструментов, необходимых для анализа и проектирования. Разработка сложных объектно-ориентированных систем в корне изменила ситуацию: попытка создать крупную систему программного обеспечения с минимальным набором инструментов равносильна строительству многоэтажного здания вручную. Поскольку объектно-ориентированные анализ и проектирование выдвигают на первый план ключевые абстракции и механизмы, разработчикам нужны инструменты, позволяющие сосредоточиться на более богатой семантике. Кроме того, для ускоренной разработки версий в рамках объектно-ориентированного макропроцесса, необходимы инструменты, обеспечивающие быстрый оборот цикла анализа и проектирования. Инструменты должны быть легко масштабируемыми. Инструмент, удобный для программиста, создающего небольшое приложение, не всегда подходит для производства более сложных систем. На самом деле, для каждого инструмента существует порог, за которым его возможности оказываются исчерпанными, и недостатки начинают перевешивать его достоинства. Виды инструментов Существуют три вида инструментов для объектно-ориентированного анализа и проектирования. Во-первых, средства визуального моделирования системы с помощью языка UML. Такой инструмент можно использовать на этапе анализа для описания семантики сценариев, а также на ранних стадиях проектирования, чтобы зафиксировать стратегические и тактические проектные решения и согласовать действия разработчиков. Средства визуального моделирования можно использовать на протяжении всего жизненного цикла вплоть до стадии реализации и сопровождения системы. Как показывает опыт, обратный анализ позволяет восстановить многие интересные аспекты системы, включая структуру классов и архитектуру компонентов системы. Без таких инструментов проектировщики вынуждены создавать причудливые визуальные представления проекта только для того, чтобы убедиться, что они опоздали и программисты приступили к реализации системы на основе устаревшего варианта.
Глава 7. Практические вопросы 359 Во-вторых, для разработки крупных проектов необходимы средства управления конфигурацией и контроля версий. Такие инструменты помогают проектировщикам сотрудничать друг с другом и получать доступ к общим ресурсам на протяжении всего жизненного цикла проекта. К этим ресурсам относятся все артефакты анализа и проектирования — от диаграмм прецедентов до диаграмм классов и последовательностей, демонстрирующих архитектуру системы и взаимодействие между ее компонентами. Как указывалось ранее, эти компоненты являются наиболее удобными для управления конфигурациями, особенно с точки зрения их повторного использования. В-третьих, для объектно-ориентированного анализа и проектирования необходимо средство управления библиотеками классов. Например, многие языки программирования содержат внутренние и внешние библиотеки классов. По мере развития проекта библиотека классов увеличивается за счет новых специализированных классов, предназначенных для повторного использования. За короткое время библиотека может достичь огромных размеров, затрудняя поиск классов и компонентов, необходимых разработчикам. Если стоимость (обычно завышенная) поиска конкретного компонента превышает стоимость (обычно заниженную) создания этого компонента с нуля, все надежды на его повторное использование оказываются напрасными. По этой причине необходим хоть какой-то библиотечный инструмент, позволяющий разработчикам находить классы и компоненты по заданным критериям, а также добавлять в библиотеку новые полезные классы и компоненты по мере их создания. Эти три вида инструментов часто интегрируются в одно целое. Основное предназначение интегрированных сред разработки (IDE) — создание программного окружения, объединяющего функции визуального моделирования, управления конфигурацией и контроля версий, а также поддержки библиотеки классов. Организационные выводы Потребность в мощных инструментах приводит к появлению двух специальных должностей в штате организации, занимающейся разработкой систем программного обеспечения: инженер по повторному использованию и системный программист. Среди прочего, в обязанности инженера по повторному использованию входит сопровождение библиотеки классов для проекта. Без активных усилий она может стать необозримой свалкой ненужных классов, на которую ни один из разработчиков и не взглянет. Кроме того, разработчиков часто приходится стимулировать к заимствованию существующих компонентов, а для этого библиотеку классов следует поддерживать в полном порядке. В обязанности системного программиста входит создание специализированных и настройка существующих инструментов для нужд проекта. Например, проекту может потребоваться система тестов для проверки некоторых аспектов пользовательского интерфейса или спе-
360 Часть П. Метод циализированный браузер классов. Системный программист занимает наиболее удобное положение для разработки этих инструментов, используя компоненты, помещенные в библиотеку классов. Их можно использовать не только в рамках текущего проекта, но и для создания последующих разработок. Однако в самом лучшем случае, когда в распоряжении проектировщиков находится интегрированная среда разработки, роль системного программиста становится ненужной, а обязанности управления этой средой возлагаются на системного администратора. Менеджеры, ограниченные в кадровых ресурсах, могут заявить, что мощные инструменты, а также специальные инженеры по повторному использованию и системные программисты — это непозволительная роскошь. Никто не собирается спорить, что в некоторых случаях это справедливо. Однако во многих проектах функции этих специалистов так или иначе исполняются, часто совершенно нестандартно. Для того чтобы внести в эту деятельность стандарты качества и повысить ее эффективность, увеличив ценность всего проекта, необходимо вкладывать средства в инструменты и кадры. 7.8 Специальные вопросы Некоторые вопросы заслуживают особого внимания со стороны специалистов по объектно-ориентированному анализу и проектированию. К специализированным вопросам относятся проектирование эффективных пользовательских интерфейсов и интеграция функциональных свойств, от данных до всей системы в целом. Кроме того, особое внимание следует уделить эффективной адаптации объектно-ориентированных технологий. Специализированные проблемы Некоторые предметные области заслуживают специального архитектурного исследования. Одна из них — проектирование эффективного пользовательского интерфейса, представляющее собой скорее искусство, чем науку. В этой области использование прототипов является абсолютно необходимым. Для того чтобы выявить типичные жесты, ошибочные действия и другие парадигмы взаимодействия с пользователем, нужна обратная связь. Помимо этого при анализе пользовательского интерфейса эффективным оказалось составление сценариев. В некоторых приложениях основным компонентом является база данных, в других может требоваться интеграция с базами данных, схемы которых изменить невозможно, как правило, из-за большого объема записанных в них данных (проблемы наследования данных). В таких приложениях можно непосредственно применять принцип разделения обязанностей: лучше всего инкапсулировать доступ ко всем таким базам данных в четко определенных интерфейсных классах.
Глава 7. Практические вопросы 361 Этот принцип особенно важен при смешанном использовании объектно-ориентированной декомпозиции и технологии реляционных баз данных. Рассмотрим также системы реального времени. Понятие реального времени в разных контекстах имеет разный смысл. В системах, ориентированных на пользователей, оно может означать реакцию системы в пределах одной секунды, а в системах сбора данных и управления — не более микросекунды. Важно ясно понимать, что даже в системах реального времени с жесткими ограничениями не каждую компоненту следует (или можно) оптимизировать. Действительно, во многих сложных системах наибольший риск состоит в том, что система не будет завершена вообще, а не в том, что она окажется эффективной. По этой причине не следует стремиться к преждевременной оптимизации. Необходимо сосредоточиться на разработке простой архитектуры, а узкие места сами выявятся в процессе эволюции версий системы достаточно рано для того, чтобы вовремя принять меры. Унаследованными системами называются приложения, характеризующиеся крупными капиталовложениями, от которых по экономическим причинам или по соображениям безопасности нельзя отказаться. Однако сопровождение таких систем может оказаться слишком дорогим и со временем их необходимо заменять. К счастью, копирование унаследованных систем напоминает копирование баз данных: для этого следует инкапсулировать доступ к их услугам в контексте четко определенных интерфейсных классов, а потом постепенно вытеснять их функции объектно-ориентированной архитектурой. Разумеется, архитектурная концепция должна отражать конечный результат, чтобы в процессе постепенных изменений унаследованная система не превратилась в набор заплат. Адаптация объектных технологий Стикс (Stix) и Мосли (Mosley) пишут: "По мере удовлетворения спроса сообщества специалистов по информационным системам на объектно-ориентированные технологии, необходимо решать многие проблемы теории познания... среди которых наиболее важными являются две задачи: понимание смысла объектов и понимание способов их проектирования. Более того, собранные свидетельства показывают, что программирование и проектирование — это независимые виды деятельности, которые следует изучать параллельно, чтобы эффективно реализовать и пользоваться преимуществами объектной технологии" [20]. Как научиться объектно-ориентированному проектированию? Мы рекомендуем следующее. • Обеспечить формальное обучение разработчиков и менеджеров по следующей программе. ■ Язык UML.
362 Часть И. Метод ■ Методы объектно-ориентированного анализа и проектирования, используемые в проекте. ■ Инструменты, используемые в проекте. ■ Языки и библиотеки, используемые в проекте. • Сначала использовать объектно-ориентированную технологию для создания проектов с низким уровнем риска и организовать обучение команды с помощью следующих мероприятий. ■ Подключить опытных консультантов по объектно-ориентированному анализу и проектированию. ■ По мере накопления опыта направлять участников в другие команды в качестве наставников. • Демонстрировать разработчикам и менеджерам примеры хорошо разработанных объектно-ориентированных систем. Опыт показывает, что профессиональный разработчик за несколько недель способен освоить синтаксис и семантику нового языка программирования. Для того чтобы тот же разработчик начал понимать важность и мощь классов и объектов, понадобится на несколько недель больше. Однако освоение концепции объектно- ориентированного проектирования требует совершенно иного подхода. Максим- чук (Maksimchuk) и Найбург (Naiburg) пришли к такому выводу, используя принцип Training Trap: "Изучение объектно-ориентированного языка не означает, что вы изучаете объектно-ориентированное проектирование с помощью UML" [21]. Может потребоваться более шести месяцев, чтобы разработчик стал компетентным проектировщиком классов. Это не всегда плохо — чтобы стать мастером, требуется время. Опыт показывает, что обучение на примерах часто оказывается эффективным и результативным подходом. Как только организация накопит критическую массу приложений, разработанных в объектно-ориентированном стиле, обучение новых разработчиков и менеджеров станет намного легче. Разработчики могут начинать работу в должности аналитика, а затем по мере накопления опыта в области объектно-ориентированного проектирования занять более высокое положение. Кроме того, они могут начинать как проектировщики, используя готовые хорошо определенные абстракции. Со временем, изучая эти компоненты и используя их под руководством более опытных сотрудников, разработчики сами приобретут достаточный опыт применения объектной модели и станут эффективными проектировщиками.
Глава 7. Практические вопросы 363 1.9 Преимущества и риски объектно-ориентированной разработки Преимущества объектно-ориентированной разработки известны уже много лет и являются вполне реальными. Однако если принципы объектно-ориентированного анализа и проектирования нарушаются, возникают определенные риски. Преимущества Приверженцы объектно-ориентированной технологии обычно обосновывают ее использование двумя причинами. Во-первых, они стремятся повысить свою конкурентоспособность благодаря сокращению времени на разработку, большой гибкости продукта и предсказуемости графика работ. Во-вторых, задачи, стоящие перед ними, могут быть настолько сложными, что другого выбора нет. Как указывалось в главе 2, использование объектной модели приводит к созданию систем, обладающих пятью свойствами хорошо структурированных сложных систем: иерархическая структура, относительность выбора элементарных компонентов (например, несколько уровней абстракций), разделение функций, общая структура и устойчивые промежуточные формы. Объектная модель образует концептуальную основу для системы обозначений и процесса объектно-ориентированной разработки. Таким образом, эти выгоды присущи самому методу. Кроме того, в главе 2 отмечались и преимущества, вытекающие из следующих свойств объектной модели (а значит и процесс объектно-ориентированной разработки). • Апелляция к когнитивным способностям человека. • Создание гибких систем, допускающих модификацию. • Стимулирование повторного использования программных компонент. • Уменьшение риска, связанного с разработкой. • Использование выразительной мощи объектно-ориентированных языков программирования. Изучение многочисленных примеров подкрепляет эти выводы. Особенно часто специалисты указывают на то, что объектный подход может сократить время разработки и размер исходного кода [22-24]. Риски, связанные с объектно-ориентированным проектированием Теневой стороной объектно-ориентированной технологии являются связанные с ней риски. Новаторское исследование этих рисков было проведено в статье Хантоса (Hantos), который указал, что "классические объектно-ориентированные
364 Часть П. Метод концепции Бертрана Мейера (Bertrand Meyer) превратились в список десяти основных не зависящих от методологии программирования рисков, предложенный Барри Боемом (Barry Boehm)" [25]. Анализируя работу Мейера [26], Хантос сформулировал следующий список объектно-ориентированных концепций, которые были преобразованы в список рисков Боема [25]. • Уникальный способ определения архитектуры и экземпляров структур данных. • Сокрытие информации с помощью абстракции и инкапсуляции. • Наследование, позволяющее организовывать родственные элементы. • Полиморфизм, позволяющий выполнять операции, которые можно автоматически адаптировать к типу структуры. • Специальные методы анализа и проектирования. • Объектно-ориентированные языки. • Среды разработки, облегчающие создание объектно-ориентированных систем. • Разработка по контракту — мощный метод для решения проблем, касающихся границ модулей, и проблем, связанных с интерфейсами. • Управление памятью, автоматически освобождающее неиспользуемые участки. • Распределение объектов, облегчающее создание мощных распределенных систем. • Объектные базы данных, позволяющие преодолеть границы типов данных в реляционных системах управления базами данных. С другой стороны, существует список десяти рисков, сформулированный Боемом [27], уточненный в работе [28] до восьми позиций. 1. Дефицит кадров. 2. Нереалистичные графики работ, сметы и процессы. 3. Дефицит готовых коммерческих продуктов, внешних компонентов и наследуемого программного обеспечения. 4. Недостатки архитектуры, эффективности или пользовательского интерфейса. 5. Несогласованность между требованиями к пользовательскому интерфейсу. 6. Непрерывный поток изменяющихся требований. 7. Недостатки сторонних субподрядчиков. 8. Развитие компьютерных наук.
Глава 7. Практические вопросы 365 Хантос подробно объяснил смысл каждого из указанных восьми рисков и показал, как объектно-ориентированные понятия позволяют их уменьшить или увеличить. Хантос изобразил полученные результаты в виде диаграммы отображения, из которой следует, что риски традиционной разработки программного обеспечения, указанные Боемом, характерны и для объектно-ориентированного анализа и проектирования. В качестве положительного свойства Хантос показал, что некоторые понятия объектно-ориентированного анализа и проектирования позволяют уменьшить риски, описанные Мейером. В частности, концепция "архитектуры и экземпляров" позволяет уменьшить риск, связанный с "непрерывным потоком изменяющихся требований" и "недостатками сторонних субподрядчиков". Концепция "абстракции и инкапсуляции" также позволяет уменьшить риск, связанный с "непрерывным потоком изменяющихся требований" [25]. Вспомнив объектно-ориентированные концепции, мы можем понять, как они снижают риски. Изменение требований, особенно на протяжении проектирования, может нанести ущерб проекту. Однако, сосредоточившись на логической и физической структуре (архитектуре) классов и компонентов системы, мы можем осуществить дробление структуры и функциональных свойств системы, сократив волновой эффект, порождаемый постоянно изменяющимися требованиями. Понимание потенциальных рисков, связанных с проектированием программного обеспечения, и механизмов влияния объектно-ориентированных концепций на них, позволяет разработать планы управления рисками, необходимые для успешного выполнения проекта. Резюме • Успешная разработка и внедрение сложных программных систем представляет собой нечто большее, чем просто создание программного кода. • Многие основные приемы управления разработкой программного обеспечения, например, проверки, не связаны с объектно-ориентированной технологией. • В устойчивом состоянии для выполнения объектно-ориентированных проектов требуется меньше ресурсов, а роли, необходимые для управления этими ресурсам, несколько отличаются от традиционных. • В процессе объектно-ориентированного анализа и проектирования нельзя производить интеграцию "одним махом". Структурными единицами в управлении конфигурацией для версий системы должны быть компоненты, а не отдельные классы. • Для успешного выполнения проекта необходимо повторное использование проектных решений.
366 Часть П. Метод • Скорость обнаружения ошибок и плотность ошибок являются полезными количественными показателями качества объектно-ориентированных систем. Существует также ряд других полезных количественных характеристик процесса и продукции. • Документация никогда не должна доминировать над самим процессом разработки. • Объектно-ориентированный анализ проектирования требует использования других инструментов по сравнению с традиционными методами. • Переход организации на объектно-ориентированные технологии требует изменения мировоззрения. Крайне важно, чтобы команда проектировщиков понимала принципы объектно-ориентированного анализа и проектирования. Эти процессы не сводятся к простому программированию. • Объектно-ориентированные технологии имеют много преимуществ, но связаны с многочисленными рисками. Для того чтобы осознать первое и уменьшить второе, необходимо научиться правильно управлять рисками.
ЧАСТЬ ΠΙ Приложения
Чтобы построить теорию, необходимо многое знать об основных явлениях в изучаемой области. Теорию вычислений сложно преподавать на очень высоком уровне абстракции, потому что мы еще недостаточно глубоко знаем этот предмет. И наоборот, конкретные примеры, изученные достаточно хорошо, следует объяснять очень подробно, надеясь с их помощью угадать и доказать основные принципы. Марвин Минский, "Форма и содержание в компьютерной науке" Методы — прекрасная вещь, но с точки зрения инженера-практика самая элегантная система обозначений или изощренный процесс абсолютно бесполезны, если с их помощью невозможно создать реальные системы. Предыдущие главы были лишь прелюдией к этому разделу, посвященному приложениям объектно-ориентированного анализа и проектирования в области прагматического конструирования систем программного обеспечения. Среди множества приложений мы выбрали несколько примеров, описывающих систему навигации, управления и контроля, криптоанализ, систему сбора данных, а также коммерческую Web-систему. Все они представляют собой уникальное множество задач. Применение методов объектно-ориентированного анализа и проектирования описывается путем последовательного прохода по этапам микропроцесса в каждой из пяти глав, посвященных конкретным приложениям. Таким образом, мы пройдем от начального этапа до конструирования. (Сама процедура перехода выходит за пределы тематики книги, однако в данной части будут рассмотрены некоторые интересные вопросы, возникающие после перехода.) Иначе говоря, в каждой из глав основное внимание будет уделено отдельному этапу макропроцесса, а также применению методов анализа и проектирования (т.е. микропроцесса). По нашему мнению, это намного полезнее, чем изучение конкретной проблемы от начала до конца. Каждая глава посвящена определенному аспекту проектирования, но освещает и другие аспекты, необходимые для наполнения контекста и лучшего понимания основной цели. • Глава 8 (спутниковая система навигации) посвящена системной архитектуре. • Глава 9 (система управления) посвящена анализу системных требований. • Глава 10 (криптоанализ) освещает проблемы анализа. • Глава 11 (сбор данных) описывает анализ на этапе предварительного проектирования. • Глава 12 (Web-моделирование) подробно описывает проектирование и реализацию системы.
Часть III. Приложения 369 Каждая из этих глав могла бы лечь в основу отдельной книги. По этой причине мы не стали описывать все стадии, действия и этапы процесса проектирования. Однако в этих главах рассмотрены все основные аспекты, имеющие большую важность и представляющие особый интерес. Зависимости между этапами объектно-ориентированного анализа и проектирования, а также виды конкретных диаграмм, которые следует использовать, не являются жестко заданными. Некоторые диаграммы более уместны на одном этапе и менее уместны на другом. Например, диаграммы сценариев намного чаще используются на ранних этапах жизненного цикла проекта. В то же время, некоторые диаграммы в реальных проектах используются очень редко, если используются вообще. Однако, как будет показано в следующих главах, некоторые диаграммы широко применяются на всем протяжении жизненного цикла проекта. Разница между этими диаграммами заключается в уровне абстракции. На ранних этапах проектирования диаграммы компонентов отражают очень крупные элементы (например, системы и подсистемы), а на более поздних этапах — более мелкие (например, выполняемые модули). Это последовательное уточнение уровней абстракции легко проследить на протяжении следующих пяти глав, посвященных приложениям.
ГЛАВА 8 СИСТЕМНАЯ АРХИТЕКТУРА: СПУТНИКОВАЯ СИСТЕМА НАВИГАЦИИ Принципы и процесс объектно-ориентированного анализа и проектирования, описанные в предшествующих частях книги, а также систему обозначений UML 2.0, рассмотренную в главе 5, можно с одинаковым успехом применять как для разработки высокоуровневой системной архитектуры, так и для создания программного обеспечения. Однако при разработке системной архитектуры анализ требований и декомпозиция крупной системы на компоненты требуют намного больше внимания, чем при проектировании программного обеспечения. В то же время следует помнить, что на этом уровне все рассуждения носят весьма абстрактный и крупномасштабный характер, имеют огромное значение для всего проекта и пренебрегают технологическими деталями. Если проектировщики хорошо понимают это и предпринимают правильные шаги при разработке архитектуры, то вероятность создания надежной и долговечной системы повышается, поскольку такая система обеспечивает качественное управление, поддержку и расширение. В главе описывается процесс разработки системной архитектуры для гипотетической системы спутниковой навигации (Satellite Navigation System — SNS) путем ее логического разбиения на функциональные блоки. Для того чтобы не загромождать изложение ненужными деталями, описание ограничено лишь первыми двумя уровнями архитектуры, на которых определяются основные сегменты и подсистемы соответственно. Таким образом, в главе описываются не все, а лишь наиболее важные этапы процесса разработки системной архитектуры. Для более полного описания всех сегментов и их подсистем пришлось бы написать отдельную книгу. Однако описываемый подход можно применять на любом уровне архитектуры (например, при уточнении структуры сегмента или подсистемы) системы спутниковой навигации.
Глава 8. Системная архитектура: спутниковая система навигации 371 Мы выбрали эту область приложения потому, что она является намного более технически сложной и интересной, чем любая простая система, изобретенная для иллюстрации. В настоящее время существуют две реальные системы спутниковой навигации — американская Система глобального позиционирования (Global Positioning System (GPS) и российская Глобальная навигационная спутниковая система (Global Navigation Satellite System — GLONASS). Кроме того, в настоящее время Европейский Союз разрабатывает третью систему — Galileo. 8.1 Начало Первые этапы разработки системной архитектуры по существу относятся к области системотехники, а не проектирования программного обеспечения, даже если речь идет о создании чисто программных систем. Международный совет по системотехнике (International Council on System Engineering — INCOSE) полагает, что системотехника — это "междисциплинарный подход и средства для создания успешных систем" [1]. Кроме того, в соответствии с определением совета INCOSE под системной архитектурой подразумевается "систематизация элементов и подсистем, а также распределение среди них функций, необходимых для удовлетворения системных требований" [2]. На этом этапе основная задача состоит в том, чтобы определить, что именно необходимо создать, выяснив границы предметной области, сформулировав сцена- рии выполнения задания (mission use case) и определив подмножество сценариев использования системы (system use case) с помощью анализа одного из сценариев выполнения задания. В рамках этого процесса разрабатываются сценарии использования системы путем анализа ее функциональных требований и документируются нефункциональные требования и ограничения. Прежде чем перейти к анализу требований, опишем глоабльную систему позиционирования. Требования, предъявляемые к спутниковой системе навигации Процесс создания системы, предназначенной для решения конкретной проблемы, начинается с определения того, что именно необходимо сконструировать. На первом этапе используется любая документация, описывающая проблему или потребности пользователей. В данном случае нам известна концепция системы и связанные с нею высокоуровневые требования и ограничения.
372 Часть III. Приложения Введение в глобальную систему позиционирования Глобальная система позиционирования (GPS) позволяет любому человеку, имеющему приемное устройство GPS, определять свои координаты на Земле независимо от местоположения, времени дня или погоды1. Спутники, входящие в систему GPS, находятся на орбите на высоте более 11 000 морских миль над Землей и управляются группой наземных станций слежения, расположенных по всему миру. За время, прошедшее от первого запуска спутника системы GPS в 1978 году до 24-го запуска в 1994 году, завершившего ее создание, она стала надежной опорой для навигации по всему миру [3]. Методы навигации постоянно совершенствуются — начиная с первых способов ориентации на местности, изобретенных первобытными людьми, и заканчивая технологически совершенной системой GPS. В ходе этой эволюции люди использовали карты Земли и звезд, компасы, секстанты, хронометры и системы наземных радиостанций, такие как LORAN (long-range navigation) [4]. Архитектура системы GPS состоит из трех сегментов: управление, пользователи и космос. Сегмент управления (Control Segment) состоит из шести наземных станций с центральным пунктом управления, расположенным на авиабазе Шривер (Schiever) в штате Колорадо. Приемные устройства, помогающие людям ориентироваться на местности, образуют сегмент пользователей (User Segment), в который приходит информация от 24 космических спутников, образующих космический сегмент (Space Segment) [5]. Приемные устройства системы GPS вычисляют расстояние до спутников, используя поступающую от них информацию о времени и координатах. В частности, "если известно точное расстояние до спутника, находящегося в космосе, мы знаем, что находимся где-то на воображаемой сфере, радиус которой равен расстоянию до спутника, а центр расположен в месте положения спутника. Если известны точные расстояния от двух спутников, мы знаем, что находимся в точке пересечения двух сфер. Если известны расстояния от третьего или четвертого спутников, мы можем точно определить свои координаты на Земле. Приемное устройство GPS обрабатывает данные, полученные от спутников, и вычисляет свои координаты" [6]. Система глобального позиционирования широко используется как военными, так и гражданскими. Военные используют систему GPS для навигации на Земле, на море и в воздухе. Кроме того, она применяется в системах вооружений, например, в системах наведения крылатых ракет. Одновременно система GPS позволила спасти много человеческих жизней среди гражданских лиц. В частности, система GPS позволяет оказывать скорую помощь лицам, попавшим в беду. Она использовалась в ходе строительства туннеля под Ла-Маншем, чтобы координировать работу двух команд, пробивавшихся навстречу друг другу со стороны Великобритании источником этой информации является книга GPS Primer — A Student Guide to the Global Positioning System, выпущенная корпорацией Aerospace. Дополнительную информацию о системе GPS можно найти в летнем выпуске журнала Crosslink за 2002 год, издаваемого корпорацией Aerospace.
Глава 8. Системная архитектура: спутниковая система навигации 373 и Франции, чтобы встретиться на середине. Кроме того, система GPS используется даже в быту, например, в системах навигации автомобилей, спорте (геокэшин- ге)2и туризме [7]. Концепция: • Предоставлять заказчикам эффективные и доступные услуги системы SNS (Satellite Navigation System). Функциональные требования: • Предоставлять услуги SNS. • Управлять системой SNS. • Поддерживать работу системы SNS. Нефункциональные требования: • Высокий уровень надежности, обеспечивающий адекватное гарантийное обслуживание. • Достаточная точность, удовлетворяющая текущие и будущие потребности пользователей. • Резервирование критических функциональных возможностей системы. • Широкая автоматизация, минимизирующая операционные издержки. • Легкость сопровождения, снижающая стоимость поддержки. • Возможность расширения функциональных возможностей системы. • Продолжительное обслуживание, особенно элементов, расположенных в космосе. Ограничения: • Соответствие международным стандартам. • Максимальное использование коммерческого аппаратного и программного обеспечения (commercial-off-the-shelf — COTS). Очевидно, что эти ограничения носят весьма упрощенный характер и определяют лишь самые главные свойства спутниковой системы навигации. На практике более подробные ограничения формулируются только после того, как будет доказана жизнеспособность предложенного решения, а на анализ будут затрачены официальный Web-сайт Cache Hunt Site системы GPS, предназначенный для геокэшинга, расположен по адресу www. geocaching, com. (Геокэшинг — это игра, смысл которой заключается в том, что один из игроков прячет "клад" в тайник и указывает его координаты на сайте, а остальные игроки должны найти этот "клад", используя приемники GPS. — Прим. ред.).
374 Часть III. Приложения сотни человеко-часов при участии многочисленных экспертов в предметной области и клиентов системы. Окончательные требования, предъявляемые к крупной системе, могут быть изложены на тысячах страниц документации (желательно, с помощью визуальных моделей). Они описывают не только общие функциональные свойства системы, но и сложные детали, такие как эскизы экранов, используемых для взаимодействия человека и компьютеров. Определение границ задачи Несмотря на свою краткость, приведенный список требований и ограничений позволяет выполнить первый этап разработки системной архитектуры спутниковой системы навигации, т.е. определить ее контекст, показанный на рис. 8.1. Эта диаграмма контекста позволяет понять окружающую среду, в которой должна функционировать система SNS. К действующим лицам, представляющим собой внешние сущности, взаимодействующие с системой, относятся люди, другие системы, предоставляющие услуги, а также реальное окружение. Стрелки зависимостей показывают, какие внешние сущности зависят от системы SNS и от каких сущностей зависит сама система. usecase SatelliteNavigationSystemContext χ Ч Operator Л SatelliteNavigationSystem > ExternalCommunications Рис. 8.1. Диаграмма контекста спутниковой системы навигации Совершенно очевидно, что действующие лица User (Пользователь), Operator (Оператор) и Maintainer (Эксплуатационник) зависят от системы SNS,
Глава 8. Системная архитектура: спутниковая система навигации 375 поскольку они используют полученную от нее информацию, перерабатывают ее и хранят соответственно. Несмотря на то что система SNS сможет генерировать свою собственную энергию, чтобы обеспечивать работу наземных станций слежения, основные услуги по поставке энергии будут предоставляться внешней системой, роль которой играет действующее лицо ExternalPower (Внешний источник энергии). Аналогично, на диаграмме показано действующее лицо ExternalCommunicator (Внешний источник связи), предоставляющее платные услуги связи с системой SNS, в некоторых сценариях — как основной канал связи, а в других — для обмена информацией внутри системы. Для того чтобы отделить эти элементы системы от внутренних компонентов, к их именам приписывается префикс External. Оставшееся действующее лицо Atmosphere /Space (Атмосфера/Космос) выглядит довольно странным, если не учитывать, что оно является проводящей средой для связи между наземными службами и спутниками, расположенными в космосе. Следовательно, это действующее лицо предоставляет услуги. Его состояние определенно влияет на качество связи. С другой стороны, это действующее лицо можно рассматривать с точки зрения согласованности с международными стандартами. Работа спутников регламентируется многочисленными национальными и международными регулирующими правилами и договорами. Следовательно, при описании этого действующего лица необходимо учитывать столь важные обстоятельства. Чрезвычайно важным свойством этой диаграммы контекста являются реальные границы системы, т.е. указание, какие элементы расположены внутри системы, а какие — вне системы. Может возникнуть вопрос: почему действующие лица Operator и Maintainer размещены за пределами пакета SatelliteNa- vigationSystem (Система навигации спутника)? Это сделано в соответствии с точкой зрения заказчика, считающего, что эта система предназначена для поставки информации пользователю. Заказчик рассматривает корпорацию, в рамках которой действует система SNS, извне, в то время как действующее лицо User (Пользователь) может считать действующие лица Operator и Maintainer внутренними компонентами системы. Очевидно, что выбор точки зрения в этом вопросе является ключевым. Например, если мы сдаем готовую к эксплуатации систему, включающую в себя службы обработки и хранения информации, то действующие лица Operator и Maintainer следует разместить внутри пакета SatelliteNavigationSystem. Существует множество способов представления диаграмм контекста, как очень простые, так и крайне сложные. Чем сложнее диаграмма, тем более подробные сведения о потоках информации между действующими лицами и системой она содержит. Если система разрабатывается в зрелой окружающей среде, например, для замены существующей версии, то этот тип информации на протяжении разработки известен заранее, что позволяет проектировщикам изображать ее на диаграмме.
376 Часть III. Приложения Детали проекта важны намного меньше, чем выбор стиля, его документирование и последовательность в действиях команды проектировщиков, обеспечивающие ясность и понятность процесса разработки. Однако мы предпочитаем использовать диаграммы контекста, поскольку они представляют собой простое и ясное средство изображения высокоуровневой концепции системы, охватывающей ее функциональные компоненты, взаимодействующие с внешней средой. В ходе этого взаимодействия система предоставляет услуги одним сущностям и получает услуги от других. Это обстоятельство имеет большое значение на начальном этапе проекта. Кроме функциональных требований, проектировщики сталкиваются с нефункциональными ограничениями, относящимися к функциональным свойствам или к системе в целом. Эти нефункциональные требования касаются надежности, точности, резервирования, автоматизации, расширяемости и продолжительности работы. Кроме того, существует еще ряд ограничений, которые следует учитывать при разработке системы SNS. Нефункциональные требования и ограничения фиксируются в текстовом документе, который называется дополнительной спецификацией (supplementary specification). Наряду с нефункциональными ограничениями этот документ также содержит функциональные требования, относящиеся к нескольким сценариям использования. Вторым важным документом является глоссарий (glossary). С его помощью участники разработки согласовывают определения основных понятий и способы их использования. Даже из этого сокращенного списка ограничений можно сделать два вывода о процессе разработки системы SNS. 1. Архитектура должна допускать развитие во времени. 2. Реализация должна как можно больше основываться на существующих стандартах. Очевидно, что в одной главе невозможно провести полный анализ или проектирование спутниковой системы навигации (и даже ее архитектуры). Поскольку нашей целью является исследование возможностей масштабирования используемой системы обозначений и процесса проектирования для разработки системной архитектуры, мы сосредоточимся на проблеме проектирования архитектуры первого и второго уровня, на которых определяются сегменты и подсистемы соответственно. Мы разработаем эти уровни архитектуры с помощью логического распределения требуемых функциональных свойств, используемых действующим лицом Operator. Как указывалось во введении к главе, мы ограничимся лишь некоторыми наиболее типичными этапами процесса разработки и артефактами. После анализа концепции и требований, команда архитекторов неизбежно придет к выводу, что функциональные требования, предъявляемые к системе, на самом деле представляют собой контейнеры {пакеты в терминологии языка UML), содержащие многочисленные сценарии использования на уровне выполнения за-
Глава 8. Системная архитектура: спутниковая система навигации 377 дания, определяющие функциональные свойства системы SNS. Эти пакеты сценариев выполнения задания образуют высокоуровневый функциональный контекст системы SNS, показанный на рис. 8.2. Эти пакеты содержат сценарии выполнения заданий, демонстрирующие способ, с помощью которого пользователи, операторы и сопровождающий персонал системы SNS взаимодействуют с системой для решения своих задач. Поскольку мы применяем методы объектно-ориентированного анализа и проектирования, а также язык UML 2.0 для разработки системы, а не программного обеспечения, обозначения, использованные на рис. 8.2, могут показаться незнакомыми, однако они ясно представляют требуемую информацию и облегчают понимание материала. >г ΐ> ΐ> :> SatelliteNavigationSystem ReceiveSNSServices ( e OperatoSNS ( [ MiesionUseCases 1 MaintainSNS | [ MiesionUseCases j Рис. 8.2. Пакеты сценариев выполнения задания с помощью системы SNS Формулировка прецедентов выполнения заданий Концепция системы выглядит довольно расплывчато: "Предоставлять заказчикам эффективные и доступные услуги системы SNS". Следовательно, задача архитектора требует разумного упрощения задачи, чтобы она стала разрешимой. Задача, подобная сформулированной выше, может легко стать жертвой аналитического паралича, поэтому мы сосредоточим основное внимание на предоставлении χ χ
378 Часть III. Приложения навигационных услуг, которые используются чаще всего, вместо того, чтобы рассматривать варианты, в которых система может делать что угодно для кого угодно (что представляется нам совершенно бесполезным). Начнем с разработки прецедентов выполнения заданий в системе SNS. Крупные проекты, как правило, организовываются небольшими коллективами проектировщиков, расположенных в штаб-квартире и ответственных за общую системную архитектуру, в то время как реальная разработка осуществляется другими компаниями на основе субподряда или другими отделами той же самой компании. На этапе анализа системные архитекторы обычно держат в уме определенную концептуальную модель, состоящую из элементов реализации. Опыт создания, управления и поддержки спутниковых систем навигации показывает, что высокоуровневая логическая архитектура такой системы должна состоять из четырех сегментов: Ground Segment (Наземные Службы), Launch Segment (Космодром), Satellite Segment (Спутник) и User Segment (Пользователь). На это можно возразить, что такое разделение относится скорее к проектированию, а не к анализу. Однако спутник должен запускаться на орбиту из определенного места. На самом деле, довольно трудно однозначно определить, что именно отражает логическая архитектурная схема: ограничения системы или ее структуру. Как бы то ни было, несомненно, что системная архитектура на этой стадии разработки в принципе является объектно-ориентированной. Например, архитектура показывает, что основные функции системы выполняют такие сложные объекты, как Ground Segment и Satellite Segment. Это полностью соответствует принципам, изложенным в главе 4: в крупной системе объекты, находящиеся на высоком уровне абстракции, образуют кластеры по функциональному признаку. Идентификация и уточнение этих объектов в ходе анализа мало отличается от аналогичных действий на этапе проектирования. Еще до создания концептуальной структуры в виде диаграммы пакетов, аналогичной показанной на рис. 8.3, можно попросить экспертов в предметной области сформулировать основные сценарии выполнения заданий, уточняющие желательное поведение системы. Слова "еще до" означают, что, даже не представляя себе архитектуру системы SNS, разработчики должны начинать анализ по принципу "черного ящика", не связанного с архитектурными ограничениями. Иначе говоря, анализ функциональных требований нацелен на создание сценариев выполнения заданий, которые должны относиться ко всей системе SNS в целом, а не к ее компонентам по отдельности. Затем эти сценарии распределяются по компонентам и содержимое "черного ящика" становится известным. В своей книге Unified Modeling Language Reference Manual Рамбо (Rumbaugh), Джекобсон (Jacobson) и Буч (Booch) утверждают: "Диаграмма деятельности (activity diagram) помогает понять поведение системы на высоком уровне абстракции, не вникая в детали передачи сообщений, необходимые для диаграмм взаимо-
Глава 8. Системная архитектура: спутниковая система навигации 379 I LaunchSegment t. I SatelliteSegment | JL GroundSegment & Τ UserSegment Рис. 8.3. Логическая архитектура системы SNS действия (collaboration diagrams)" [8]3. Следовательно, диаграммы деятельности являются основным инструментом анализа сценариев выполнения заданий и иллюстрации ожидаемого поведения системы. Некоторые коллективы разработчиков для этой цели используют диаграммы последовательностей или диаграммы коммуникации, но мы считаем, что эти диаграммы более удобны для проектирования на более низких уровнях архитектурной иерархии. В нашем анализе основное внимание будет уделено успешным сценариям выполнения заданий, а многочисленные альтернативные сценарии будут отложены на другое время. Термин успешный сценарий может показаться незнакомым. Поясним его смысл на банальном примере банкомата. Одним из вариантов использования банкомата является сценарий Withdraw Cash (Снятие наличных). Он описывает именно то, что мы обычно ожидаем от таких машин. В этом сценарии пользователь взаимодействует с банкоматом, проходя несколько этапов: вставляет карточку, вводит PIN-код, указывает сумму изъятия, выбирает счет и т.д. Ни одно из этих действий не приводит к конечной цели (снятию наличных денег со счета), поэтому они не могут считаться настоящими вариантами использования банкомата. Сценарий Withdraw Cash (как и все варианты использования) состоит из многих сценариев, каждый из которых использует разные функциональные свойства банкомата. Рассмотрим сначала успешный сценарий снятия денег со счета. Этот сценарий называется первичным (primary scenario). Альтернативные, или вторичные сценарии относятся к ситуациям, которые ответвляются от основного сценария. Например, вернемся к сценарию Withdraw Cash и рассмотрим пункт, в котором пользователь указывает сумму денег, снимаемых со счета. Предположим, что в ответ банкомат сообщает о превышении дневного лимита и требует, чтобы пользователь В языке UML 2.0 диаграмма взаимодействия называется диаграммой коммуникации (communication diagram).
380 Часть III. Приложения указал другую сумму (меньше предыдущей). Эта последовательность действий является типичным примером вторичного сценария. Несколько его первых шагов совпадают с этапами первичного сценария (успешно), но потом происходит ответвление, связанное с превышением дневного лимита, и последующий возврат в русло первичного сценария. Надеемся, этот пример поясняет ситуацию. Однако в системах реального времени, таких как спутниковая система навигации, большинство функциональных свойств встроено во вторичные сценарии. Их можно рассматривать как подводную часть айсберга, но тем не менее они чрезвычайно важны для полноценного и безопасного функционирования системы. Иначе говоря, вторичные сценарии являются скрытыми в том смысле, что им уделяется намного меньше внимания, хотя они могут нанести системе значительный ущерб, так же как подводная часть айсберга может потопить корабль. Следовательно, анализ системы должен включать в себя изучение вторичных сценариев. Объем функциональных свойств системы, описанных во вторичных сценариях, колеблется, но имеет большое значение для всей системы. Хотя из-за недостатка места эти сценарии не будут рассмотрены, следует помнить, что в реальном проекте это необходимо сделать. Итак, вернемся к поставленной задаче и сформулируем сценарии выполнения заданий для пакета OperateSNS. Основываясь на анализе операций в системе SNS, можно предложить следующие четыре сценария выполнения заданий. • Initialize Operations (Инициализация операций) • Provide Normal Operations (выполнение рутинных операций) • Provide Special Operations (Выполнение особых операций) • Terminate Operations (Прекращение операций) Спецификации этих сценариев выполнения заданий зависят в основном от предметной экспертизы, осуществленной коллективом разработчиков. Коме прошлого опыта ценными инструментами в процессе анализа являются методы моделирования и прототипы. Тем не менее, для проведения анализа мы предпочитаем моделировать диаграммы деятельности, описанные в следующем подразделе. Результаты разработки сценариев выполнения заданий для пакета OperateSNS (Работа системы SNS) представлены на рис. 8.4. В оставшейся части главы в центре внимания будет находиться сценарий выполнения заданий Initialize Operations, предназначенный для определения действий, которые должны быть выполнены, чтобы инициализировать операцию системы SNS по запросу оператора. Определение сценариев использования системы Итак, для определения инкапсулированных сценариев использования системы мы разработали диаграмму деятельности, описывающую сценарий выполнения заданий Initialize Operations. Разрабатывая эту диаграмму, мы не
Глава 8. Системная архитектура: спутниковая система навигации 381 Operator Maintainor Рис. 8.4. Уточнение сценария выполнения заданий для пакета OperateSNS пытались использовать знания о сегментах, из которых состоит система SNS (см. рис. 8.3). Мы приняли этот подход, чтобы не ограничивать анализ операций системы SNS предположениями об ее архитектуре. На этом этапе мы рассматриваем систему как "черный ящик", в который заглядывать не следует, и сосредоточиваем внимание лишь на услугах, которые она оказывает, и способах, с помощью которых она это делает. Нас интересует поток управления между оператором и системой SNS, поскольку мы анализируем поведение системы лишь на высоком уровне. Поскольку нас интересуют действия, выполняемые системой SNS, а не сообщения, представленные на диаграммах коммуникации или последовательностей, диаграмма деятельности относительно проста. Если же необходимо определить действия всей системы SNS, то следует разработать диаграмму деятельности, основанную на всех сценариях выполнения заданий, и выявить громадное количество действий, которые система SNS должна выполнить, чтобы удовлетворить потребности пользователя. Попробуйте представить себе все действия, которые система должна выполнять 24 часа в сутки! Однако мы ограничимся сценарием
382 Часть III. Приложения выполнения заданий Initialize Operations, которому соответствует диаграмма, представленная на рис. 8.5. Рис. 8.5. Диаграмма деятельности для пакета Initialize Operations, построенная по принципу "черного ящика" На основе этой диаграммы деятельности и выводов опытных системотехников был разработан список сценариев использования системы. Например, мы решили объединить действия Подготовить к запуску и Запустить в рамках одного сценария Запустить спутник. Мы пришли к выводу, что остальные действия охватывают важные функциональные свойства системы и, следовательно, должны
Глава 8. Системная архитектура: спутниковая система навигации 383 быть представлены отдельными сценариями использования. Эти сценарии перечислены в табл. 8.1. Таблица 8.1. Сценарии использования системы для пакета Initialize Operations Сценарий использования Описание системы Launch Satellite (Запуск спутника) Fly to Separation Point (Полет в точку отделения) Activate Satellite (Активация спутника) Separate Satellite (Отделение спутника) Move Satellite into Orbit (Вывод спутника на орбиту) Perform Satellite Checkout (Проверка спутника) Prepare to Operations (Подготовка к работе) Transmit Initial Position Information (Передача информации о первоначальном положении) Сценарии использования системы для пакета Initialize Operations представлены на рис. 8.6. На нем изображен пакет Initialize Operations, содержащий сценарии выполнения заданий. Остальные три сценария выполнения заданий, охватывающие функциональные свойства системы SNS, показаны с ключевыми словами "mission use case". Такой подход представляется ясным и полезным. Однако каждый коллектив разработчиков может использовать свой собственный метод определения и документирования действий системы. 8.2 Разработка Перейдем к системной архитектуре, образующей основу для выполнения требований, которые содержатся в сценариях использования системы, разработанных в предыдущем разделе. В первых двух подразделах рассматриваются два вопроса, Подготовить ракету-носитель и спутник, а затем выполнить запуск. Направить ракету-носитель в точку отделения спутника. Для этого необходимо выполнить ряд операций. Активизировать спутник и подготовить его к отделению от ракеты-носителя. Отделить спутник от ракеты-носителя. Использовать двигатели спутника для его вывода на правильную орбиту. Провести орбитальную проверку работы спутника. Провести завершающую подготовку к работе на орбите. Перейти в рабочий режим и передать информацию о первоначальном положении пользователям системы SNS.
384 Часть III. Приложе I ReceiveSNSServices j OperateSNS L. I InitializeOperatiorw 1 Operator Рис. 8.6. Сценарий использования системы Initialize Operations
Глава 8. Системная архитектура: спутниковая система навигации 385 касающиеся архитектуры: способы разработки хорошей архитектуры и действия, которые следует выполнить при этом. В двух следующих разделах ("Обоснование предложенной системной архитектуры" и "Распределение нефункциональных требований и определение интерфейсов") описан процесс анализа системной архитектуры SNS на макроуровне. Наша цель — обосновать предложенную системную архитектуру до перехода на этап анализа сегментов и определения архитектуры взаимодействующих подсистем. На этом этапе используются методы анализа сценариев использования, описанные ранее, но все сценарии анализируются в совокупности, а не по отдельности. Это упрощение вполне допустимо на стадии разработки прототипов поведения, но не приемлемо при реальном распределении функциональных свойств системы среди индивидуальных сегментов. После завершения разработки прототипов поведения системы в следующих разделах обосновывается архитектура системы SNS и описывается их размещение. В этих разделах возобновляется анализ реальной системной архитектуры с целью ее декомпозиции на отдельные сегменты и подсистемы. Разработка хорошей архитектуры Как указывалось в главе 6, существует много методов разработки архитектуры системы. Некоторые из них весьма элегантны, а некоторые, в сожалению, совершенно глупые. Как же отличить хорошую архитектуру от плохой? Хорошая архитектура, как правило, имеет объектно-ориентированные свойства. Очевидно, это не означает, что применение объектно-ориентированных методов автоматически порождает хорошую архитектуру. Однако, как указано в главах 1 и 2, применение принципов объектно-ориентированной декомпозиции обычно позволяет обеспечить желательные свойства организованной сложности. Хорошая архитектура, неважно, системы или программного обеспечения, обычно характеризуется определенными атрибутами. • Хорошая архитектура состоит из четко определенных уровней абстракции, обеспечиваемых точно определенными и управляемыми интерфейсами, и конструируется на основе хорошо определенных и управляемых свойств на нижних уровнях абстракции. • Хорошая архитектура обеспечивает четкое разделение между интерфейсом и реализацией на каждом уровне абстракции, открывая возможности изменять реализацию любого слоя без нарушения предположений клиентов. • Хорошая архитектура отличается простотой: общие функциональные свойства достигаются с помощью общих абстракций и общих механизмов. Простой (или непростой) разработки хорошей архитектуры спутниковой системы навигации недостаточно. Необходимо ознакомить с этой архитектурой всех
386 Часть III. Приложения участников проекта. Проблемы, связанные с этим процессом, описаны в следующей врезке. Описание архитектуры Во врезке "Документирование архитектуры программного обеспечения", помещенной в главе 6, объяснялось, почему документирование архитектуры системы так важно для архитекторов и других участников проекта. Кроме того, там рассмотрен стандарт IEEE Standard 1471-2000, рекомендации IEEE Recommended Practice for Architectural Description of Software-Intensive Systems, а также архитектурная модель 4+1, предложенная Кручтеном (Kruchten) и состоящая из пяти проекций архитектуры программного обеспечения: проекции сценариев (Use Case View), логической проекции (Logical View), проекции реализации (Implementation View), проекции процессов (Process View) и проекции развертывания (Deployment View). Как указывают Майер (Maier), Эмери (Emery) и Хиллиард (Hilliard) [9], несмотря на то что стандарт IEEE Standard 1471-2000 посвящен системной архитектуре, "он в одинаковой степени применим для описания любой системы, а значит, позволяет описывать любую системную архитектуру". Кроме того, эти исследователи считают, что "чрезвычайно важным применением стандарта ANSI/IEEE 1471-2000 в системотехнике может стать согласованность и гармонизация разнообразных архитектурных концепций, быстро получающих популярность" [10]. Затем авторы сравнивают между собой наиболее популярные архитектурные модели: 4+1, ISO RM-ODP, DoDAF и Zachman. Аналогично, по мнению Крикоряна (Krikorian), представившего публике работу Augmented 4+1 views, модель 4+1, предложенная Кручтеном, также можно применять в системотехнике. В частности, Крикорян проанализировал модель Кручтена с точки зрения системотехники, указав подходящие действия и артефакты [11]. Определение действий, связанных с разработкой архитектуры Микропроцесс анализа и проектирования, описанный в главе 6, предусматривает определенную совокупность действий, выполняемых на каждом уровне абстракции в системе. Каждое действие, в свою очередь, определяет следующие задачи по разработке системы, необходимые для создания архитектуры системы SNS: • Идентифицировать архитектурные элементы на заданном уровне абстракции, чтобы определить границы задачи и приступить к объектно-ориентированной декомпозиции. • Идентифицировать семантику элементов, т.е. установить их поведение и атрибуты.
Глава 8. Системная архитектура: спутниковая система навигации 387 • Идентифицировать отношения между элементами, чтобы уточнить их границы и элементы, с которыми они взаимодействуют. • Определить интерфейсы элементов, а затем уточнить их для анализа на следующем уровне абстракции. Эта совокупность действий позволяет понять, что основной задачей при разработке архитектуры системы SNS является определение ее элементов (сегментов и подсистем), а также их обязанностей, взаимодействий и интерфейсов. В результате архитектор получает в свое распоряжение среду разработки, позволяющую разрабатывать и исследовать архитектурные схемы. Следует помнить, что эти действия, как правило, выполняются параллельно, а не последовательно. Например, идентификация отношений между элементами может помочь лучше определить поведение и атрибуты системы. В следующих подразделах мы определим сегменты спутниковой системы навигации, их функциональные свойства, взаимодействия между ними, а также интерфейсы. Обоснование предложенной системной архитектуры Желательно, чтобы архитектор системы имел возможность экспериментировать с альтернативными декомпозициями системы, чтобы заказчики были уверены в обоснованности принятых решений. Для этого можно широко использовать разработку моделей, математическое моделирование или создание прототипов. Эти модели, методы и прототипы впоследствии по мере развития системы могут использоваться для регрессионного тестирования. В этом и последующем разделах описывается анализ архитектуры системы SNS на макроуровне. Это позволяет обосновать сделанные предположения и решения, прежде чем двигаться дальше. Следует убедиться, что любая проблема, связанная с архитектурой, будет выявлена на ранних, а не на поздних стадиях анализа и проектирования — чем раньше будут внесены изменения в технические требования, тем легче их учесть в процессе разработки системы. Это относится и к изменениям архитектурных решений. В центре нашего внимания будут находиться функциональные свойства пакета Initialize Operations, поскольку именно этот пакет изучался в предыдущих разделах. Следует сделать одно предостережение: несмотря на простоту методов, применяющихся в этом и следующих разделах для разработки архитектуры системы, в данном разделе они будут использоваться совершенно иначе. Мы очень быстро "пробурим" несколько архитектурных уровней, чтобы сосредоточиться на более широких аспектах системы по сравнению со сценарием использования системы Initialize Operations. Модели, которые будут использоваться в этом разделе, непригодны для создания реальной системной архитектуры. Слишком часто первоначальные архитектурные решения оказываются необоснованными, поскольку коллективы архитекторов плохо понимают смысл этой ста-
388 Часть III. Приложения дии или торопятся приступить к проектированию. Как правило, в этих ситуациях они немедленно переходят к декомпозиции сценариев использования системы, перепоручая разработку сценариев использования сегментов другим группам. Затем команды, разрабатывающие архитектуру сегментов, повторяют этот процесс, идентифицируя сценарии использования подсистем. В итоге архитекторы могут столкнуться с необходимостью воссоединения сценариев использования, находящихся на разных архитектурных уровнях, чтобы выяснить, правильно ли взаимодействуют элементы на каждом уровне архитектуры. К сожалению, слишком поздно! Любые исправления на поздних стадиях анализа и проектирования связаны с большими трудностями, а также затратами времени и денег. Вот почему проведение анализа на макроуровне до разработки сценариев использования сегментов намного предпочтительнее. Это же относится и к коллективам архитекторов, разрабатывающих сегменты по отношению к сценариям использования подсистем. На первом этапе нужно оценить результаты, полученные на предыдущих этапах, определить, в какой точке процесса мы находимся, и разработать план дальнейших действий. Вместе с экспертами в предметной области мы оценим логическую архитектуру системы SNS (см. рис. 8.3) и разработаем диаграмму действий для сценария использования пакета Initialize Operations (см. рис. 8.5), придерживаясь как функциональной, так и нефункциональной точек зрения. Мы считаем, что функциональные свойства системы отражены правильно, но не уверены в некоторых нефункциональных требованиях. Среди требований есть условие, что система SNS должна обеспечивать резервирование критически важных функциональных возможностей. На данном уровне системной архитектуры производится расслоение структуры сегментов, но не проектируется их внутренняя архитектура. Таким образом, мы должны обеспечить резервирование на уровне сегментов. Для того чтобы удовлетворить требование резервирования функциональных свойств, мы приняли два стратегических решения, касающихся системной архитектуры. Во-первых, мы решили установить резервные аппаратные средства, дублирующие основное оборудование в наземном сегменте. Эта аппаратура будет работать в режиме замены непосредственно в процессе работы (hot-swappable mode), когда и основное, и дублирующее оборудование работают в параллельном режиме. Если основное оборудование выйдет из строя, то его можно будет быстро заменить. Во-вторых, аналогичный подход будет использоваться для резервирования оборудования, установленного на космодроме. В спутниковом сегменте резервирование функциональных свойств обеспечивается многочисленными спутниками, как находящимися на орбите, так и готовящимися к запуску. Все это будет дополнять резервирование функциональных свойств каждого спутника, которое разработчики должны обеспечить, выполняя нефункциональные требования, касающиеся системы SNS. В пользовательском сегменте резервирование
Глава 8. Системная архитектура: спутниковая система навигации 389 функциональных свойств поддерживается возможностью замены всего сегмента. Как и в предыдущем случае, разработчики пользовательского сегмента должны сосредоточить свое внимание на его внутренних резервах. Как показано на диаграмме деятельности пакета Initialize Operations, изображенной на рис. 8.5 и построенной по принципу "черного ящика", функциональные свойства системы SatelliteNavigationSystem распределены по четырем сегментам: Ground Segment (Наземные Службы), Launch Segment (Космодром), Satellite Segment (Спутник) и User Segment (Пользователь). Наша цель — распределить сценарии использования сегментов, выделенные из сценариев использования системы, по конкретным сегментам. Таким образом, функциональные свойства всей системы SNS будут обеспечиваться с помощью взаимодействия между сегментами. Если сценарии использования сегментов будут определены правильно, то каждый сегмент будет полностью соответствовать следующим объектно-ориентированным принципам. • Абстракция. С точки зрения стороннего наблюдателя сегменты имеют четко очерченные границы. • Инкапсуляция. Сегменты подразделяются на подсистемы, образующие их структуру и обеспечивающие их поведение. Сегменты непрозрачны для других сегментов. • Модульность. Сегменты состоят из совокупности связных и слабо связанных между собой подсистем. • Иерархия. Сегменты представляют собой упорядоченные или ранжированные абстракции. Для систем, сложность которых сравнима со сложностью системы SNS, этот этап анализа может длиться несколько месяцев, пока не будет достигнут достаточный уровень детализации4. Это одна из причин, по которой настоятельно рекомендуется обосновывать архитектурные решения, используя быстрые и приближенные оценки предложенной концепции (например, с помощью создания моделей и прототипов), чтобы убедиться в том, что вы находитесь на правильном пути. Команда архитекторов не должна стремиться к созданию исчерпывающего списка сценариев использования системы (на это нет времени). Ей следует сосредоточить свое внимание лишь на основных вариантах, имеющих значение для архитектуры системы. Анализируя действия, изображенные на рис. 8.5, мы должны непрерывно задавать себе множество вопросов. Какой сегмент (или сегменты) отвечает за то или иное действие? Достаточно ли информации имеется в сегменте, для того 4Опасайтесь "аналитического паралича": если время, затраченное на анализ системы, превышает размеры окна деловых возможностей, то следует оставить все надежды — все, кто попадает в эту ловушку, рано или поздно выходят из игры.
390 Часть III. Приложения чтобы выполнить действие, или он должен перепоручить его другому сегменту? Не слишком ли много обязанностей возложено на сегмент? Выполняет ли он действия, никак не связанные между собой? Что может пойти не по плану? Иначе говоря, что произойдет, если будут нарушены некоторые предусловия или не будут выполнены постусловия? Не правда ли удивительно, насколько похожи эти вопросы на те, которые задают себе проектировщики программного обеспечения? Помните, о чем мы предупреждали в начале главы? Принципы и процесс объектно-ориентированного анализа и проектирования, описанные в предшествующих частях книги, а также систему обозначений UML 2.0, рассмотренную в главе 5, можно с одинаковым успехом применять как для разработки высокоуровневой системной архитектуры, так и для создания программного обеспечения. Ранее был описан анализ системы SNS, выполненный по принципу "черного ящика". Теперь настало время проанализировать внутреннюю структуру системы — сегменты, из которых она состоит, и функциональные свойства, которые должны обеспечиваться с помощью взаимодействия между сегментами. Для этого можно применить метод прозрачного ящика (white-box analysis) к списку сценариев использования, приведенному в табл. 8.1. Следует пристально изучить систему SNS и определить, как она выполняет свои функции. Некоторые факты следует знать заранее. Например, ограничение "Использовать ракету-носитель Proteus-4" определенно влияет на распределение функциональных свойств в системе. Более того, коллектив проектировщиков, разрабатывающих спутниковый сегмент, может быть ограничен требованием "Использовать несущий отсек Gamma 11(B)"5. Развернем этот тезис в следующей врезке. В табл. 8.1 перечислены восемь сценариев использования системы SNS, выявленные при анализе действий пакета SatelliteNavigationSystem, изображенного на рис. 8.5. В ходе реальной, а не приближенной разработки системной архитектуры (которой мы занимаемся в данный момент), нам пришлось бы разрабатывать отдельные диаграммы деятельности для каждого из этих сценариев использования и распределять эти действия среди сегментов, так чтобы выполнялись четыре основных объектно-ориентированных принципа. Однако для того чтобы увеличить масштаб анализа функциональных свойств на макроуровне, мы объединили все восемь сценариев использования системы на одной диаграмме. Это сделать довольно просто, поскольку мы не стремимся слишком глубоко 5Несущий отсек обеспечивает инфраструктурные услуги (например, поставляет энергию и обеспечивает связь), поддерживающие работу спутника, который выполняет специальные функции, такие как передача информации о координатах пользователя.
Глава 8. Системная архитектура: спутниковая система навигации 391 Распределение функциональных свойств В конце концов требования, предъявляемые к системе, необходимо трансформировать в требования, предъявляемые к аппаратному оборудованию, программному обеспечению и средствам ручного управления спутниковой системы навигации, так чтобы организации, имеющие разный опыт, могли параллельно решать свои задачи. Предпринимая эти усилия, коллектив архитекторов должен всегда придерживаться избранной концепции. Распределение функциональных свойств является основной задачей архитекторов на протяжении всей разработки, поскольку ее можно решать на любом уровне абстракции, от самого высокого до самого низкого. Перечисленные ниже примеры иллюстрируют это утверждение. • Система. Функциональные свойства можно распределить по всей системе SNS так, чтобы было удобно поручить работу другой компании, например, Европейскому космическому агентству (European Space Agency), разрабатывающей системы Galileo. • Сегмент. Основным примером распределения функциональных свойств на уровне сегмента является разделение всего контракта на субподряды, заключаемые с многочисленными компаниями. Разумеется, это не значит, что нам следует полностью отказаться от проектирования сегмента космодрома, но разработку интерфейсов можно поручить субподрядчику. • Подсистема6. Распределение функциональных свойств на этом уровне связано с использованием серийно выпускаемых несущих отсеков при разработке спутникового сегмента. • Компоненты. На этом уровне системной архитектуры функциональные свойства распределяются между аппаратным оборудованием, программным обеспечением и средствами ручного управления спутниковой системы навигации. Например, подсистема пользовательского интерфейса (User Interface Subsystem) может состоять из двух компонентов: аппаратного оборудования (жидкокристаллического дисплея) и программы (для управления пользовательским сегментом). углубляться в детали — ведь нас интересует лишь распределение функциональных свойств среди сегментов. Выявив четыре логических системы SNS (см. рис. 8.3), можно приступать к консультациям с экспертами в предметной области о распределении функциональных свойств. Если системная архитектура в этот момент неизвестна, то функциональные свойства можно распределять условно, называя сегменты неопределенными именами, например, SegmentOne (Сегмент 1), SegmentTwo (Сегмент 2) и SegmentThree (Сегмент 3). Каждый из этих сегментов можно 6Описывая уровни подсистем и компонентов архитектуры системы SNS, мы немного забегаем вперед.
392 Часть III. Приложения интерпретировать как специалиста, обладающего специализированными возможностями и взаимодействующего с другими специалистами для обеспечения работы всей системы SNS — в данном случае, при инициализации операций. Это распределение следует продолжать по мере анализа многочисленных сценариев использования, создавая более сложную картину и уточняя имена сегментов. Этот подход напоминает разработку классов, описанную в главе 3. Напомним, что в этой главе был описан способ измерения качества классов и предложены пять показателей. Два из них — связность и связанность — играют очень важную роль при оценке качества основных абстракций в архитектуре спутниковой системы навигации, т.е. ее сегментов. Сегменты системы SNS должны быть слабо связанными друг с другом. Они должны существовать отдельно друг от друга, поддерживая минимальное количество каналов связи, необходимых для обеспечения функционирования системы. Вторым показателем качества является связность абстракций. Он измеряет силу взаимосвязей среди элементов отдельного сегмента. Наименее желательным видом связности является случайная связность (coincidental cohesion), при которой сегмент состоит из абсолютно независимых друг от друга абстракций. Наиболее желательной является функциональная связность (functional cohesion), при которой элементы сегмента работают совместно, обеспечивая точно определенное поведение. Анализируя действия, представленные на рис. 8.5, можно создать диаграмму деятельности, показанную на рис. 8.7. Сценарий использования системы Launch Satellite (Запуск спутника) предусматривает два действия: Prepare for Launch (Подготовка к запуску) и Launch (Запуск). Совершенно очевидно, что эти действия должны обеспечивать сегменты GroundSegment (Наземные службы) и LaunchSegment (Космодром). Сегмент GroundSegment должен выполнить подготовительные работы для запуска ракеты-носителя и отдать сегменту LaunchSegment команду выполнить аналогичные приготовления. После завершения подготовительных работ действующее лицо Operator отдает сегменту GroundSegment команду на запуск, а он, в свою очередь, передает соответствующие команды сегменту LaunchSegment. Анализ сценария использования системы Launch Satellite позволяет выявить действия, которые должны выполнить сегменты GroundSegment и LaunchSegment. Анализ остальных сценариев использования системы, образующих пакет InitializeOperations, приводит к диаграмме деятельности, показанной на рис. 8.7. Диаграмма деятельности пакета Initialize Operations, построенная по принципу "прозрачного ящика", демонстрирует лишь часть функциональных свойств системы, содержащуюся в пакете сценариев выполнения заданий OperateSNS. Остается изучить действия, предшествующие данному моменту, а также последующие действия, содержащиеся в сценариях выполнения заданий Provide Normal Operations, Provide Special Operations и Тег-
Глава 8. Системная архитектура: спутниковая система навигации 393 Operator 1 Команда на подготовку Команда на запуск > Команда на активацию cnyjMKa > Команда на отделение спутника ( Команда на \ позиционирование|^~ 1и на орбите / Команда на отладку бортовых систем Т. > Команда на подготовку к работе «η-*— > Команда на выполнение работы £-_ > GroundSegment Подготовка к запуску Έ 3 Подготовка наземных служб Управление запуском Управление полетом > Управление активацией спутника Управление отделением спутника У ,. Управление •^| позиционирова- Управление отладкой .бортовых систем > Руководство отладкой > у Управление подготовкой работ ение\ вкой к I- Руководство подготовкой к ЙР /— Управление работой > LaunchSegment Подготовка служб | запуска I Запуск 5 Э | Полет к точке I (^ отделения J > Управление активацией спутника Отделение спутника ^ SatelliteSegment Активация спутника К Выйти на | орбиту J Выполнение отладки Выполнить подготовку работ нить Ч >вку к I Передача информации о первоначальном положении I J Рис. 8.7. Диаграмма деятельности пакета Initialize Operations, построенная по принципу "прозрачного ящика"
394 Часть III. Приложения minate Operations. Однако эти действия выходят за рамки анализа, выполняемого на макроуровне. Для их подробного изучения пришлось бы повторить все предыдущие этапы и определить поведение системы. Это позволило бы уточнить взаимодействие между сегментами. К этим функциональным возможностям относятся действия, связанные с активизацией наземных служб и космодрома, проверка целостности спутника и установка спутника на ракету-носитель. Кроме того, в ходе нормального функционирования наземные службы выполняют множество операций, перечисленных ниже. • Непрерывное отслеживание и создание отчетов о состоянии системы. • Непрерывная оценка динамики полета спутников и управление станциями слежения. • Отслеживание и документирование всех сигналов тревоги. • Управление событиями, включая инициализацию и прекращение работы системы. • Оптимизация операций, связанных с работой спутников: оценка состояния двигателя и продление работы спутников. • Восстановление работы спутников после сбоев в электропитании. • Управление качеством работы спутников. • Разработка производственных процедур (регламентных и аварийных). Эти виды деятельности не вошли в наш обзор, поскольку для этого пришлось бы анализировать сценарии выполнения заданий, входящих в пакеты Maintain- SNS (Поддержание работы SNS) и ReceiveSNSServices (Получение услуг SNS), показанные на рис. 8.2 и 8.6. Однако мы продолжим предварительный анализ системы на примере пакета Initialize Operations. На следующем этапе формулируются сценарии использования каждого сегмента системы SNS, показанного на рис. 8.7. Для этого необходимо сосредоточить внимание на конкретном сегменте и определить действия, которые обеспечивают его функциональные свойства как по отдельности, так и в сочетании друг с другом. Начнем с сегмента GroundSegment. Включим первые три действия — Prepare for Launch (Подготовка к запуску), Prepare Ground System (Подготовка наземных служб) и Command Launch (Управление запуском) — в сценарий использования под названием Control Launch (Управление запуском). Следующее действие — Command Flight (Управление полетом) — довольно значительное по масштабу, поэтому ему посвящен отдельный сценарий использования под названием Control Flight (Управление полетом). Аналогично формируются сценарии использования сегментов LaunchSegment и Satellite- Segment. Итоговые сценарии использования и их составные части перечислены в табл. 8.2.
Глава 8. Системная архитектура: спутниковая система навигации 395 Таблица 8.2. Сценарии использования сегментов в пакете Initialize Operations Сегмент SNS Сценарий использования Действие сегмента GroundSegment (Наземные службы) Control Launch (Управление запуском) Prepare for Launch (Подготовка к запуску) Prepare Ground Segment (Подготовка наземных служб) Command Launch (Управление запуском) Control Flight (Управление полетом) Command Flight (Управление полетом) Command Satellite Activation (Активация спутника) Command Satellite Activation (Активация спутника) Control Orbit Positioning (Управление орбитальным ориентированием) Control Orbit Positioning (Управление орбитальным ориентированием) Command Satellite Checkout (Управление отладкой работы спутника) Command Satellite Checkout (Управление отладкой работы спутника) Conduct Satellite Checkout (Отладка работы спутника) Conduct Operation Preparations (Подготовка к выполнению операции) Command Operation Preparations (Управление подготовкой к выполнению операции) Conduct Operation Preparations (Подготовка к выполнению операции)
396 Часть III. Приложения Окончание табл. 8.2 Сегмент SNS Сценарий использования Действие сегмента Command Operation (Управление выполнением операции) Command Operation (Управление выполнением операции) LaunchSegment (Космодром) Launch (Запуск) Prepare Launch Segment (Подготовка космодрома) Launch Launcher (Запуск ракеты-носителя) Fly to Separation Point (Полет в точку отделения спутника) Fly to Separation Point (Полет в точку отделения спутника) Command Satellite Activation (Управление активацией спутника) Command Satellite Activation (Управление активацией спутника) Separate Satellite (Отделение спутника) Separate Satellite (Отделение спутника) SatelliteSegment (Спутник) Activate Satellite (Активация спутника) Activate Satellite (Активация спутника) Maneuver to Orbit (Маневрирование на орбите) Maneuver to Orbit (Маневрирование на орбите) Prepare for operations (Подготовка к выполнению операций) Perform Checkout (Отладка) Perform Operation Preparations (Подготовка к выполнению операций) Transmit Initial Position Information (Передача информации о первоначальном положении) Transmit Initial Position Information (Передача информации о первоначальном положении)
Глава 8. Системная архитектура: спутниковая система навигации 397 Распределение нефункциональных требований и определение интерфейсов В ходе анализа функциональных свойств пакета Initialize Operations было получено дополнительное нефункциональное требование к спутниковой системе навигации: "Время от начала подготовки к запуску до начала передачи информации со спутника не должно превышать семи дней". Чем объяснить это требование? Возможно, заказчик не желает заменять неисправные спутники их орбитальными дублерами7 и предпочитает запускать новые спутники, включая их в работу в течение недели. Итак, наша задача заключается в распределении этого времени (7 дней = 168 часов) по сценариям использования, перечисленным в табл. 8.2, например, установка спутника на ракету-носитель не должна превышать 168 часов. Как же это сделать? Эта работа сводится к двум видам деятельности: распределению нефункциональных требований и документированию результатов. Распределение функционального требования (168 часов) по сценариям использования сегментов в основном опирается на опыт экспертов в предметной области. Кроме того, для того чтобы использовать опыт экспертов в предметной области и разработчиков, мы применили другие методы, такие как моделирование альтернативных схем. В представленном примере 48 из 168 часов были выделены сценариям использования сегментов в пакете Initialize Operations, перечисленным в табл. 8.2. Оставшиеся 120 часов выделяются на другие виды деятельности, к которым относятся активация наземных служб, активация космодрома, проверка целостности спутника и установка спутника на ракету-носитель. Вторая задача — документирование результатов — в основном зависит от требований и инструментов визуального моделирования, используемых командой архитекторов, а также от самого процесса разработки. Многие инструменты позволяют документировать эти результаты, но эта информация обычно хранится в базе требований, имеющей ссылку на действие, представленное в визуальной модели, или описывается на специальных закладках. Несмотря на то что эти инструменты облегчают создание отчетов и проведение статистического анализа, они не позволяют создавать визуальные презентации, предпочитаемые людьми, особенно на этапе разработки архитектуры. В данном случае мы предпочли использовать таблицу (в частности, табл. 8.3), в которой ясно представлены результаты распределения 48 часов. Такие же методы можно применять для распределения других нефункциональных требований среди всех сценариев использования сегментов. Нефункциональные требования, распределенные по сценариям использования сегментов, на следующем уровне абстракции распределяются среди сценариев ис- 73амену неисправных спутников можно осуществить с помощью спутников-дублеров, уже находящихся на орбите. Они обращаются на орбите подобно запасным игрокам футбольной команды, ожидающим своей очереди выйти на поле.
398 Часть III. Приложения Таблица 8.3. Распределение времени, выделенного на запуск ракеты в пакете Initialize Operations* Сегмент SNS Сценарий использования сегмента Время (часы:минуты) GroundSegment Control Launch 11:22 (Наземные (Управление запуском) службы) Control Flight (Управление полетом) Command Satellite Activation (Активация спутника) Command Satellite Separation (Управление отделением спутника) Control Orbit Positioning (Управление орбитальным ориентированием) Command Satellite Checkout (Управление отладкой работы спутника) Conduct Operation Preparations (Подготовка к выполнению операции) 0:17 0:01 0:01 0:05 16:30 4:30 Command Operation 0:01 (Управление выполнением операции) LaunchSegment Launch 11:30 (Космодром) (Запуск) Fly to Separation Point (Полет в точку отделения спутника) Command Satellite Activation (Управление активацией спутника) 0:17 0:01 Separate Satellite 0:04 (Отделение спутника)
Глава 8. Системная архитектура: спутниковая система навигации 399 Окончание табл. 8.3 Сегмент SNS Сценарий использования сегмента Время (часы:минуты) SatelliteSegment Activate Satellite 0:03 (Спутник) (Активация спутника) Maneuver to Orbit (Маневрирование на орбите) Prepare for operations (Подготовка к выполнению операций) 13:45 21:29 Transmit Initial Position 0:03** Information (Передача информации о первоначальном положении) * Если вы имеете реальный опыт в этой области, то легко догадаетесь, что наше распределение времени является слишком приблизительным. Наши эксперты в предметной области были на космодроме во время запуска ракеты-носителя. Хотя на запуск было выделено до 80 часов, на самом деле процедура запуска удается выполнить за 48 часов. Это возможно благодаря тому, что многие операции, перечисленные на рис. 8.7, выполняются параллельно. ** За эти три минуты система SNS начинает передавать информацию по запросу с Земли. Кроме того, 40 часов (из 48) выделяется на выполнение восьми действий, указанных в разделе Operations на рис. 8.7. пользования подсистем с помощью тех же самых методов. Методы, использованные нами для распределения функциональных и нефункциональных требований, могут применяться рекурсивно, по мере перехода с одного уровня на другой: от системы к сегментам, от сегментов к подсистемам и т.д. Кроме того, существуют еще два потенциальных ограничения. • Совместимость с международными стандартами. • Максимальное использование серийно выпускаемого аппаратного оборудования и программного обеспечения. Ограничение, касающееся совместимости с международными стандартами, относится к спецификации внешнего действующего лица Atmosphere/Space (Атмосфера/Космос), упомянутого ранее. Проектировщики должны взаимодействовать с национальными и международными агентствами по стандартизации, регламентирующими использование радиоканалов для определения, например, частот, на которых может передаваться информация о координатах пользователей. Это значит, что наземные службы, космодром (по крайней мере, во время запуска ракеты-носителя) и спутник должны соответствовать требованиям внешнего интерфейса системы SNS. Мы перечислили эти проблемы, поскольку с точки зрения
400 Часть III. Приложения функциональных возможностей, ограничения (и нефункциональные требования) иногда рассматриваются слишком поздно, а иногда и вообще игнорируются. Мы практически не затронули проблему внешних интерфейсов, поскольку предметом нашего рассмотрения является системная архитектура системы SYS с функциональной точки зрения. Методы проектирования и документирования спецификаций интерфейсов должны быть известны тем читателям, кто когда-либо занимался разработкой программного обеспечения. Интерфейсы, существующие в системе SNS, обеспечивают взаимодействие между действующими лицами, указанными на рис. 8.1: User (Пользователь), Operator (Оператор), Maintainer (Техник), External Power (Внешний источник энергии), ExternalCommu- nications (Внешние коммуникации) и Atmosphere/Space (Атмосфера/Космос). Очевидно, для спецификации интерфейсов, предназначенных для действующих лиц User, Operator и Maintainer, необходимо провести анализ функциональных требований. Кроме того, большую помощь в этом деле могут оказать специалисты по взаимодействию между людьми и машинами. Интерфейсы взаимодействия действующих лиц External Power и ExternalCommunica- tions можно определить на достаточно ранних этапах, поскольку они зависят в основном от стандартов энергоснабжения и связи. Последний внешний интерфейс, обеспечивающий взаимодействие с действующим лицом Atmosphere/ Space, определяется главным образом национальными правительствами и международными агентствами, договора между которыми регламентируют передачу информации со спутников. Согласование системной архитектуры и ее разворачивание Концепция логической архитектуры системы SNS, представленной на рис. 8.3, выдержала проверку с помощью поведенческих прототипов. Следовательно, рис. 8.3 и диаграмма компонентов, изображенная на рис. 8.8, отражают логическую концепцию архитектуры первого уровня. В языке UML 2.0 диаграмму компонентов можно использовать для иерархической декомпозиции системы. Это значит, что она представляет высокоуровневую абстракцию архитектуры системы SNS, т.е. их сегментов и отношений между ними. На рис. 8.8 показаны два способа представления интерфейсов между сегментами — в виде шарниров (интерфейс LaunchSupport) и с помощью пунктирных линий зависимости, соединяющих требуемый и предоставляемый интерфейсы (интерфейсы Positionlnforma- tion). Возвращаясь к рис. 8.1, мы видим, что интерфейсы системы SNS, изображенные на рис. 8.8, не учитывают трех действующих лиц: ExternalPower, ExternalCommunications и Atmosphere/Space. Эти действующие лица
Глава 8. Системная архитектура: спутниковая система навигации 401 SolarRadiation а «segment» LaunchSegment LaunchControl ^j* «segment» QroundSegment LaunchSupport I a «ΓΊ, «segment» SatelllteSegment Positionlnformation Positionlnformation I Positionlnformation «segment» UserSegment a τ OperatorAccess MaintainerAccess UserAccess Рис. 8.8. Диаграмма компонентов для спутниковой системы навигации оказывают системе SNS важные услуги, однако не находятся в центре внимания при разработке логической архитектуры. На рис. 8.9 продемонстрировано размещение компонентов, показанных на рис. 8.8, по архитектурным узлам системы. Эти компоненты являются сегментами системы SNS и представлены в виде артефактов языка UML 2.0. Следует отметить, что такое использование обозначений довольно нетипично. Как правило, в таких случаях производится распределение артефактов программного обеспечения (кода, исходных файлов, документов и других сущностей, связанных с кодом) по узлам обработки информации. Однако данная диаграмма ясно отражает информацию, а некоторых нестандартных приемов использования языка UML 2.0 в системотехнике избежать невозможно. Интерфейсы, с помощью которых действующие лица Operator, Maintainer и User взаимодействуют с системой SNS, содержатся внутри сегментов, поэтому мы предпочли показать эти отношения в виде зависимостей. Ранее мы решили обеспечить резервирование функциональных свойств системы с помощью дублирующего оборудования в сегментах GroundSegment и LaunchSegment в режиме "горячей" замены, когда и первичное, и дублирующее оборудование работают параллельно. Разрабатывая архитектуру системы SNS, мы пришли к выводу, что для более эффективного резервирования функциональных возможностей следует распределить каждый из сегментов Ground-
402 Часть III. Приложения s LaunchSlte LaunchSegment Щ / \ Г ι V 1 «atmosphere/space» 2 1 I 1 12 / 1 X ' «terrestrial» «atmosphere/space» /' 1 >^ * I >^ • 1. »// j GroundSite /\ GroundSegment Щ v 1? 1 1 1 / \ i \ ί 1 V V J /— 7 SatelliteConstellation SateiiiteSegment Щ {1Л • 1 ! и V I1 i «atmosphere/space» ; / J A «device» ! UeerDevlce i UserSegment Щ ____^_.—_ 1 Ι Ρ ψ Operator Malntalner Uaer Рис. 8.9. Размещение сегментов системы SNS Segment и LaunchSegment в двух географических точках. Это защитит нас от полной потери функциональных возможностей сегмента, например из-за стихийных бедствий. Это проектное решение показано в виде коэффициента кратности 2 на коммуникационной связи между узлами GroundSite и LaunchSite. Таким образом, мы создали резервные пункты, которые при необходимости смогут заменить основные узлы. Другой аспект архитектуры системы SNS, требующий пояснений, связан с узлом SatelliteConstellation и артефактами сегмента SateiiiteSegment, которыми он владеет. По существу, узел SatelliteConstellation представляет собой совокупность спутников и мест их расположения в космосе, так как эти спутники передают информацию артефактам сегмента UserSegment. Узел SatelliteConstellation поддерживает работу артефактов сегмента SateiiiteSegment, например, учитывает гравитацию (фактор, о котором мы, похоже, забыли), чтобы обеспечить заданную орбиту спутников, а также состояние атмосферы и космического пространства, чтобы обеспечить устойчивую связь со спутниками. Кратность {1. . . *} артефактов сегмента SateiiiteSegment
Глава 8. Системная архитектура: спутниковая система навигации 403 означает, что в группу входит, по крайней мере, один спутник. Наши заказчики еще не определили поверхность покрытия для системы SNS8. Когда заказчик примет решение, можно будет определить реальное количество спутников, необходимых для обеспечения "эффективных и экономичных услуг системы SNS", предоставляемых ею своим пользователям. Декомпозиция системной архитектуры Итак, мы обосновали наши предположения и решения, касающиеся архитектуры системы SNS, по отношению к сценарию использования системы Initia- lizeOperations. Если возникнут какие-либо проблемы, архитектуру можно будет легко модифицировать. Прежде чем идти дальше, необходимо отметить одно важное обстоятельство, характерное для проведенного анализа на макроуровне — поведенческие прототипы должны быть отброшены, поскольку они выполнили свою задачу. Аналогично, прототипы кода не могут стать основой для поставляемого программного обеспечения. Диаграмма логической архитектуры системы SNS, представленная на рис. 8.3, является полезной, но неполной, поскольку каждый сегмент, показанный на этой диаграмме, остается слишком крупным для небольших коллективов проектировщиков. Необходимо углубиться в структуру каждого сегмента и провести дальнейшую декомпозицию на подсистемы. Для этого применяются те методы анализа, которые уже применялись для создания прототипа архитектуры сегментов системы SNS в рамках сценария InitializeOperations, показанных на рис. 8.8. Эти методы применяются на каждом уровне абстракции — от системы к сегментам, от сегментов к подсистемам и т.д., — чтобы определить сценарии использования для каждого сегмента на любом уровне системной архитектуры. При этом нефункциональные требования распределяются по сценариям использования каждого элемента на всех уровнях системной декомпозицир. Для полноты картины укажем методы анализа, применяемые в ходе декомпозиции. 1. Для того чтобы выявить действия системы, каждый сценарий использования системы анализируется по принципу "черного ящика". 2. Для того чтобы распределить действия системы по сегментам, они анализируются по принципу "прозрачного ящика". 8 Очевидно, что эта неопределенность является основным источником риска (технического и нетехнического). Для того чтобы помочь заказчику принять решение, можно попытаться определить оптимальное количество спутников, необходимое для обеспечения желательного покрытия, с помощью моделирования. Читатели, интересующиеся этим вопросом, могут прочитать статьи "Orbit Determination and Satellite Navigation" и "Optimizing Performance Through Constellation Management" в летнем выпуске журнала Crosslink, изданного корпорацией Aerospace в 2002 году (www.aero.org/publications/crosslink/summer2002/index.html),
404 Часть III. Приложения 3. На основе распределенных действий системы определяются сценарии использования сегментов. 4. Для того чтобы выявить действия сегментов, каждый сценарий использования сегмента анализируется по принципу "черного ящика". 5. Для того чтобы распределить действия сегмента по подсистемам, они анализируются по принципу "прозрачного ящика". 6. На основе распределенных действий сегмента определяются сценарии использования подсистем. Методы анализа по принципу "черного" и "прозрачного" ящика описаны в следующей врезке. Методы архитектурного анализа Многие годы системотехники использовали для анализа функциональных возможностей системы и их распределения по элементам ее архитектуры методы, очень напоминающие подходы, описанные выше. С их помощью была успешно разработана система глобального позиционирования GPS. В своей книге The Object Advantage Джекобсон (Jakobson et al.) и соавторы описали сценарии использования и их приложения к анализу промышленных систем, созданные на основе концепции сценариев использования высшего и низшего порядков [12]. Унифицированный процесс разработки для системотехники (IBM Rational Unified Process for Systems Engineering — RUP SE), предложенный компанией IBM Rational, по существу, объединяет эти подходы и расширяет средства RUP. Системотехники уже многие годы эффективно применяют концепцию сценариев использования и анализ по принципу "черного" и "прозрачного" ящиков. Как правило, прежде чем перейти на следующий этап, проектировщики проводят полный анализ каждого архитектурного уровня системы. Иначе говоря, прежде чем переходить на этап 2, следует на этапе 1 провести анализ всех сценариев использования системы по принципу "черного ящика". Затем необходимо провести анализ всех действий системы по принципу "прозрачного" ящика и лишь после этого переходить на этап 3 и т.д. Однако из-за ограниченного объема книги декомпозиция системной архитектуры будет продемонстрирована лишь на примере сценария использования системы Launch Satellite. Читая приведенный выше список этапов анализа, не следует думать, что проектировщики должны пройти его "вертикально": определить сценарий использования системы, выявить ее действия, определить сценарий использования сегментов, выявить действия сегмента, определить сценарий использования подсистемы и т.д., а затем повторить всю процедуру для следующего сценария использования системы. Это неэффективно. Перечисленные этапы на
Глава 8. Системная архитектура: спутниковая система навигации 405 каждом уровне архитектуры следует выполнять "горизонтально", чтобы выработать полную и цельную концепцию системы, которую можно обосновать. Последующий анализ — не описанный в книге — выполняется следующим образом. • Выполняется анализ сценария использования Launch Satellite no принципу "черного ящика" и определяются действия системы. • Выделенные действия анализируются по принципу "прозрачного ящика" и распределяются по сегментам. • Выполняется анализ сценария использования сегмента GroundSystem по принципу "черного ящика" и определяются действия системы. • Выполняется анализ сценария использования Control Launch сегмента GroundSystem по принципу "черного ящика" и определяются действия системы. • Выполняется анализ сценария использования Control Launch сегмента GroundSystem по принципу "прозрачного ящика" и выделенные действия системы распределяются по подсистемам. Результаты этого анализа приведены на рис. 8.10. На диаграмме показаны действия, которые должна выполнять каждая подсистема сегмента GroundSeg- ment в ходе взаимодействия с другими подсистемами для управления запуском спутника. Это позволяет разработать архитектуру каждого сегмента спутниковой системы навигации. Архитектура каждого сегмента системы показана ниже. Архитектура сегмента GroundSegment состоит из пяти подсистем: Соп- trolCenter (Центр управления), ТТ&С (подсистема слежения, телеметрии и управления), SensorStation (Место расположения датчиков), Gateway (Стартовая площадка) и Userlnterface (Пользовательский интерфейс), представленный на рис. 8.11. Подсистема Control Center обеспечивает функциональные свойства, связанные с управлением всей системой SNS, взаимодействуя с подсистемой ТТ&С и SensorStation. Подсистема ТТ&С обеспечивает слежение и управление сегментом SatelliteSegment. Подсистема SensorStation поставляет информацию о положении спутника, поступающую от сегмента SatelliteSegment, и данные о состоянии окружающей среды. Подсистема Gateway обеспечивает связь подсистемы ControlCenter с сегментами LaunchSegment и SatelliteSegment для управления запуском и действиями со спутником соответственно. На рис. 8.12 изображена логическая архитектура сегмента LaunchSegment, состоящего из трех подсистем: LaunchCenter (Цент управления запуском), Launcher (Ракета-носитель) и Gateway (Стартовая площадка). Подсистема LauncherCenter обеспечивает управление сегментом LaunchSegment. Его функции аналогичны действиям, которые выполняет подсистема ControlCen-
406 Часть III. Приложения а щ •с I ^шшХшщь el! Ц*1 ?1! l·*® § я б о g ,•-—* V вд о к и с Ρ (0 о с о и о X S 2 lllle S3- о 2 о о и1 е||1| Si! Si α» Φ 2 Ρ- 14 c= 9 Ι ^JL^ 00 О Я
Глава 8. Системная архитектура: спутниковая система навигации 407 ter по отношению к сегменту GroundSegment. Подсистема Gateway в этом сегменте, как и в сегменте GroundSegment, позволяет подсистеме Launch- Center получать команды управления запуском от сегмента GroundSegment и обеспечивать запуск ракеты-носителя подсистемой Launcher. «segment» GroundSegment э—О* Positionlnformation Environmentallnlbrmation а «subsystem» SensorStatlon ι Environmentallnfbrmation о о «subsystem» тт&с s TT&CServices Positioninformation SatelliteControl SatelliteControi CX Π—Ο a «subsystem» ControlCenter к Sateiiitelnformation >-£>£ -——г LaunchControi ManuaiControi «subsystem» a ex—η—ο LaunchControi a «subsystem» Userinterface OperatorAccess MaintainerAccess OperatorAccess О О MaintainerAccess Рис. 8.11. Логическая архитектура сегмента GroundSegment Сегмент SatelliteSegment разделяется на две подсистемы, как показано на рис. 8.13. Подсистема SatelliteBus (Несущий отсек) обеспечивает инфраструктурную поддержку работы системы NavigationPayload. По своей структуре оборудование подсистемы SatelliteBus обеспечивает поставку энергии, управление позицией и двигателей. Оно позволяет подсистеме Navigat ionPayload поставлять информацию пользователям системы SNS (включая установку точного времени и генерацию сигналов позиционирования). Сегмент UserSegment также разделяется на несколько подсистем, как показано на рис. 8.14. Подсистема Receiver (Приемник) получает информацию о положении пользователя от сегмента SatelliteSegment и передает эту
408 Часть III. Приложения LaunchControi а «segment» LaunchSegment «subsystem» Gateway LaunchControi ςχ ρ—ο LaunchSupport LaunchSupport LaunchControi Рис. 8.12. Логическая архитектура сегмента LaunchSegment SolarRadiatlon а LaunchSupport >-о<—э- I «segment» SatelltteSegment SolarRadiation «subsystem» SatellrteBua a InfrastructureSupport a «subsystem» NavlgatlonPayload SatelliteControl Positioninformation Satelhtelnfbrmation SatelliteControl Satellitelnformation Positioninformation Рис. 8.13. Логическая архитектура сегмента SatelliteSegment навигационную информацию подсистеме Userlnterface. Подсистема User- Interface открывает подсистеме User доступ к средствам навигации подсисте-
Глава 8. Системная архитектура: спутниковая система навигации 409 Positionlnformation «segment» UserSegment а Positionlnformation I «subsystem» Receiver ffl PositlonData «subsystem» Userinterfaee ffl Navigationlnfbrmetion «subsystem» Processor a UserAooess UserAccess Рис. 8.14. Логическая UserSegment архитектура сегмента мы UserSegment с помощью ряда специализированных интерфейсов, например, нажатия кнопок, прикасания к экранам и звуковых сигналов. Эта схема состоит из четырех сегментов, каждая из которых включает несколько подсистем, обеспечивающих функциональные возможности системы с помощью аппаратного оборудования, программного обеспечения и ручных операций. В некоторых случаях распределение функциональных свойств для опытных архитекторов является вполне очевидным. Как указывалось в главе 7, эти сегменты и их подсистемы образуют рабочие модули, а также крупные модули для управления конфигурацией и контроля версий. Каждый сегмент или подсистема должна разрабатываться отдельной организацией, коллективом или отдельным лицом, либо несколькими организациями, коллективами или лицами. Они проводят детальное проектирование и реализацию элементов, а также управляют интерфейсами между элементами на одном и том же уровне абстракции. Таким образом, управление очень крупными проектами может представлять собой очень сложную задачу, которую необходимо разделить на несколько более мелких частей.
410 Часть III. Приложения Итак, цель достигнута — мы продемонстрировали принципы и процесс объектно-ориентированного анализа и проектирования, а также систему обозначений UML 2.0 на примере разработки высокоуровневой архитектуры. 8.3 Конструирование Как указывалось в главе 6, в конце этапа разработки должна быть создана устойчивая архитектура системы. Любая модификация этой архитектуры, которая может понадобиться на этапе конструирования, ограничена архитектурными элементами низкого уровня, а не сегментами или подсистемами разрабатываемой системы SNS. В соответствии с темой главы — продемонстрировать разработку архитектуры системы SNS путем логического разделения функциональных возможностей для определения сегментов и подсистем — мы не описываем никаких архитектурных мероприятий, предпринимаемых на этом этапе. 8.4 Сопровождение Нефункциональные требования, предъявляемые к спутниковой системе навигации, содержат два пункта, для выполнения которых необходима гибкая архитектура, а именно: расширяемость и долгий период обслуживания. Второе требование означает, что кроме всего прочего, проект должен допускать расширение, чтобы гарантировать надежное функционирование. По мере увеличения количества пользователей системы SNS и появления новых технологий, функциональные свойства системы должны совершенствоваться. Рассмотрим, насколько полно проект системы SNS соответствует этим требованиям. Добавление новых функциональных возможностей Представим себе, что кроме всего прочего, система SNS должна иметь возможность получать информацию от других систем, например, GPS, GLONASS и Galileo. Это позволит повысить точность определения географических координат пользователей. Для этого достаточно сделать минимальные изменения в системе SNS, поскольку эти изменения локализованы в сегменте UserSegment. Благоприятным обстоятельством является также тот факт, что существующий пользовательский сегмент можно легко обновить, изменив подсистему Receiver и расширив подсистему Processor. Итак, добавление этой функциональной возможности требует очень небольшого изменения существующего проекта. Это свойство характерно для всех хорошо структурированных объектно-ориентированных систем: значительное расширение требований, предъявляемых к системе, легко осуществить за счет конструирования новых приложений для существующих механизмов.
Глава 8. Системная архитектура: спутниковая система навигации 411 А что, если понадобится радикальная перестройка системы? Предположим, что заказчик пожелал включить в проект возможность поиска и спасения заблудившихся людей (search and rescue — RAS) по сигнальным маякам9. Как это требование влияет на архитектуру системы? Анализ показывает, что наибольшее влияние это требование оказывает на сегмент SatelliteSegment и в некоторой степени — на сегмент GroundSegment. Этот результат вполне предсказуем. Если бы мы предвидели подобное требование, мы включили бы в систему возможность принимать специальные сигналы (или диапазон сигналов), и тогда в сегмент SatelliteSegment не пришлось бы вносить никаких изменений. По отношению к сегменту GroundSegment изменения касаются возможности передавать информацию, полученную от сигнальных маяков, соответствующим властям. Для этого понадобилось бы внести небольшие изменения в программное обеспечение и модифицировать подсистемы ControlCenter и ТТ&С. Итак, эти крупные изменения в составе требований имели бы минимальное влияние на архитектуру системы SNS в целом. К сожалению, вносить изменения в подсистемы, расположенные в космосе, очень трудно. По этой причине системные архитекторы стараются предвидеть возможные изменения требований. Однако даже в самой худшей ситуации мы способны в будущем добавить к системе SNS возможности SAR с минимальным влиянием существующей архитектуры или функциональных возможностей. Изменение аппаратного оборудования Аппаратная технология совершенствуется быстрее, чем наши способности создавать программное обеспечение. Более того, очень часто большое количество политических и исторических причин вынуждает проектировщиков выбирать определенное оборудование и программное обеспечение и впоследствии жалеть об этом10. Аппаратное оборудование для крупных систем устаревает намного быстрее программного обеспечения. Например, через несколько лет работы проектировщики могут решить полностью заменить подсистему ControlCenter сегмента GroundSegment. Как 9Программа Galileo предусматривает возможность сотрудничества с системой Cospas-Sarsat (www.cospas-sarsat.org) с целью поиска и спасения людей по всему миру. Создатели программы Galileo считают, что их вклад в эти усилия обеспечит быстрый прием сигналов бедствия и определение местоположения маяков с точностью до нескольких метров. 10Например, проектировщики могли бы выбрать определенное оборудование или программное обеспечение, поставляемое третьей стороной, а затем убедиться в том, что поставщик не в состоянии обеспечить их работу. Или еще хуже, единственный поставщик, способный продать очень важное оборудование, может разориться. В таких случаях менеджер проекта обычно имеет выбор: 1) убежать в ночь, крича и рыдая, или 2) выбрать другую продукцию, надеясь, что системная архитектура не пострадает от этих изменений. Применение объектно-ориентированного анализа и проектирования позволяет надеяться, что менеджеру удастся осуществить вторую возможность, хотя иногда остается лишь горько сожалеть и плакать.
412 Часть III. Приложения это повлияет на существующую архитектуру? Если при проектировании системы ее интерфейсы создавались на высоком уровне абстракции, замена аппаратного оборудования не потребует крупных изменений в программном обеспечении. Поскольку все проектные решения инкапсулированы в подсистеме ControlCen- ter, никакая другая подсистема не зависит от свойств рабочих станций. Иначе говоря, эта подсистема скрывает все секреты аппаратного оборудования. Это значит, что функциональные возможности рабочей станции скрыты в подсистеме ControlCenter. Следовательно, эта подсистема играет роль абстрактного брандмауэра, защищающего всех клиентов от изменений, связанных со сложностями конкретной технологии. Аналогично, на реализацию системы может повлиять радикальное изменение телекоммуникационных стандартов, хотя в этом случае его влияние ограничено. В частности, разработанный проект гарантирует, что подсистема Gateway знает о сетевых коммуникациях. Таким образом, фундаментальное изменение сетевых технологий не способно повлиять на высокоуровневых клиентов, поскольку подсистема Gateway защищает их от перипетий реального мира. Итак, ни одно из изменений, перечисленных выше, не приводит к радикальному пересмотру существующей архитектуры системы. Это главный признак объектно-ориентированной системы с хорошей архитектурой.
ГЛАВА 9 СИСТЕМА УПРАВЛЕНИЯ ТРАФИКОМ Индустрия программного обеспечения достигла такого уровня развития, что в настоящее время охватывает широкий диапазон автоматизированных приложений: от бортовых микрокомпьютеров в автомобилях до рутинного распределения мультфильмов в сети интерактивных видеомагазинов. Отличительной чертой всех этих крупных систем является их исключительная сложность. Разумеется, создание компактных систем само по себе имеет большое значение, но некоторые крупные задачи невозможно решить без больших программ. Крупные приложения обычно разрабатывают организации, специализирующиеся на создании программного обеспечения и состоящие из нескольких сотен сотрудников, которые, взаимодействуя друг с другом, должны написать миллионы строк кода и удовлетворить постоянно изменяющимся требованиям. Такие проекты, как правило, редко ограничиваются одной программой. Намного чаще создаются комплексы взаимодействующих программ, выполняемых в распределенной среде, состоящей из множества компьютеров, по-разному связанных между собой. Для того чтобы уменьшить риск провала, руководство такими проектами обычно возлагается на центральную организацию, отвечающую за архитектуру и целостность системы. Остальная часть работы обычно выполняется по субподрядам другими компаниями или подразделениями. Таким образом, коллектив разработчиков никогда не собирается вместе. Как правило, сотрудники распределены в пространстве и — вследствие текучести кадров в крупных проектах — во времени. Разработчики, занимающиеся созданием небольших, самостоятельных программ, предназначенных для индивидуального пользователя, могут быть ошеломлены масштабом проблем, возникающих при разработке крупных приложений, до такой степени, что они сочтут глупостью даже пытаться приступать к проектированию. Однако реалии деловой и научной жизни вынуждают со-
414 Часть III. Приложения здавать крупные системы программного обеспечения. В некоторых случаях, наоборот, глупо не попытаться сделать это. Представьте себе ручную систему для управления движением воздушного транспорта крупного города или жизнеобеспечения космической станции, пилотируемой людьми, или бухгалтерского учета в транснациональном банке. Успешная автоматизация таких систем не только решает реальные проблемы, но и приносит много материальных и нематериальных выгод: снижение эксплуатационных расходов, повышение надежности и расширение функциональных возможностей. Конечно, ключевое слово в этом предложении — успешная. Совершенно очевидно, что создание больших систем представляет собой трудную задачу, требующую для своего решения применения самых лучших методов, созданных инженерной мыслью, а также творческих способностей немногих выдающихся проектировщиков. В главе описано решение именно такой задачи. 9.1 Начало Для большинства жителей США поезда являются артефактом далекого прошлого. В Европе и многих странах Азии сложилась совершенно противоположная ситуация. В этих странах поезда образуют значительную часть национальных транспортных систем. Железные дороги ежедневно перевозят множество людей и грузов на десятки тысяч километров как внутри стран, так и через границы. Справедливости ради следует отметить, что в США поезда также играют важную экономическую роль в перевозке грузов. Кроме того, по мере разрастания городов легкий железнодорожный транспорт может решить проблему пробок на автомобильных дорогах и загрязнения окружающей среды двигателями внутреннего сгорания. Железные дороги — это бизнес. Следовательно, они должны быть прибыльными. Железнодорожные компании обязаны искусно поддерживать баланс между требованиями экономии и безопасности, а также между повышением интенсивности перевозок и разумным расписанием движения. Для разрешения этих противоречий необходима автоматическая система управления движением поездов, включающая в себя компьютеризированную маршрутизацию и мониторинг всех элементов железной дороги. Такие автоматические и полуавтоматические системы управления железными дорогами в настоящее время существуют в Швеции, Великобритании, Германии, Франции, Японии [1], Канаде и США. Цели, стимулировавшие создание этих систем, носили, в основном, экономический и социальный характер: снижение эксплуатационных затрат, более эффективное использование ресурсов и повышение безопасности, как побочный эффект. Мы начнем анализ функций системы управления железнодорожным трафиком (Train Traffic Management System — TTMS) с определения основных требо-
Глава 9. Система управления трафиком 415 ваний и сценариев использования системы, описывающих функциональные возможности. Требования к системе управления движением Опыт разработки крупных систем показывает, что первоначальная формулировка требований никогда не бывает полной, часто остается неопределенной и всегда является противоречивой. По этим причинам необходимо бороться с неопределенностью на протяжении всего проекта и строго придерживаться предположения, что разработка такой системы со временем будет постепенно эволюционировать. Как указывалось в главе 6, процесс разработки позволяет пользователям и разработчикам глубже понять действительно важные требования — намного лучше, чем любой бумажный документ, не опирающийся на существующую реализацию или прототип. Кроме того, поскольку разработка программного обеспечения для крупной системы может длиться несколько лет, требования, предъявляемые к программному обеспечению, должны допускать модификацию, чтобы иметь возможность реагировать на быстрый технологический прогресс аппаратного оборудования1. Совершенно очевидно, нет никакого смысла разрабатывать элегантную архитектуру программного обеспечения, которая ко времени завершения проекта окажется устаревшей. Вот почему мы предполагаем, что любой механизм, входящий в системную архитектуру, должен опираться на существующие стандарты связи, графики работы в сети и датчики. Для совершенно новых систем иногда необходимо разрабатывать абсолютно новое аппаратное оборудование или программную технологию. Однако это вносит в проект дополнительный риск. Разработка программного обеспечения для крупного автоматизированного приложения по-прежнему сопряжена с наивысшим риском, и наша цель — снизить этот риск до приемлемого уровня, а не увеличить его. В реальном мире очень крупные и сложные системы невозможно описать с помощью простых ограничений. Однако в этой главе ограничения предназначены лишь для иллюстрации процесса анализа и проектирования. На самом деле такие системы часто становятся жертвой "аналитического паралича", поскольку количество требований достигает нескольких тысяч, как функциональных, так и нефункциональных, а количество ограничений не поддается перечислению. Очевидно, следует сосредоточить свои усилия на разработке наиболее важных элементов и прототипов в контексте проектируемой системы. Многие сложные системы предусматривают использование компьютеров разного типа. Продуманная и устойчивая архитектура существенно смягчает риск изменения аппаратного оборудования в ходе выполнения проекта — явления, которое происходит слишком часто. Аппаратное оборудование приходит и уходит, поэтому важно управлять границей между аппаратным и программным обеспечением системы, чтобы иметь возможность использовать новые продукты, удешевляющие систему или повышающие ее производительность, одновременно сохраняя целостность архитектурной системы.
416 Часть III. Приложения Система управления железнодорожным трафиком выполняет две главные функции: маршрутизация железнодорожных перевозок и мониторинг железнодорожных систем. К родственным функциям относятся: планирование трафика, контроль местонахождения поездов, мониторинг трафика, предотвращение столкновений и регистрация операций. На основе этих функций мы определили восемь прецедентов использования, перечисленных в следующем списке. • Route Train: определение маршрутного плана (train plain) для конкретного поезда. • Plan Traffic: определение схемы движения (traffic plan), обеспечивающей основу для разработки маршрутного плана в конкретном временном интервале и географическом регионе. • Monitor Train Systems: мониторинг функционирования бортовых систем. • Predict Failure: анализ состояния систем поезда и оценка вероятности аварии в рамках конкретного маршрутного плана. • Track Train Location: слежение за местоположением поезд а с помощью ресурсов системы TTMS и системы глобального позиционирования Navstar (Navstar Global Positioning System). • Monitor Traffic: мониторинг всего железнодорожного трафика в регионе. • Avoid Collision: обеспечение автоматических и ручных средств управления, позволяющих предотвратить столкновение поездов. • Log Maintenance: обеспечение средств для регистрации операций, выполняемых поездом. Эти прецеденты использования устанавливают основные функциональные требования к системе TTMS, т.е. сообщают, что должна делать система для своих пользователей. Кроме того, существуют нефункциональные требования и ограничения, которые влияют на требования, определенные в прецедентах использования. Эти требования перечислены ниже. Нефункциональные требования: • Безопасная перевозка пассажиров и грузов. • Поддержка скорости движения поезда не ниже 250 км/час. • Взаимодействие с внешними системами управления трафиком. • Обеспечение максимальной степени повторного использования и совместимости существующего оборудования. • Обеспечение доступности системы на уровне 99,99%.
Глава 9. Система управления трафиком 417 • Обеспечение полного резервирования функциональных возможностей системы TTMS. • Определение местоположения поезда с точностью до 10,0 ярдов. • Определение скорости движения поезда с точностью до 1,5 миль в час. • Реакция на команды оператора быстрее 1,0 секунд. • Поддержка возможностей эксплуатации и совершенствования системы TTMS. Ограничения: • Соответствие правительственным и промышленным стандартам. • Максимальное использование серийно выпускаемого аппаратного оборудования и программного обеспечения. Итак, определив основные требования на очень высоком уровне абстракции, необходимо переключить внимание на пользователей системы TTMS. Нам удалось определить три группы людей, взаимодействующих с системой: Dispatcher (Диспетчер), TrainEngineer (Машинист) nMaintainer (Эксплуатационник). Кроме того, система TTMS взаимодействует с внешней системой Navstar GPS. Эти действующие лица играют следующие роли в системе TTMS. • Действующее лицо Dispatcher устанавливает маршруты поездов и отслеживает их передвижение. • Действующее лицо TrainEngineer следит за состоянием поезда и обслуживает его. • Действующее лицо Maintainer следит за состоянием систем поезда и обслуживает их. • Действующее лицо Navstar GPS предоставляет услуги по определению географических координат для отслеживания поездов. Определение прецедентов использования системы На рис. 9.1 показана диаграмма прецедентов использования системы TTMS. На ней показаны функциональные возможности, используемые каждым действующим лицом. Кроме того, как следует из диаграммы, между некоторыми прецедентами использования существуют организационные зависимости «include» и «extend». Функциональные возможности сценария Monitor Train Systems (Мониторинг бортовых систем) дополняются прецедентом использования Predict Failure (Прогнозирование отказов). В ходе мониторинга системы может понадобиться провести анализ вероятности аварии (condition:{request Predict Failure}) в конкретной системе, функционирование которой вызывает сомнения. Эта функция выполняется в точке Potential Failure (Потенциальный отказ).
418 Часть III. Приложения Train Traffic Management System Рис. 9.1. Диаграмма прецедентов использования для системы TTMS Функциональные возможности прецедента использования Monitor Traffic (Мониторинг трафика) также расширяются с помощью прецедента использования Collision (Столкновение). В рамках этого прецедента действующее
Глава 9. Система управления трафиком 419 лицо, отслуживающее трафик поездов, может попытаться избежать столкновений — в точке расширения Potential Collision (Потенциальное столкновение). Эту функцию можно выполнить как вручную, так и в автоматическом режиме. Прецедент использования Monitor Traffic всегда включает в себя функциональные возможности прецедента использования Track Train Location (Отслеживание положения поезда), позволяющего получить точную картину расположения всех поездов. Для этого используются ресурсы систем TTMS и Navstar GPS. Детали функциональных свойств каждого из этих прецедентов использования описываются в текстуальных документах, которые называются спецификациями прецедентов использования. Рассмотрим спецификации двух прецедентов использования: Route Train (Маршрутизация поезда) и Monitor Train Systems (Системы слежения за поездом). Формат этих спецификаций не определен и позволяет описывать как первичный, так и вторичные альтернативные сценарии. Следует отметить, что эти спецификации прецедентов использования очерчивают границы взаимодействия между пользователями системы и самой системой TTMS. Такой подход часто называется методом анализа по принципу "черного ящика ", поскольку внутреннее функционирование системы при этом не раскрывается. Этот подход позволяет определить, что система делает, а не как она это делает. Название прецедента использования: Route Train. Цель сценария: установить маршрутный план поезда, в котором хранится вся информация о маршруте конкретного состава и действующих лицах, с которыми он взаимодействует. Пункт контакта: Катарина Бах. Дата модификации: 5.09.2006. Предусловия: существует схема движения поезда, установленная на определенный промежуток времени и для конкретного географического региона (территории) в рамках разрабатываемого маршрутного плана. Постусловия: разработан маршрутный план для конкретного поезда, содержащий детальную информацию о маршруте. Ограничения: каждый поезд имеет уникальный идентификационный номер внутри данной системы. Ресурсы на одновременную разработку нескольких маршрутных планов могут не выделяться. Предположения: маршрутный план доступен для диспетчеров по запросу и при необходимости может изменяться и запрашиваться машинистом.
420 Часть III. Приложения Основной сценарий: A. Система TTMS предоставляет диспетчеру список вариантов. Б. Диспетчер выбирает опцию, предусмотренную для разработки нового маршрутного плана. B. Система TTMS открывает шаблон маршрутного плана. Г. Диспетчер заполняет шаблон маршрутного плана, указывая информацию об идентификационном номере локомотива, машинисте и графике движения. Д. Диспетчер вводит заполненный маршрутный план в систему TTMS. Ε. Система присваивает маршрутному плану уникальный идентификационный номер и сохраняет его, допуская возможность запроса и модификации этого плана. Ж. Сценарий завершен. Альтернативные сценарии. Условие ввода в действие альтернативных сценариев. Условие 1. Разработка нового плана, основанного на существующем Б1. Диспетчер выбирает опцию, связанную с разработкой нового маршрутного плана на основе существующего. Б2. Диспетчер указывает критерий поиска существующего маршрутного плана. БЗ. Система TTMS выводит результаты поиска. Б4. Диспетчер выбирает существующий маршрутный план. Б5. Диспетчер заполняет маршрутный план. Б6. Выполнение основного сценария возобновляется с пункта Д. Условие ввода в действие альтернативных сценариев. Условие 2. Изменение существующего маршрутного плана. Б1. Диспетчер выбирает опцию, связанную с изменением существующего маршрутного плана. Б2. Диспетчер указывает критерий поиска существующего маршрутного плана. БЗ. Система TTMS выводит результаты поиска. Б4. Диспетчер выбирает существующий маршрутный план. Б5. Диспетчер изменяет маршрутный план. Б6. Диспетчер вводит измененный маршрутный план в систему.
Глава 9. Система управления трафиком 421 Б7. Система сохраняет его, допуская возможность запроса и модификации. Б8. Сценарий завершен. Название прецедента использования: Monitor Train Systems. Цель сценария: мониторинг бортовых систем. Пункт контакта: Катарина Бах. Дата модификации: 5.09.2006. Предусловия: локомотив находится на маршруте. Постусловия: имеется доступ к информации, касающейся функционирования бортовых систем. Ограничения: нет. Предположения: мониторинг бортовых систем относится к локомотивам, находящимся на маршруте. Сообщения о проблемах, связанных с функционированием бортовых систем, поступают в виде визуальных или звуковых сигналов, а также в виде текста на дисплее. Основной сценарий: A. Система TTMS предоставляет машинисту список вариантов. Б. Машинист выбирает опцию, предусмотренную для мониторинга бортовых систем. B. Система TTMS предоставляет машинисту информацию о состоянии бортовых систем. Г. Машинист просматривает информацию о состоянии бортовых систем. Д. Сценарий завершен. Альтернативные сценарии. Условие ввода в действие альтернативных сценариев. Условие 1. Необходима дополнительная информация. Д1. Машинист решает уточнить информацию о состоянии системы, подающей предупреждающие сигналы. Д2. Система TTMS предоставляет машинисту подробную информацию о состоянии выбранной системы. ДЗ. Машинист просматривает подробную информацию о состоянии системы. Д4. Выполнение основного сценария возобновляется с пункта Б. Точка расширения — Potential Failure. Условие 2. Необходимо провести оценку вероятности отказа системы. ДЗ-1. Машинист запрашивает оценку вероятности отказа системы. ДЗ-2. Система TTMS оценивает вероятность отказа указанной системы.
422 Часть III. Приложения ДЗ-3. Система TTMS представляет машинисту результаты оценки вероятности отказа системы. ДЗ-4. Машинист изучает оценку вероятности отказа системы. ДЗ-5. Машинист отдает команду системе TTMS выдать сигнал тревоги эксплуатационнику системы, которая может оказать. ДЗ-6. Система TTMS передает эксплуатационнику этой системы сигнал тревоги. ДЗ-7. Эксплуатационник запрашивает результаты оценки вероятности отказа системы. ДЗ-8. Система TTMS передает эксплуатационнику результаты оценки вероятности отказа системы. ДЗ-9. Эксплуатационник анализирует эти результаты и приходит к выводу, что сигнал тревоги пока не требует немедленного реагирования. ДЗ-10. Эксплуатационник отдает системе TTMS команду информировать машиниста о своем решении. ДЗ-11. Система TTMS передает машинисту информацию о решении эксплуатационника. ДЗ-12. Машинист решает провести более глубокий анализ состояния выбранной системы. ДЗ-13. Выполнение альтернативного сценария возобновляется с пункта ДЗ. Несмотря на то что требования, предъявляемые к системе TTMS, крайне упрощены, они еще полностью не перечислены и остаются весьма расплывчатыми. Эта ситуация вполне типична для разработки больших и сложных систем реального приложения. Как уже указывалось, эффективное управление постоянно изменяющимися требованиями является необходимым условием успешной разработки проекта, которая должна вовремя и без излишних затрат обеспечить все функциональные возможности системы. Однако не следует думать, что наша цель — остановить процесс изменения требований. Мы не можем и не должны это делать, учитывая быстрый прогресс аппаратного обеспечения, который обычно сопровождается падением цен и позволяет решать все больше задач. Невероятно мощное и сложное программное обеспечение в настоящее время стало доступным для использования на персональных компьютерах, а процессоры с тактовой частотой в несколько мегагерц и оперативные запоминающие устройства (RAM) емкостью в несколько гигабайт уже достаточно широко распространены. Итак, не следует останавливать процесс изменения требований — необходимо взять его под контроль, особенно с учетом того, что процесс разработки системы может длиться несколько лет. Опыт показывает, что одними из основных средств
Глава 9. Система управления трафиком 423 управления рисками, связанными с изменением технических требований в крупных автоматизированных системах, являются использование последовательного и поступательного процесса разработки и гибкая архитектура. Кроме того, необходимо максимально широко использовать серийно выпускаемое коммерческое аппаратное оборудование и программное обеспечение. По этой причине в этой главе основное внимание уделяется архитектуре, способной воспринимать изменения технических требований, предъявляемых к системе. 9.2 Разработка Перейдем к разработке архитектуры системы TTMS в целом. Начнем с анализа требуемых функциональных возможностей, который позволит определить архитектуру системы TTMS. Тем самым мы совершим переход от системотехники к разработке аппаратного и программного обеспечения. Раздел завершается перечислением основных абстракций и механизмов системы TTMS. Анализ функциональных возможностей системы После определения технических требований, предъявляемых к системе TTMS, необходимо проанализировать, как составные части системы обеспечивают желательные функциональные возможности. Этот подход часто называют методом "прозрачного ящика", поскольку он предусматривает явный анализ внутреннего функционирования системы. Для анализа разнообразных сценариев использования и выявления новых подробностей мы будем конструировать диаграммы деятельности. Начнем с рис. 9.2, на котором продемонстрирован основной вариант развития событий в рамках сценария Route Train (Маршрутизация поезда). Эта диаграмма деятельности является относительно простой и отражает содержание данного сценария использования. На ней показано взаимодействие между действующим лицом Dispatcher (Диспетчер) и системой RailOperationsCon- trolSystem (Система управления железной дорогой), выполняющей основные команды и играющей роль центра управления системой TTMS, в ходе которого действующее лицо Dispatcher создает новый объект TrainPlan (План движения поезда). Определив составляющие элементы системы TTMS, необходимо рассмотреть функциональные и нефункциональные технические требования, а также ограничения. Однако следует иметь в виду два взаимно противоречивых технических аспекта: желание инкапсулировать абстракции и необходимость сделать некоторые абстракции видимыми для других элементов. Иначе говоря, следует стремиться к тому, чтобы элементы проекта были связными (группируя их в логически связанные между собой абстракции) и слабосвязанными (минимизируя зависимости
424 Часть III. Приложения Рис. 9.2. Основной сценарий Route Train между элементами). Таким образом, понятие модульности можно определить как свойство системы, допускающее ее разложение на множество связных и слабосвязанных элементов. В противоположность рис. 9.2, диаграмма деятельности, изображенная на рис. 9.3, более сложна, поскольку она иллюстрирует первый альтернативный вариант прецедента использования Monitor Train Systems (Мониторинг бортовых систем), в котором действующее лицо TrainEngineer (Машинист) решает выполнить подробный мониторинг системы LocomotiveAnalysisand- Reporting (Анализ состояния локомотива и отчеты), подавшей сигнал тревоги. На диаграмме показаны составные элементы системы TTMS, обеспечивающие эту возможность: система OnboardDisplay (Дисплей бортовых систем), система
Глава 9. Система управления трафиком 425 TrainEngineer OnboardDispiay LocomotiveAnalysisandReporting EnergyManagement DataManagement Решает проверить системы > Предоставляет выбор ( Запрашивает беглый обзор данных о состоянии системы U Выполняет анализ результатов беглого обзора Представляет результаты беглого обзора состояния системы [иначе] *® [требуется более подробный мониторинг системы] Решает провести подробный мониторинг [системы анализа| состояния локомотива и выдачи отчетов Анализирует подробную информацию о |«ζ- состоянии системы Запрашивает ^ подробную информацию о состоянии , системы , Предоставляет подробную информацию о состоянии системы Выполняет беглый обзор данных _ИГ Выполняет беглый обзор данных Выполняет беглый обзор данных Выдает информацию о температуре и давлении масла, количестве топлива, напряжении и силе тока генератора, параметрах дроссельной системы, количестве оборотов двигателя, температуре воды, силе тяги и т.д. Рис. 9.3. Альтернативный вариант сценария Monitor Train Systems LocomotiveAnalysisandReporting, система EnergyManagement (Управление электроэнергией) и модуль DataManagement (Управление данными). Как видим, система OnboardDisplaySystem обеспечивает взаимодействие между действующим лицом TrainEngineer и системой TTMS. Исполняя эту роль, она получает от действующего лица TrainEngineer команду выполнить мониторинг бортовых систем и, в свою очередь, передает запрос на получение соответствующих данных от каждой из этих трех систем. Затем обзорная информация о состоянии бортовых систем передается действующему лицу TrainEngineer для дальнейшего анализа. В этот момент действующее лицо TrainEngi-
426 Часть III. Приложения neer может ограничиться беглым обзором данных и завершить выполнение основного сценария. Однако в рамках альтернативного сценария действующее лицо TrainEngineer должно запросить у системы LocomotiveAnalysisand- Reporting, подающей тревожные сигналы, более подробную информацию. В ответ система OnboardDisplay получает от системы подробные данные для представления на экране. После анализа этой информации действующее лицо TrainEngineer возвращается на уровень беглого обзора данных о состоянии системы. Вопрос, следует ли на диаграмме деятельности, изображенной на рис. 9.3, представлять один (альтернативный) или оба (основной и альтернативный) варианта сценариев, зависит от соглашений, принятых в коллективе проектировщиков. Альтернативный сценарий, описанный выше, конкретизирует расширение функциональных возможностей сценария использования Monitor Train Systems с помощью сценария использования Predict Failure. Этот сценарий можно было бы добавить к диаграмме, показанной на рис. 9.3, для более полного описания возможностей системы, уточнив действия, выполняемые системой, когда действующее лицо TrainEngineer выдает запрос на оценку вероятности отказа подозрительной системы (condition: {request Predict Failure}). Этот вариант развития событий описан во врезке "Диаграмма обзора взаимодействия". Определение архитектуры системы TTMS Для проведения более строгого анализа функциональных возможностей, предусмотренного всеми сценариями использования системы TTMS, включая анализ влияния функциональных и нефункциональных технических требований и ограничений, используется блочная диаграмма, представленная на рис. 9.5 [2]. Система анализа состояния локомотива и выдачи отчетов состоит из цифровых и аналоговых датчиков, предназначенных для мониторинга параметров работы локомотива, включая температуру и давление масла, количество топлива, напряжение и силу тока генератора, параметры дроссельной системы, количество оборотов двигателя, температуру воды и силу тяги. Показания датчиков передаются машинисту через бортовую дисплейную систему, а также диспетчеру и обслуживающему персоналу по сети. Предупреждение или сигнал тревоги выдается и регистрируется в специальном журнале каждый раз, когда показания датчика выходят за пределы допустимого диапазона. Этот журнал используется при проведении эксплуатационных работ и для управления расходом топлива. Система управления энергией в режиме реального времени подсказывает машинисту наиболее эффективные установки двигательной и тормозной системы. Входными данными для этой системы являются: профиль и уклон пути, ограничения скорости, расписание, загрузка поезда и максимальная развиваемая мощ-
Глава 9. Система управления трафиком 427 Диаграмма обзора взаимодействия Существует еще один вариант представления сценария использования Monitor Train Systems — вместе с его основным и альтернативным вариантами — диаграмма обзора взаимодействия, показанная на рис. 9.4. sd MonitorTrainSystems у* 1 PerformOverviewSystemStatusMonitoring [иначе] [требуется более подробный мониторинг системы] *§> raf PerformDetailedSyetemStatusMonitoring [else] [требуется оценка вероятности отказа системы] «* , PerformFailurePredictionAnalysis Рис. 9.4. Альтернативный вариант сценария Monitor Train Systems Как следует из названия этой диаграммы, она демонстрирует результаты поверхностного обзора функциональных возможностей сценария использования Monitor Train Systems. Она показывает поток событий, возникающих в ходе взаимодействия. Эти события изображены в виде рамочек, в левом верхнем углу которых написано слово ref. Для того чтобы описать все детали каждого сценария — Perform Overview System Status Monitoring (Выполнить беглый обзор состояния системы), Perform Detailed System Status Monitoring (Выполнить детальный обзор состояния системы) и Perform Failure Prediction Analysis (Оценить вероятность отказа) — на месте ссылок на диаграммы обзора взаимодействия необходимо указывать реальные взаимодействия.
428 Часть III. Приложения Для детализации сценариев диаграмма обзора взаимодействия может использовать любой вид взаимодействия — последовательность, связь, синхронизацию или другой. Эту диаграмму можно использовать для изображения потоков управления через взаимодействия. Она особенно полезна для изображения долгих и сложных взаимодействий. Система глобального позиционирования Navstar & ЭУ7ТТ1. Система анализа состояния локомотива и выдачи отчетов Рис. 9.5. Блочная диаграмма системы TTMS ность. На основе этих данных система может определить оптимальные параметры работы дроссельной и тормозной систем, минимизующие расход топлива и согласованные с заданным расписанием и требованиями безопасности. Рекомендации системы, профиль и уклон пути, местоположение и скорость поезда выводятся на дисплей с помощью бортовой дисплейной системы.
Глава 9. Система управления трафиком 429 Бортовая дисплейная система обеспечивает человеко-машинный интерфейс машиниста. На дисплей выводится информация, поступающая от системы анализа состояния локомотива и выдачи отчетов, системы управления энергоснабжением и модуля управления данными. Для просмотра данных машинист может использовать специальные клавиши. Блок управления данными представляет собой коммуникационный шлюз для обмена информацией между бортовыми системами поезда и внешней сетью, в которую входят поезда, диспетчеры и другие пользователи. Отслеживание местоположения поезда осуществляется с помощью подключенных к сети транспондеров местоположения и глобальной спутниковой системы позиционирования Navstar. Система анализа состояния локомотива и выдачи отчетов может вычислять местоположение поезда с помощью навигационного счисления (dead reckoning) на основе счетчика, подсчитывающего количество оборотов колеса. Эта информация дополняется данными транспондеров местоположения, размещенных через каждую милю пути или на важнейших железнодорожных узлах. Транспондеры передают информацию о себе на проходящие поезда, используя собственные модули управления данными, что позволяет более точно определить местоположение. Кроме того, поезд может быть оснащен приемниками GPS, с помощью которых его местоположение можно определить с точностью до 10 ярдов. Модуль интерфейса путевых устройств размещается там, где есть какое-либо управляемое устройство (например, стрелка) или датчик (например, инфракрасный датчик для обнаружения перегрева колесных подшипников). Каждый модуль интерфейса может получать команды от местного наземного терминального контроллера (например, включить и выключить сигнал). Устройства могут быть переведены в ручной режим управления. Кроме того, каждое устройство может сообщать свои текущие параметры. Наземный терминальный контроллер обменивается информацией с модулями интерфейса путевых устройств, а также проходящими поездами. Эти контроллеры расположены вдоль железнодорожного пути через такие расстояния, чтобы любой поезд всегда находился в зоне действия хотя бы одного из них. Каждый наземный терминальный контроллер передает свою информацию в объединенную сетевую систему управления. Связь между этой системой и наземным терминальным контроллером может осуществляться по радио в ультракоротковолновом диапазоне, по наземным линиям или по оптическому волокну в зависимости от удаленности данного пункта. Сетевая система управления обеспечивает функционирование всей железнодорожной сети. Она может автоматически направлять информацию по другому маршруту, если на одном из альтернативных путей произойдет отказ оборудования, Сетевая система управления, в свою очередь, соединяется с одним или несколькими диспетчерскими центрами, образующими систему управления рельсовыми
430 Часть III. Приложения операциями, а также с другими пользователями. В системе управления рельсовыми операциями диспетчеры могут устанавливать маршруты движения поездов и отслеживать их передвижение. Каждый диспетчер контролирует свой собственный участок: каждая диспетчерская управляющая консоль может управлять одной или несколькими территориями. Маршрутизация поездов подразумевает выдачу инструкций для автоматического перевода поезда с одного пути на другой, установку ограничения скорости, управление пропуском автомобилей на переездах, разрешение и запрещение движения поезда по определенным участкам пути. Диспетчеры могут наблюдать за состоянием пути впереди по маршруту поезда и передавать эту информацию машинисту. В опасных ситуациях (нарушение графика, повреждение пути или возможность столкновения) поезда могут быть остановлены системой управления рельсовыми операциями (по команде диспетчера или автоматически). Диспетчеры могут также вывести на экран любую информацию, доступную машинистам отдельных поездов, разослать распоряжения, регламентирующие движение, установить параметры путевых устройств и пересмотреть план движения. Очевидно, что маршрутная схема и путевое оборудование со временем могут меняться. Количество поездов и маршруты их движения могут изменяться ежедневно. Следовательно, система TTMS должна обеспечивать возможность подключения новых датчиков, сетей и более совершенного оборудования. Нефункциональные требования — возможность сопровождения и эволюции системы TTMS — ясно показывают, что необходимо разработать гибкую архитектуру, способную изменяться со временем. Кроме того, оба ограничения означают, что система должна опираться на национальные стандарты (правительственные и промышленные) и максимально использовать серийно выпускаемое аппаратное оборудование и программное обеспечение. От проектирования системы к разработке аппаратного оборудования и программного обеспечения До сих пор мы проектировали систему, а не аппаратное оборудование и программное обеспечение, поскольку мы анализировали сценарии использования, описывающие основные функциональные возможности системы TTMS. Этот анализ позволяет построить блочную диаграмму, состоящую из основных элементов, образующих потенциальную архитектуру системы TTMS. Продолжая разработку, мы должны уточнить архитектуру низкоуровневого аппаратного оборудования и программного обеспечения, согласованную с принятой архитектурной концепцией. Потом следует решить, какая часть функциональных возможностей системы будет выполнена с помощью аппаратных, программных или ручных операций. Для этого необходимо усилить сотрудничество между коллективами, занимающи-
Глава 9. Система управления трафиком 431 мися разработкой систем, аппаратного оборудования, программного обеспечения и операций. Блочная диаграмма, представленная на рис. 9.6, отражает потенциальную архитектуру системы, разработанную с помощью объектно-ориентированного подхода. Непосредственным следствием этого подхода является компонентная природа этой архитектуры. Как видим, элементы системы TTMS, выполняющие основные функции, являются связными и слабосвязанными. Дальнейший анализ функциональных возможностей системы можно провести, конструируя совместно с экспертами в предметной области диаграммы деятельности, уточняющие взаимодействие между элементами. По мере спуска на более низкие уровни архитектурной иерархии необходимо уточнить взаимодействие между элементами системы и оценить поведение системы, используя диаграммы последовательностей, классов и прототипы. На рис. 9.6 приведена диаграмма последовательностей, иллюстрирующая один простой сценарий автоматизированного выполнения ежедневных поездных приказов. Она более подробно описывает работу системы TTMS, чем диаграмма деятельности, изображенная на рис. 9.2. Предположим, что этот сценарий начинается с момента, когда создан новый маршрутный план (см. рис. 9.2, на котором показаны основные события и элементы системы). Позднее нам придется описать в документации такие детали системы, как определение атрибутов, сигнатура операций и спецификации связей. Создает локальное расписание движения поезда Решает проблему столкновений (генерирует отчет об исключительной ситуации для диспетчера) Издает новый поездной приказ :TrainPian OperatlonsScheduler :LocaiPlan сг reportClashQ сг adaptQ findSchedutoQ Order orderQ *P Рис. 9.6. Сценарий выполнения ежедневных поездных приказов Завершив анализ функциональных возможностей системы TTMS (с помощью соответствующих уровней архитектуры), необходимо распределить технические требования к системе среди аппаратных, программных и даже операционных элементов системы. Выражение "даже операционных" использовано потому, что слишком часто люди считают, будто все на свете должно быть автоматизировано. Разумеется, эта задача типична, но следует понимать, что некоторые функ-
432 Часть III. Приложения циональные возможности, особенно в областях, связанных с обеспечением безопасности, должны (в некоторых случаях — по закону) реализовываться людьми. Иногда распределение технических требований среди аппаратного оборудования и программного обеспечения носит совершенно очевидный характер. Например, совершенно ясно, что для составления расписаний движения поездов следует использовать компьютерные программы, а бортовые дисплейные системы и дисплеи в центрах управления рельсовыми операциями создавать с помощью серийно выпускаемых терминалов. Решение о распределении функциональных возможностей среди аппаратного оборудования и программного обеспечения зависит от многих критериев, в частности, от возможностей повторного использования, доступности коммерческого оборудования, а также опыта и предпочтений разработчиков. Выбирая серийно выпускаемое оборудование, например, датчики, проектировщики перекладывают проектные решения на плечи компаний-поставщиков. Однако в целом справедливо следующее правило: программное обеспечение следует предпочесть, когда необходимо обеспечить гибкость системы, а аппаратное оборудование — когда на первом плане находится ее производительность. Для простоты предположим, что первоначальный вариант аппаратной архитектуры уже выбран. Этот выбор нельзя считать окончательным, но по крайней мере он дает отправную точку для распределения технических требований к программному обеспечению. В ходе анализа и проектирования необходима свобода выбора между аппаратной или программной реализацией той или иной функции, поскольку позднее может оказаться, что для обеспечения функциональной возможности требуется дополнительная аппаратура, или что ее можно более эффективно реализовать с помощью программных средств. На рис. 9.7 показано размещение аппаратного оборудования для системы TTMS, представленное в виде диаграммы развертывания Эта аппаратная архитектура соответствует блочной диаграмме системы, изображенной на рис. 9.5. В частности, на ней предусмотрен один бортовой компьютер на каждом поезде, соединяющий систему анализа состояния локомотива и выдачи отчетов, систему управления энергоснабжением, бортовую дисплейную систему и модуль управления данными. Предполагается, что каждый транспондер местоположения соединен с передатчиком, с помощью которого можно посылать сообщения на проходящий поезд, а компьютеры с транспондерами местоположения не соединены. С другой стороны, все группы путевых устройств (каждое из которых логически состоит из модуля интерфейса и переключателей) управляются путевым компьютером, способным взаимодействовать с проходящим поездом или наземным терминальным контроллером с помощью передатчиков и приемников. Связь между передатчиками и приемниками осуществляется с помощью радиоволн на ультракоротких частотах, наземных релейных линий и оптического волокна. Каждый наземный терминальный контроллер соединяется с локальной сетью, в которую входит местный диспетчерский центр, выполняющий функции системы управ-
Глава 9. Система управления трафиком 433 ления рельсовыми операциями. Для обеспечения бесперебойного обслуживания мы решили разместить на каждом диспетчерском центре два компьютера: основной и резервный, который включается в случае отказа основного компьютера. В свободное время резервный компьютер может использоваться для обслуживания пользователей, имеющих более низкий приоритет. Display «device» Transmitter & Receiver Train Computer Ц «device» Sensor «device» Location Transponder Ц 1 «device» Actuator «device» Transmitter Primary Dispatch Computer gj «device» Local Area У Network «device» Display Wayside Computer § j | Backup Diepatch Computer Ц «device» Switch 1 Рис. 9.7. Диаграмма развертывания системы TTMS С эксплуатационной точки зрения, система TTMS может состоять из сотен компьютеров: по одному в каждом поезде, по одному в каждом модуле интерфейса путевых устройств и по два в каждом диспетчерском центре. На диаграмме развертывания показаны лишь некоторые из них, так как показывать конфигурацию сходных компьютеров совершенно излишне. Для того чтобы сохранить контроль над разработкой любого сложного проекта, необходимо иметь надежные и ясные интерфейсы, обеспечивающие взаимодействие между основными элементами системы. Это особенно важно при определении интерфейсов аппаратного оборудования и программного обеспечения. Вначале интерфейсы могут быть нечеткими, но проектировщики должны быстро формализовать их, чтобы различные части системы можно было разрабатывать, тестировать и интегрировать одновременно. Хорошо определенные интерфейсы существенно облегчают поиск компромиссов между аппаратным оборудованием и программным обеспечением системы без переработок уже готовых частей. Бо-
434 Часть III. Приложения лее того, нельзя рассчитывать, что все разработчики, участвующие в крупном, возможно, глобально распределенном проекте, будут одинаково хорошо понимать работу всех частей системы. Следовательно, необходимо поручить спецификацию основных абстракций и механизмов самым лучшим системным архитекторам. Ключевые абстракции и механизмы Изучение требований, предъявляемых к системе TTMS, показывает, что проект сводится к решению четырех основных подзадач: 1. Работа в сети. 2. Организация базы данных. 3. Создание интерфейса "человек/компьютер". 4. Управление аналоговыми и цифровыми устройствами в реальном времени. Как нам удалось выяснить, что именно эти задачи порождают основной риск провала проекта? Систему объединяет в одно целое распределенная сеть связи. В виде радиосигналов сообщения циркулируют между транспондерами, поездами, наземными терминальными контроллерами и модулями интерфейсов путевых устройств. Кроме того, диспетчерские центры и отдельные наземные терминальные контроллеры также должны обмениваться сообщениями. Безопасная работа всей системы зависит от своевременной и надежной передачи и приема сообщений. Кроме того, система должна одновременно хранить информацию о текущем местоположении и планируемых маршрутах многих поездов. Она должна обеспечивать обновление и целостность информации даже при попытках одновременно записать и считать информацию из разных мест сети. По существу, эта задача сводится к созданию распределенной базы данных. Проектирование человеко-машинных интерфейсов порождает другую совокупность задач. В частности, пользователями системы в основном являются машинисты и диспетчеры, от которых не требуется умение работать с компьютером. Пользовательские интерфейсы операционных систем, таких как UNIX или Windows, могут быть вполне приемлемыми для программистов, но считаются недружелюбными по отношению к конечным пользователям приложений, таких как система управления железнодорожным движением. Следовательно, все формы взаимодействия должны быть тщательно разработаны с учетом особенностей конечных пользователей. В заключение отметим, что система TTMS должна взаимодействовать с множеством датчиков и исполнительных механизмов. Независимо от вида устройства, задачи измерения и управления похожи друг на друга и во всех частях системы должны решаться единообразно.
Глава 9. Система управления трафиком 435 Каждая из этих четырех подзадач связана со многими независящими друг от друга аспектами. Системные архитекторы должны идентифицировать основные абстракции и механизмы, существующие в каждой задаче, чтобы для их решения можно было привлечь экспертов в конкретных предметных областях. Следует подчеркнуть, что эти задачи не относятся ни к анализу, ни к проектированию. Их решение влияет лишь на архитектуру системы, а проектирование будет выявлять новые аспекты, для которых потребуется новый анализ. Таким образом, разработка всегда является последовательным и поступательным процессом. Краткий предметный анализ четырех основных подзадач показывает, что существуют три основные абстракции высокого уровня. 1. Поезда — локомотивы и вагоны. 2. Пути — профиль, уклон и путевые устройства. 3. Планы — расписания, приказы, разрешения, полномочия и назначение поездных бригад. Каждый поезд имеет текущее положение на маршруте и только один действующий план движения. Аналогично, в каждой точке маршрута может находиться не больше одного поезда, а каждый план относится только к одному поезду, но связан со многими пунктами маршрута. Продолжая анализ, можно выделить основные механизмы для каждой из четырех почти не связанных между собой подзадач. 1. Передача сообщений. 2. Планирование расписаний движения поездов. 3. Отображение информации. 4. Сбор показаний датчиков. Эти четыре механизма составляют сущность разрабатываемой системы. Они порождают наибольший риск неудачи проекта. Следовательно, очень важно, чтобы исследование альтернативных подходов проводили самые лучшие системные архитекторы. В результате возникнет среда разработки, с помощью которой менее опытные разработчики смогут собрать остальные части системы. 9.3 Конструирование Разработка архитектуры подразумевает выявление основной структуры классов и спецификацию общих взаимодействий между классами. Эти механизмы должны находиться в центре внимания уже на самых ранних этапах проекта. Это позволит выявить элементы наибольшего риска и правильно отразить архитектурную концепцию системы. Результаты этого этапа образуют среду разработки,
436 Часть III. Приложения состоящую из классов и взаимодействий между ними, на основе которой конструируются остальные функциональные элементы системы. В начале раздела изучается семантика каждого из четырех основных механизмов: передачи сообщений, планирования расписаний движения поездов, отображения информации, сбора данных от датчиков. Затем мы обсудим вопросы управления выпусками, образующими последовательный и поступательный процесс разработки. В заключении раздела мы проанализируем, как системная архитектура поддерживает спецификации подсистем TTMS. Механизм передачи сообщений Под сообщением подразумевается не вызов методов, как это принято в объектно-ориентированных языках программирования, а концепция из словаря предметной области, находящаяся на более высоком уровне абстракции. Например, типичными сообщениями в системе TTMS является сигнал активации путевого устройства, отметка о проезде определенных пунктов маршрута и приказы, которые диспетчеры отдают машинистам. В целом, все эти виды сообщений передаются в системе TTMS на двух разных уровнях. 1. Между компьютерами и устройствами. 2. Между компьютерами. Рассмотрим второй уровень передачи сообщений. Поскольку решение поставленной задачи основано на использовании географически распределенной сети связи, необходимо учесть такие факторы, как помехи, отказы оборудования и секретность сообщений. При идентификации сообщений можно сначала определить пары взаимодействующих компьютеров по диаграмме развертывания (см. рис. 9.7). Для каждой такой пары нужно ответить на три вопроса. 1. Какую информацию обрабатывает каждый компьютер? 2. Какая информация будет передаваться с одного компьютера на другой? 3. К какому уровню абстракции будет относиться эта информация? Ответить на эти вопросы сразу невозможно. Следует действовать постепенно, пока не возникнет уверенность, что нам удалось выявить правильные сообщения и в системе нет узких мест, возникающих, когда в одном канале связи накапливается слишком много сообщений или сообщения слишком велики или малы. На данном этапе проектирования крайне важно сосредоточить внимание на сути, а не на форме сообщений. Слишком часто системные архитекторы начинают проектирование с выбора представления сообщений на уровне битов. При решении реальной задачи преждевременный выбор низкоуровневого представления сообщений в будущем обязательно подвергнется изменениям и нарушит работу
Глава 9. Система управления трафиком 437 всех клиентов, зависящих от данного представления. Более того, на данном этапе проектирования еще нет достаточной информации о способах использования этих сообщений, и проектировщики не могут принимать эффективные решения о их представлении. Концентрируя внимание на сути сообщений, следует рассмотреть внешний вид каждого класса сообщений. Иначе говоря, необходимо установить роли и обязанности каждого сообщения, а также указать, какие операции можно выполнить для их обработки. Диаграмма классов, представленная на рис. 9.8, отражает проектные решения, касающиеся некоторых наиболее важных сообщений, циркулирующих в системе TTMS. Следует подчеркнуть, что все сообщения в конечном счете являются экземплярами абстрактного класса Message, инкапсулирующего поведение, присущее всем сообщениям. Три класса более низкого уровня описывают основные категории сообщений: TrainStatusMessage (Сообщение о состоянии поезда), TrainPlanMessage (Сообщение о плане движения поезда), WaysideDe- viceMessage (Сообщение путевого устройства). Каждый из этих трех классов в дальнейшем конкретизируется. Окончательный проект может содержать десятки специализированных классов. На данном этапе существование этих промежуточных классов становится еще более важным, поскольку без них многочисленные компоненты остались бы не связанными между собой и их работу было бы сложно поддерживать. По мере развития проекта будут, скорее всего, обнаружены другие важные группы сообщений — мы сконструируем для них новые промежуточные классы. К счастью, такая реорганизация иерархии классов имеет очень слабое семантическое влияние клиентов, использующих базовые классы. В рамках архитектурного проектирования сначала необходимо стабилизировать интерфейсы основных классов сообщений. Этот процесс можно начать с предметного анализа наиболее важных классов иерархии, чтобы сформулировать их роли и обязанности. Разработав интерфейсы наиболее важных сообщений, можно приступать к созданию программ, основанных на этих классах и предназначенных для моделирования процессов создания и приема потоков сообщений. Эти программы можно использовать как временный инструмент для тестирования различных частей системы в ходе проектирования еще до момента, когда будет завершена разработка интерфейсов частей системы, которые будут с ними взаимодействовать. Совершенно очевидно, что диаграмма классов, представленная на рис. 9.8, неполна. На практике проектировщикам часто удается сразу определить основные сообщения, а все остальные выявлять по мере того, как будут обнаруживаться менее общие формы взаимодействия. Использование объектно-ориентированной архитектуры позволяет последовательно добавлять эти сообщения, не нарушая существующий проект системы, поскольку такие изменения сохраняют совместимость с ранее разработанными классами.
438 Часть III. Приложения {abstract} TrainStatusMessage StopMessage I Рис. 9.8. Диаграмма классов Message Если структура классов удовлетворительна, можно начать проектирование самого механизма передачи сообщений. Этот механизм преследует две противоречивые цели: обеспечивать надежную доставку сообщения, но делать это на таком высоком уровне абстракции, чтобы клиенту не надо было заботиться о способе доставки сообщения. Такой механизм передачи сообщений позволяет клиентам ограничиваться упрощенным представлением о процессах приема и передачи. На рис. 9.9 представлен сценарий, отражающий результаты проектирования механизма передачи сообщений. Как показано на диаграмме, для того чтобы послать сообщение, клиент сначала создает новое сообщение т, а затем передает его по радио диспетчеру своего узла, на которого возложена обязанность ставить сообщение в очередь для последующей отправки. Обратите внимание на то, что проект использует четыре активных объекта (каждый из которых имеет свой собственный поток управления), о чем свидетельствуют вертикальные линии внутри соответствующих прямоугольников: Client, messageMgr: Queue, messageMgr' : Queue и Receiver. Кроме того, следует подчеркнуть, что менеджер сообщений получает сообщения для отправки по радио как параметр, а затем использует объект Transporter для приведения сообщения в канонический вид и дальнейшей передачи его по сети.
Глава 9. Система управления трафиком 439 :Client 2: broadcast(m) - messageMgr :Queue Τ 1η< ■ new() Создается во время передачи сообщения Пересекает Е\ границы узла Τ 3 si treamout(m) transporter I* broadcast(m) listener 7 nextMessage()- messageMgr* :Queue 5: streamm(m) ΪΪ vmm'mmrmwmnmi»'' Создается во ks время передачи сообщения 6: new(m') m* :Message Рис. 9.9. Механизм передачи сообщений Как следует из диаграммы, передача сообщения представляет собой асинхронную операцию — обозначенную открытой стрелкой, — поскольку мы не хотели, чтобы клиент ожидал, пока сообщение, поступающее по радио, будет зашифровано, расшифровано и, возможно, повторно передано по линии связи из-за помех. В итоге некий объект класса Listener (Слушатель), находящийся в другой части сети, примет сообщение, приведет его в канонический вид и отправит диспетчеру своего узла, который, в свою очередь, создаст параллельное сообщение и поставит его в очередь. Получатель может заблокировать начало очереди сообщений, ожидая поступления следующего сообщения, которое передается как параметр синхронной операции nextMessage (). При проектировании диспетчера сообщений мы расположили его на уровне приложений в сетевой модели ISO Open Systems Interconnection (OSI) [3]. Это позволяет всем клиентам, принимающим и передающим сообщения, функционировать на самом высоком уровне абстракции, т.е. обмениваться сообщениями, имеющими специфический для данного приложения характер. Вероятно, окончательная реализация этого механизма будет немного более сложной. Например, может возникнуть необходимость шифровать и дешифровать сообщения, а также использовать коды обнаружения и исправления ошибок,
440 Часть III. Приложения чтобы обеспечить надежную связь в условиях помех на линиях связи и возможных отказов оборудования. Планирование расписания движения поездов Как указывалось ранее, концепция плана движения поезда является центральной для функционирования системы TTMS. Каждый поезд имеет только один активный план, а каждый план предназначен только для одного поезда и может содержать много различных приказов и точек на маршруте. На первом этапе необходимо точно определить, из каких частей состоит план движения поезда. Для этого следует перечислить всех потенциальных клиентов плана и выяснить, как они его используют. Например, некоторые клиенты могут иметь право создавать планы, другие — изменять их, а остальные могут их только читать. В этом смысле план движения поезда представляет собой хранилище всей информации, связанной с маршрутом одного отдельного поезда и действиями во время движения, например, отцеплением или прицеплением вагонов. На рис. 9.10 продемонстрированы стратегические проектные решения, касающиеся структуры класса TrainPlan. Для того чтобы показать части, из которых состоит план движения поезда, использована диаграмма класса (как альтернатива традиционной диаграмме сущность-отношение). Итак, каждый план движения поезда состоит одной бригады и может включать в себя много приказов и действий. Эти действия упорядочены во времени и с каждым из них связана определенная информация, такая как время, местоположение, скорость, ответственное лицо, приказы. Например, план может содержать следующие действия, перечисленные в табл. 9.1. Таблица 9.1. Действия, которые может предусматривать план движения поезда Время Положение Скорость Ответственное лицо Приказ 0800 Pueblo Как указано Начальник депо Покинуть депо 1100 Colorado Springs 40 миль/ч Отцепить 30 вагонов 1300 Denver 40 миль/ч Отцепить 20 вагонов 1600 Pueblo Как указано Вернуться в депо Как следует из диаграммы 9.10, класс TrainPlan включает поле Uniqueld, содержащее число, однозначно идентифицирующее каждый экземпляр класса TrainPlan. Поскольку информация является сложной, классы, указанные на этой диаграмме, которые можно было бы рассматривать как атрибуты некоего класса, на самом деле являются самостоятельными. Например, класс Uniqueld не просто хранит уникальный идентификационный номер. Он содержит разно-
Глава 9. Система управления трафиком 441 протяжении всего срока службы системы TTMS "К TrainPian Crew UnlquelD Order Authority Рис. 9.10. Диаграмма класса TrainPian образные атрибуты и операции, необходимые для обеспечения согласованности с национальными и международными стандартами. Кроме того, на бригаду поезда также накладываются ограничения, например, они могут выполнять свою работу только в определенных пунктах маршрута или придерживаться ограничений по скорости на конкретных участках пути в указанное время. Аналогично разработке класса Message и его подклассов, можно в первую очередь выполнить проектирование наиболее важных элементов плана движения поезда, а их детали уточнять по мере того, как планы станут использоваться разными клиентами. Наличие огромного количества активных и неактивных планов движения поездов ставит перед нами проблему разработки базы данных, упомянутую ранее. Диаграмма классов, показанная на рис. 9.10, может служить эскизом логической схемы этой базы данных. Возникает простой вопрос: где хранится план движения поезда? В идеальном мире, где нет помех или задержек при передаче данных и где компьютерные ресурсы неограничены, можно было бы хранить все планы движения поездов в единой центральной базе данных. Такой подход гарантировал бы существование единственного экземпляра каждого плана. Однако реальный мир
442 Часть III. Приложения несовершенен, поэтому такое решение непрактично. Необходимо учитывать задержки при передаче данных и ограниченную производительность процессоров. Таким образом, хранение плана движения поезда в централизованной базе данных не соответствует требованиям, предъявляемым к системам реального времени. Однако с помощью программного обеспечения можно создать иллюзию отдельной централизованной базы данных. Для этого планы движения поездов следует хранить в компьютерах диспетчерского центра, а их копии будут по мере необходимости распределяться по узлам сети. Для обеспечения эффективности компьютер каждого поезда может хранить копию своего текущего плана. Таким образом, бортовое программное обеспечение может получать нужные сведения с пренебрежимо малыми задержками. Если план изменится в результате действий диспетчера или (что менее вероятно) по решению машиниста, программное обеспечение должно гарантировать, что все копии этого плана будут своевременно обновлены. Сценарий передачи и обновления копий зависит от механизма планирования расписаний движения поездов, показанного на рис. 9.11. Исходный вариант плана движения каждого поезда находится в централизованной базе данных, расположенной в диспетчерском центре, а его копии могут быть разосланы по всей сети. Как только какой-либо клиент запросит копию конкретного плана движения поезда (используя операцию get () с уникальным идентификатором Unique Id, передаваемым в качестве аргумента), исходная версия копируется и передается клиенту как параметр, а местоположение копии регистрируется в базе данных. Теперь предположим, что в результате действий машиниста клиент хочет изменить план движения поезда. В таком случае сначала клиент должен вызвать операцию копирования плана и модифицировать состояние копии. Затем сообщение об изменениях пересылается в централизованную базу данных на диспетчерский центр, что позволяет учесть сделанные изменения в исходном плане. Поскольку местоположение каждой копии данного плана движения поезда зарегистрировано в централизованной базе данных, после изменения исходного варианта можно разослать сообщения остальным клиентам и внести изменение во все остальные копии плана. Для того чтобы гарантировать согласованность изменений во всех узлах сети, можно использовать механизм блокировки записей, так что никакие изменения не будут сделаны, пока не будут обновлены все копии исходного варианта. Этот механизм одинаково правильно работает и в том случае, когда изменения в план движения вносит диспетчер. Сначала обновляется исходный вариант плана в базе данных, а затем сообщения об изменениях всех копий рассылаются по сети остальным клиентам с помощью аналогичного механизма. Как именно осуществляется передача изменений? Для этого используется механизм передачи сообщений, разработанный ранее. В частности, может возникнуть необходимость добавить в проект новые сообщения, связанные с планом движения поезда, и по-
Глава 9. Система управления трафиком 443 Объекты — -к зеркальные отображения 1· modifyO .Client TrainPlan Ι 4: get(UniquelD) 2: modifyO databaseMgr :Plan TrainPlan 3 modifyO 1\ Персистентный Рис. 9.11. Планирование расписания движения поезда строить механизм изменения планов движения поездов на базе уже существующего низкоуровневого механизма передачи сообщений. Использование серийно выпускаемых систем управления базами данных на диспетчерских компьютерах позволяет выполнять любые операции, связанные с резервированием данных, их восстановлением, ведением регистрационного журнала и обеспечением секретности информации. Отображение информации Как уже отмечалось, использование серийно выпускаемых технических средств для управления базой данных позволяет сосредоточить внимание на специфике задачи. Использование стандартных графических инструментов позволяет добиться аналогичных результатов при отображении информации на дисплеях. Это резко поднимает уровень абстракции системы, так что разработчикам не надо беспокоиться о визуальном представлении объектов на уровне пикселей. Кроме того, очень важно инкапсулировать проектные решения о визуальном представлении различных объектов. Рассмотрим, например, отображение информации о профиле и уклоне конкретных участков маршрута. Предположим, что изображение должно появляться в двух местах: на дисплее в диспетчерском центре и на бортовом дисплее поезда (на котором отображается только участок пути впереди поезда). Предположим, что нами уже разработан класс, экземпляры которого описывают участки пути. Тогда можно проанализировать два подхода к визуализации состояния таких объектов. Во-первых, можно предусмотреть некий специальный управляющий объект, создающий визуальное представление заданного объекта по запросу Во-вторых,
444 Часть III. Приложения можно исключить создание внешнего объекта и инкапсулировать знание о способах отображения объекта. Второй подход предпочтительней, поскольку он проще и точнее отражает сущность объектной модели. Однако этот подход не лишен потенциальных недостатков. В итоге мы можем получить множество разновидностей отображаемых объектов, каждый из которых создан разными группами разработчиков. Если каждый отображаемый объект будет обрабатываться отдельно, то может возникнуть избыточный код, разнобой стилей реализации и вообще невообразимая путаница. Намного лучше провести предметный анализ всех разновидностей отображаемых объектов, выделить их общие элементы и создать набор промежуточных классов, обеспечивающий визуальное изображение этих общих элементов. В свою очередь, промежуточные классы можно создать на основе низкоуровневых графических пакетов, выпускаемых серийно. Схема, иллюстрирующая использование общих вспомогательных классов при реализации всех отображаемых объектов, представлена на рис. 9.12. Эти вспомогательные классы, в свою очередь, используют низкоуровневый интерфейс системы Windows, скрытый от всех высокоуровневых классов. С практической точки зрения интерфейсы, такие как функции Windows API, трудно реализовать в одном классе. Следовательно, диаграмма немного упрощена. Вероятно, реализация потребует нескольких классов Windows API и специальных утилит. Train Track V TralnPlan А TralnDleplayUtillty Ύ Windows API Рис. 9.12. Вспомогательные классы для отображения объектов Основное преимущество этого подхода заключается в ограниченном влиянии изменений, возникающих при перераспределении роли аппаратуры и программ на
Глава 9. Система управления трафиком 445 низком уровне. Например, если потребуется заменить дисплеи на более или менее мощные, придется переделать процедуры только в классе TrainDisplayUti- lities. Иначе при любых изменениях на нижнем уровне пришлось бы модифицировать каждый отображаемый объект. Сбор показаний датчиков Как следует из технических требований, система TTMS должна содержать большое количество разнообразных датчиков. Например, на каждом поезде датчики следят за температурой масла, количеством топлива, дроссельной установкой, температурой воды, нагрузкой на двигатель и т.д. Активные датчики некоторых путевых устройств сообщают текущее положение своих переключателей и передают сигналы. Все значения, возвращаемые датчиками, отличаются друг от друга, но их обработка в основном производится сходным образом. Более того, большинство датчиков должны периодически проходить тестирование. Если показатель лежит в определенном диапазоне, то ничего особенного не происходит — просто пользователь получает новую величину. Если показатель превышает определенный уровень, то клиенты должны получить предупреждения. Если же показатель выходит за пределы допустимого диапазона (например, давление масла на локомотиве падает до опасного уровня), то следует подать сигнал тревоги и уведомить клиентов о необходимости принять решительные меры. Воспроизведение этого поведения для каждого вида датчиков не только утомительно и чревато ошибками, но и приводит к избыточному объему кода. Если не выделить общие свойства всех датчиков, то разные разработчики предложат разные решения одной и той же задачи на основе немного отличающихся друг от друга сенсорных механизмов, что приведет к сложностям при сопровождении системы. Следовательно, крайне желательно провести предметный анализ всех периодически опрашиваемых аналоговых датчиков и предложить общий сенсорный механизм, приемлемый для всех видов датчиков. Для этого можно воспользоваться архитектурой, включающей в себя иерархию классов, описывающих работу датчиков и механизмов, периодически опрашивающих датчики. Управление версиями Поскольку мы придерживаемся поступательного подхода в разработке систем, следует рассмотреть вопросы применения методов управления версиями и глубже проанализировать архитектуру системы, а также спецификации ее подсистем. Сначала мы выберем несколько сценариев, представляющих особый интерес, и сделаем вертикальный срез нашей архитектуры, а затем опишем модули, имитирующие выполнение этих сценариев. Например, в качестве основных сценариев можно выбрать следующие: Route Train, Monitor Train Systems и Monitor Traffic. В совокупности ре-
446 Часть III. Приложения ализация этих сценариев затрагивает практически все критически важные аспекты архитектуры, фокусируя внимание проектировщиков на оценке стратегических решений. После достижения очередной контрольной точки можно переходить к выпуску очередной версии программного обеспечения, следуя описанному ниже алгоритму. 1. Создать план движения поезда, основанный на существующем варианте; модифицировать план поезда. 2. Запросить подробный мониторинг систем, вызывающих подозрение; запросить оценку вероятности отказа системы; запросить оценку вероятности отказа системы у эксплуатационника. 3. Вручную предотвратить столкновение; запросить автоматизированную помощь при предотвращении столкновения; отслеживать трафик с помощью ресурсов системы TTMS и Navstar GPS. В 12- и 18-месячных циклах разработки периодичность выпусков новых версий может составить три месяца, причем каждая новая версия наследует функциональные возможности своих предшественников. Проделав эту работу, мы выполним все сценарии, существующие в системе. Основа успеха этой стратегии — управление риском. Для этого при выпуске каждой версии разработчики должны определить наиболее опасные риски и предложить способы их уменьшения. Для систем управления, подобной описываемой в этой главе, это означает проведение тестов на ранних этапах проектирования (чтобы выявить любые дефекты на стадии, когда их еще можно устранить). Выпуск последовательных версий программного обеспечения предусматривает широкий выбор сценариев, охватывающих функциональные возможности системы, чтобы в анализе не осталось "белых пятен". Архитектура системы Разработка программного обеспечения для очень крупных систем часто начинается еще до завершения сборки аппаратного оборудования. Эта работа часто занимает больше времени, чем проектирование технических средств. В любом случае на всем протяжении разработки необходимо обеспечивать согласованность между программным и аппаратным обеспечением. Следовательно, проектировщики должны стремиться к тому, чтобы программное обеспечение было как можно более независимым от аппаратных требований, так чтобы его разработку программного обеспечения можно было проводить в отсутствие устойчивой технической среды. Кроме того, это значит, что программное обеспечение должно разрабатываться с учетом взаимозаменяемых подсистем. В системах управления и контроля, таких как TTMS, проектировщики могут воспользоваться преимуществами новой технологии, которая может возникнуть в ходе разработке.
Глава 9. Система управления трафиком 447 Уже на ранних этапах разработки необходимо провести разумную декомпозицию системного программного обеспечения, так чтобы субподрядчики могли работать параллельно. Часто на декомпозицию системы влияют многочисленные причины, не имеющие технического характера. Наиболее важными среди них является распределение работы среди независимых разработчиков. Отношения между субподрядчиками обычно устанавливаются на ранних стадиях разработки сложных систем, часто задолго до поступления информации о технических решениях, касающихся декомпозиции системы. Как выбрать подходящую декомпозицию подсистемы? Объекты высокого уровня часто объединяются по функциональному признаку. Это не противоречит принципам объектной модели, поскольку термин функциональный означает не арифметическую абстракцию, включающую в себя ввод-вывод данных. Речь идет о сценариях, описывающих прозрачное и проверяемое поведение, являющееся следствием взаимодействия между логически связанными объектами. Таким образом, абстракции и механизмы наивысшего уровня, выявленные на первых этапах, являются приемлемыми кандидатами, вокруг которых можно организовывать систему. Сначала можно установить существование таких подсистем, а затем со временем уточнять их интерфейс. Проектные решения, касающиеся высокоуровневой архитектуры системы TTMS, представлены на диаграмме компонентов, показанной на рис. 9.13. Как видим, система имеет слоистую архитектуру, охватывающую функции четырех подсистем, идентифицированных ранее, а именно: сеть, база данных, человеко- машинный интерфейс и средства управления в реальном времени. Спецификация подсистем Рассмотрев внешнее представление любой из этих подсистем, легко обнаружить, что она обладает всеми характеристиками объекта. Каждая подсистема имеет уникальную, хотя и статичную, индивидуальность и большое количество состояний, демонстрируя очень сложное поведение. Подсистемы служат хранилищами других подсистем и классов. Они точнее всего характеризуются ресурсами, которые экспортируются через интерфейсы (такие как функции NetworkSer- vices), предоставляемые подсистемой NetworkFacilities (см. рис. 9.13). Диаграмма компонентов, показанная на рис. 9.13, является всего лишь отправной точкой для разработки архитектуры подсистем TTMS. Эти подсистемы высокого уровня в дальнейшем раскладываются на более мелкие подсистемы более низкого уровня. Рассматривая подсистему NetworkFacilities (Средства работы в сети), мы разбили ее на две другие подсистемы: закрытую RadioCom- munication (Радиосвязь) и открытую Messages (Сообщения). Закрытая подсистема скрывает детали программного управления физическими устройствами
448 Часть III. Приложения DeviceControl DeviceControl L a «subsystem» UserApplications I PersistenceServices PersistenceServices NetworkServioes [Per !t «subsystem» Devices ffl PersistenceServices «subsystem» a J Network Service· I NetworkServices 4* JNetv NetworkServices s «subsystem» NetworkFacllltles Рис. 9.13. Высокоуровневая диаграмма компонентов системы TTMS радиосвязи, а открытая подсистема обеспечивает функционирование механизма передачи сообщений, разработанного ранее. Подсистема Databases (Базы данных) построена на основе ресурсов подсистемы NetworkFacilities и реализует механизм разработки планов движения поезда, описанных ранее. Эта система подразделяется на две открытые подсистемы: TrainPlanDatabase (База данных планов движения поездов) и Track- Database (Маршрутная база данных). В системе предусмотрена также закрытая подсистема DatabaseManager (Менеджер баз данных), обеспечивающая все услуги, общие для этих двух баз данных. В подсистеме Devices (Устройства) программы, относящиеся ко всем путевым устройствам, объединяются в одну подсистему, а программы, связанные с бортовыми механизмами и датчиками локомотива, — в другую. Эти две подсистемы доступны клиентам подсистемы Devices и построены на основе ресурсов подсистем TrainPlanDatabase и Messages. Таким образом, подсистема Devices обеспечивает реализацию механизма датчиков, описанного выше. В заключение отметим, что подсистема верхнего уровня UserApplications (Прикладные программы) разделяется на несколько небольших подсистем, включая EngineerApplications (Функции машиниста) и DispatcherAp- plications (Функции диспетчера), чтобы продемонстрировать разную роль двух главных пользователей системы TTMS. Подсистема EngineerApplications содержит ресурсы, обеспечивающие взаимодействие машиниста и борто-
Глава 9. Система управления трафиком 449 вых систем и предусмотренные в технических требованиях к системе, в частности, система анализа состояния локомотива и выдачи отчетов и система управления энергоснабжением. Подсистема DispatcherApplicatlons обеспечивает взаимодействие между диспетчером и компьютером. Подсистемы Engineer- Applications и DispatcherApplicatlons используют общие закрытые ресурсы, обеспечиваемые подсистемой Displays (Дисплеи), реализующей описанный ранее механизм отображения информации. Проектирование позволило выделить четыре подсистемы верхнего уровня и несколько подсистем более низкого уровня, в которых размещены все основные абстракции и механизмы, изобретенные ранее. Эти подсистемы распределены среди коллективов разработчиков, определяющих интерфейсы взаимодействия между ними на одном и том же уровне абстракции. Такой подход к декомпозиции крупных и сложных задач позволяет проанализировать разрабатываемую систему с разных точек зрения. Таким образом очередной выпуск системы представляет собой совокупность совместимых версий всех подсистем, и таких выпусков может быть много — по одному на каждого разработчика, один — для тестирования разработчиками и, возможно, еще один — для тестирования пользователями. Прежде чем передавать разработку в распоряжение всей команды, отдельные проектировщики могут создавать собственные стабильные выпуски системы. В них объединяются новые версии программного обеспечения, разработкой которых занимаются эти специалисты. Основой успеха является тщательное конструирование интерфейсов подсистем. После определения интерфейсы должны быть хорошо защищены. Как определяется внешний вид каждой подсистемы? Для этого каждую подсистему следует рассматривать как объект. Таким образом, необходимо задать вопросы, которые уже ставились по отношению к намного более простым объектам: какие состояния имеет объект? какие действия над ним может выполнить клиент? каких действий он требует от других объектов? Например, рассмотрим подсистему TrainPlanDatabase. Она строится на основе трех других подсистем (Messages, TrainDatabase, TrackDatabase) и имеет нескольких важных клиентов — подсистемы WaysideDevices (Путевые устройства), LocomotiveDevices (Бортовые устройства), EngineerAppli- cations (Функции машиниста) и DispatcherApplicatlons (Функции диспетчера). Подсистема TrainPlanBatabase хранит относительно простые состояния всех планов движения поездов. Разумеется, хитрость заключается в том, что эта подсистема должна поддерживать функционирование распределенного механизма передачи планов движения поездов. Снаружи клиент видит монолитную базу данных, но изнутри эта база данных является распределенной, и поэтому использовать механизм передачи сообщений подсистемы Messages нельзя. Какие действия можно выполнять с помощью TrainPlanDatabase? По- видимому, к ней применимы все обычные операции: добавление, удаление и из-
450 Часть III. Приложения менение записей, а также запросы. Проектные решения, касающиеся этой подсистемы, необходимо зафиксировать в форме классов, содержащих объявления этих операций. На этой стадии следует перейти к проектированию подсистем. Напомним, что интерфейсы практически никогда не определяются сразу и навсегда. Как показывает опыт, если интерфейсы разработаны в соответствии с объектно-ориентированными принципами, то большинство изменений оказываются совместимыми "снизу-вверх". 9.4 Эксплуатация Надежная и полезная система управления постоянно совершенствуется. Это не означает, что она никогда не достигает устойчивого состояния. Наоборот, это условие должно выполняться в каждом выпуске системы. В действительности, системы, занимающие центральное место в конкретном бизнесе, например, в управлении железнодорожными перевозками, должны постоянно адаптироваться к изменениям деловых реалий. В противном случае система станет не активом, а пассивом. Несмотря на то что основной риск, с которым связаны изменения системы TTMS, носит технический характер, существуют также политические и социальные риски. Однако эластичная объектно-ориентированная система предоставляет проектировщикам много степеней свободы, позволяя адаптировать изменения правил и рыночных законов. Система TTMS позволяет добавлять существенные функциональные возможности, например, обработку платежной ведомости. Предположим, обработка платежных ведомостей железнодорожной компании осуществляется с использованием устаревших технических средств, снятых с производства, и поэтому возник большой риск навсегда потерять всю систему платежей в результате одной серьезной поломки. По этой причине обработку платежной ведомости следует интегрировать в систему TTMS. Нетрудно понять, как эти две несвязанные задачи могут сосуществовать. Для этого можно просто рассматривать их как отдельные приложения, причем обработка платежной ведомости происходит в фоновом режиме. Дальнейший анализ показывает, что интеграция обработки платежной ведомости может принести огромную пользу. Напомним, что планы движения поездов, помимо всего прочего, содержат информацию о распределении бригад. Следовательно, можно сравнить запланированное и реальное распределение бригад, вычислить рабочее время, сверхурочные часы и т.д. Получая эту информацию непосредственно, можно точнее и быстрее обрабатывать платежную ведомость. Как добавление этой функции влияет на существующий проект? Очень слабо. Наш подход предусматривает включение в подсистему UserApplications
Глава 9. Система управления трафиком 451 новой подсистемы для обработки платежных ведомостей. Из этой точки системы в подсистеме будут видны все важные механизмы, необходимые для ее функционирования. Всем хорошо структурированным объектно-ориентированным системам присуще общее свойство: значительные дополнения к требованиям можно довольно просто учесть путем включения новых функций в существующие механизмы. Включение в систему TTMS экспертной подсистемы, помогающей диспетчеру определять маршруты и реагировать на чрезвычайные ситуации, представляет собой более существенное изменение. Как это может повлиять на архитектуру системы? Ответ прежний — это изменение слабо влияет на архитектуру системы. Можно разместить новую подсистему между подсистемами TrainPlanDatabase и DispatcherApplications, так как база знаний, созданная для экспертной системы, аналогична системе TrainPlanDatabase. Более того, подсистема DispatcherApplications является единственным клиентом экспертной системы. Следовательно, необходимо разработать новый механизм представления рекомендаций конечному пользователю. Например, можно использовать архитектуру информационной доски. Одна из замечательных характеристик хорошо спроектированных архитектур состоит в стремлении достичь определенной критической массы функциональных свойств. Иначе говоря, если функции и структура системы определены правильно, то пользователи вскоре могут выявить такие возможности, которые проектировщики не могли даже предвидеть. Такие способы взаимодействия пользователя с системой целесообразно формализовать и включать в архитектуру. Возможность по-новому использовать существующие механизмы, сохраняя тем самым целостность проекта, является характерным признаком хорошо спроектированной архитектуры.
ГЛАВА 10 ИСКУССТВЕННЫЙ ИНТЕЛЛЕКТ: КРИПТОАНАЛИЗ Мыслящие существа демонстрируют очень сложные формы поведения, руководствуясь сознанием, механизмы которого мы знаем очень плохо. Подумайте, например, о том, как вы планируете маршрут поездки по городу, чтобы выполнить полученные задания. Попробуйте понять, как, перемещаясь по тускло освещенной комнате, вам удается различить границы предметов и избежать столкновения. Поразмышляйте о том, как вам удается сосредоточиться на беседе с одним собеседником на вечеринке, где десятки людей говорят одновременно. Ни одна из этих задач не имеет простого алгоритмического решения. Планирование маршрута относится к классу NP-полных задач. Перемещение в темноте связано с анализом нечеткой (в буквальном смысле этого слова) и неполной зрительной информации. Идентификация речи одного человека среди множества источников звука требует от слушателя умения выделять полезную информацию из шума и отфильтровывать все ненужные сообщения из остальной какофонии. Исследователи в области искусственного интеллекта изучают эти и подобные проблемы, стремясь понять процессы познания человека. Эта работа часто связана с построением интеллектуальных систем, имитирующих некоторые аспекты поведения человека. Ерман (Erman), Ларк (Lark) и Хейес-Рот (Hayes- Roth) указывают, что "интеллектуальные системы отличаются от традиционных следующими признаками (не обязательно всеми сразу). • Способность преследовать цели, изменяющиеся с течением времени. • Умение усваивать, использовать и преобразовывать знания. • Возможность использования разнообразных специализированных подсистем с помощью множества специально выбранных методов.
Глава 10. Искусственный интеллект: криптоанализ 453 • Способность обеспечить интеллектуальное взаимодействие с пользователями и другими системами. • Умение самостоятельно распределять собственные ресурсы и внимание" [1]. Создание систем, обладающих хотя бы одним из перечисленных признаков, представляет собой очень трудную задачу. Еще сложнее разработать интеллектуальную систему для использования в прикладных областях, связанных с безопасностью жизни и собственности, например, для медицинской диагностики и диспетчеризации авиарейсов. Такие системы никогда не должны создавать опасность, а искусственный интеллект редко основывается на здравом смысле. Несмотря на то что успехи в этой области знаний чересчур преувеличены отдельными энтузиастами, теория искусственного интеллекта выдвинула несколько здравых и практичных идей, среди которых следует отметить методы представления знаний и архитектурные принципы интеллектуальных систем для принятия решений, в частности, экспертные системы и концепцию информационной доски [2]. В данной главе рассматривается проектирование интеллектуальной системы расшифровки криптограмм на основе метода информационной доски, имитирующего человеческий способ решения задачи. Как мы увидим, использование методов объектно-ориентированного проектирования позволяет достичь хороших результатов в этой области. ЮЛ Начало Рассмотрим одну из задач криптоанализа — процесс преобразования зашифрованного текста в открытый. В наиболее общем случае процесс дешифровки представляет собой неразрешимую задачу и не поддается даже самым мощным научным методам. К счастью, наша задача относительно проста, поскольку мы ограничимся простым шифром замены (substitution cipher). Требования криптоанализа Криптография изучает "методы передачи данных в виде, непонятном для посторонних" [3]. Используя криптографические алгоритмы, можно преобразовать сообщение (открытый текст) в криптограмму (зашифрованный текст) и наоборот. Шифр замены — один из наиболее известных криптографических алгоритмов, изобретенных еще в Древнем Риме. В этом шифре каждая буква открытого текста заменяется другой буквой. Например, можно заменить все буквы сообщения их преемниками: букву А — буквой В, букву В — буквой С, а букву Ζ — буквой А. Тогда открытый текст
454 Часть III. Приложения CLOS is an object-oriented programming language превращается в криптограмму DMPT jt bo pckfdu-psjfoufe qsphsbnnjoh mbohvbhf Чаще всего замена делается более сложным образом. Например, буква А заменяется буквой G, буква В — буквой J и т.д. Рассмотрим следующую криптограмму. PDG TBCER CQ TCK AL S NGELCH QZBBR SBAJG Подсказка: буква С в этой криптограмме соответствует букве О исходного текста. Предположение, что для шифрования текста используется только шифр замены, существенно упрощает задачу. Тем не менее в общем случае процесс дешифровки является не столь алгоритмически тривиальным. Для расшифровки часто используется метод проб и ошибок, когда криптоаналитики делают предположения о конкретной замене и рассматривают последствия. Например, можно начать расшифровку с изучения одно- и двухбуквенных слов в криптограмме и предположения, что они соответствуют наиболее употребительным словам английского языка (I, a, or, it, in, of, on). Подставляя эти предполагаемые буквы в другие слова, можно расшифровать весь текст. Например, если трехбуквенное слово начинается с буквы О, то это могут быть слова one, our или off. Для взлома шифра можно также использовать знание фонетики и грамматики. Например, две одинаковые соседние буквы вряд ли означают qq. Аналогично, можно предположить, что слово, заканчивающееся буквой д, на самом деле имеет суффикс ing. На еще более высоком уровне абстракции логично предположить, что словосочетание it is более вероятно, чем if is. Кроме того, можно предположить, что структура предложения, как правило, включает в себя существительное и глагол. Таким образом, если выяснится, что в предложении есть глагол, то следует начинать поиск прилагательных и существительных. Эти рассуждения приводят нас к следующим требованиям, предъявляемым к задаче: изобрести систему, которая по заданной криптограмме восстанавливает исходный открытый текст с помощью простого шифра замены. Определение границ задачи Для начала попробуем выполнить сценарий расшифровки простой криптограммы. Попробуйте решить следующую головоломку, а потом запишите последовательность ваших действий (только не подглядывайте!). Q AZWS DSSC KAS DXZNN DASNN Подсказка: буква W соответствует букве ν в открытом тексте. Перебор всех возможных вариантов совершенно лишен смысла. Предполагая, что открытый текст содержит 26 прописных английских букв, получим 26! (около
Глава 10. Искусственный интеллект: криптоанализ 455 4,03 χ 1026) возможных комбинаций. Следовательно, нужно попробовать не лобовое решение, а что-то другое. Например, можно использовать предположения о структуре предложений, слов и букв, а затем сделать естественный вывод. Если новой информации извлечь не удается, то следует выдвинуть другое вероятное предположение, ведущее к решению. Если же обнаружится, что предположение приводит к противоречию или заводит в тупик, необходимо вернуться назад и изменить прежние предположения. Рассмотрим пошаговое решение поставленной задачи. 1. Используя подсказку, просто заменим букву w буквой v. Q AZVS DSSC KAS DXZNN DASNN 2. Первое слово состоит из одной буквы, вероятно, А или I. Предположим, что это буква А: A AZVS DSEC KAS DXZNN DASNN 3. В третьем слове должны быть гласные звуки и вероятно, что это двойные буквы. Это вряд ли могут быть буквы UU, 11 или АА, так как буква А уже использована. Итак, попробуем вариант ЕЕ. A AZVE DEEC КАЕ DXZNN DAENN 4. Четвертое слово состоит из трех букв и оканчивается на букву Е, так как оно очень похоже на слово THE. A HZVE DEEC THE DXZNN DHENN 5. Во втором слове нужна гласная, но лишь буквы I, О, U (буквы А и Ε уже использованы). Осмысленное слово дает только вариант с буквой I. A HIVE DEEC THE DXINN DHENN 6. Существует лишь несколько слов с двойной буквой Е, состоящих из четырех букв (DEER, BEER, SEEN). Грамматика требует, чтобы третье слово было глаголом, поэтому остановимся на слове SEEN. A HIVE SEEN THE SXJNN SHENN 7. Полученное предложение не имеет смысла (улей (HIVE) не может видеть (SEEN)), значит, где-то сделана ошибка. Похоже, проблема заключается в выборе гласной буквы во втором слове, и необходимо изменить первое предположение. I HAVE SEEN THE SXANN SHENN 8. Рассмотрим последнее слово. Двойная буква в конце не может быть буквой S (мы уже использовали эту букву и, кроме того, полученное слово не имеет смысла), а вот сочетание LL дает осмысленное слово. I HAVE SEEN THE SXALL SHELL
456 Часть III. Приложения 9. Пятое слово — часть именной группы и поэтому, вероятно, является прилагательным. Анализируя шаблон STALL, находим слово SMALL. I HAVE SEEN THE SMALL SHELL Итак, решение найдено. Анализируя процесс решения, можно сделать три наблюдения. • Для решения задачи мы использовали разные источники знания: о грамматике, о составе слов, о чередовании согласных и гласных. • Сделанные предположения мы регистрировали в одном месте, потом мы применяли к ним имеющиеся у нас знания и анализировали последствия. • Мы рассуждали оппортунистически. Иногда рассуждения шли от общего к частному (словом из трех букв, оканчивающимся на букву Е, является, вероятно, слово THE), а иногда от частного к общему (шаблон ?ЕЕ? может соответствовать словам DEER, BEER, SEEN, но среди них глаголом является только слово SEEN). Анализируя ход проведенных рассуждений, можно выделить основные абстракции. Ими являются элементы анализа, позволяющие установить исходную архитектуру. В приведенном выше списке перечислены несколько источников знания, центральное место регистрации предположений и гипотез, а также компонент управления, позволяющий осуществлять оппортунистическое решение задачи. Описанный подход известен как метод информационной доски (blackboard model). Он впервые был предложен Ньюэллом (Newell) в 1962 году, а позднее был использован Редди (Reddy) и Ерманом (Erman) в проектах Hearsay и Hearsay II, посвященных проблемам распознавания речи [4]. Исследования подтвердили эффективность метода в данной предметной области, и вскоре он был успешно использован в других областях, включая интерпретацию сигналов, трехмерное моделирование молекулярных структур, распознавание образов и планирование [5]. Этот метод оказался весьма удобным для представления описательных знаний и эффективным с точки зрения памяти и времени по сравнению с другими подходами [6]. Информационная доска представляет собой архитектурный шаблон, который можно считать результатом анализа алгоритма решения, описанного выше. Архитектуру системы можно представить в виде системы классов и механизмов, описывающих способ взаимодействия между их экземплярами. Архитектура информационной доски Энглемор (Englemore) и Морган (Morgan) провели аналогию между моделью информационной доски группой людей, собирающей мозаику:
Глава 10. Искусственный интеллект: криптоанализ 457 Представим себе комнату с большой доской, рядом с которой собралась группа людей, держащих в руках кусочки мозаики. Сначала добровольцы прикрепляют на доске наиболее "вероятные" фрагменты изображения. Далее каждый участник группы изучает оставшиеся у него детали изображения и решает, есть ли такие, которые подходят к уже находящимся на доске. Участник, нашедший соответствие, подходит к доске и добавляет свою часть. После этого участники по очереди обновляют мозаику фрагмент за фрагментом. При этом не важно, сколько фрагментов находится на руках у участников. Все изображение будет полностью собрано в полной тишине, т.е. без общения между членами группы. Каждый участник действует самостоятельно, зная, в какой момент потребуется его помощь. Очередность подхода к доске заранее не устанавливается. Совместное поведение зависит только от изображения, собранного на доске. Анализ показывает, что этот процесс носит последовательный (к изображению добавляется один фрагмент за подход) и оппортунистский характер (фрагмент прикрепляется к доске, только если существует такая возможность). Такой подход сильно отличается от систематического перебора фрагментов для сборки изображения, начиная с левого верхнего [7]. Анализ рис. 10.1 показывает, что основу этой модели образуют три элемента: информационная доска, источники знаний и модель управления [8]. Обратите внимание на то, как следующее определение описывает основные абстракции, выделенные из предметной области. Как считает Нии (Nii), "информационная доска предназначена для хранения вычисляемых данных о решении задачи, используемых и порождаемых источниками знаний. Информационная доска состоит из объектов, принадлежащих пространству решений. Эти объекты иерархически распределяются по уровням анализа и вместе со своими атрибутами образуют словарь пространства решений" [9]. Как указывают Энглемор и Морган, "знания из предметной области, необходимые для решения задачи, хранятся в нескольких независимых источниках. Предназначение каждого источника знаний заключается в предоставлении информации, полезной для решения задачи. Текущая информация из каждого источника отражается на доске и обновляется в соответствии с содержанием специализированных знаний. Источники знаний могут принимать форму процедур, наборов правил или логических заключений" [10]. Источники знаний специализируются по предметным областям. В системах распознавания речи они могут включать в себя агентов, анализирующих фонемы, морфемы, слова и предложения. В системах распознавания образов источники знаний могут содержать сведения об элементарных структурах изображения, та-
458 Часть III. Приложения Источники знаний Информационная доска Рис. 10.1. Модель информационной доски ких как границы и области одинаковой плотности, а на более высоком уровне абстракции — объекты, характерные для конкретной сцены, например, дома, дороги, поля, автомобили и люди. Вообще говоря, источники знаний соответствуют иерархической структуре объектов, размещаемых на информационной доске. Более того, каждый источник использует в качестве входных данных объекты одного уровня иерархии, а в качестве выхода генерирует и/или изменяет объекты на другом уровне. Например, в системе распознавания речи источник знаний о словах может анализировать поток фонем (низкий уровень абстракции), чтобы обнаружить слово (более высокий уровень абстракции). И наоборот, источник знаний о предложениях может предположить, что во фразе должен существовать глагол (высокий уровень абстракции) и проверить это предположение, перебрав список возможных слов (более низкий уровень абстракции). Эти два подхода к поиску решения называются соответственно прямой и обратной последовательностью рассуждений. Прямая последовательность рассуждений (forward-chaining) позволяет перейти от частных утверждений к общим, а обратная последовательность (backward-chaining) начинается с некоторой гипотезы и позволяет проверить ее на основе известных утверждений. Вот почему управление информационной доской является оппортунистическим: в зависимости от обстоятельств, источники знаний могут активизировать либо прямые, либо обратные последовательности рассуждений. Источники знаний, как правило, состоят из двух компонентов: предусловий и действий. Предусловиями (preconditions) называется состояние информационной доски, представляющее интерес для конкретного источника знаний. Например, в распознавании образов предусловием может быть наличие прямой линии
Глава 10. Искусственный интеллект: криптоанализ 459 (возможно, означающей дорогу). Выполнение предусловий заставляет источник знаний переключить внимание на конкретный участок информационной доски и привести в действие соответствующие правила или процедурные знания. В этих условиях очередность не имеет значения: если источник знаний обнаруживает данные, полезные для решения задачи, он сообщает об этом управляющему модулю. Фигурально говоря, он как бы поднимает руку, показывая, что желает сделать что-то полезное. Затем управляющий модуль выбирает среди нескольких источников, поднявших руку, наиболее перспективный. Анализ источников знаний Вернемся к поставленной задаче и рассмотрим источники знаний, которые могут помочь при ее решении. Создавая крупные системы знаний, лучше всего сесть рядом с экспертом в предметной области и фиксировать те эвристики, которые он использует для решения задачи. Для решения нашей задачи следует попытаться расшифровать большое количество криптограмм и зарегистрировать особенности процесса рассуждений. Анализ выявил 13 источников знаний, относящихся к нашей задаче. В списке они приведены вместе с соответствующими знаниями. • Префиксы Суффиксы • Согласные • Непосредственно известные подстановки • Двойные буквы • Частота букв • Правильные строки • Сравнение с шаблоном • Структура предложений • Короткие слова • Решение • Гласные Наиболее часто встречающиеся начала слов (например, re, anti, un). Наиболее часто встречающиеся окончания слов (1у, ing, es, ed). Буквы, не являющиеся гласными. Подсказки, известные заранее. Наиболее часто встречающиеся двойные буквы (tt, 11, ss). Вероятность появления букв в тексте. Допустимые и недопустимые сочетания букв (например, qu и zg). Слова, соответствующие конкретному шаблону. Грамматика, в частности, знания об именных и глагольных группах. Возможные одно-, двух-, трех- и четырехбуквенные слова. Найдено ли решение или мы зашли в тупик. Буквы, не являющиеся согласными.
460 Часть III. Приложения • Структура слова Расположение гласных и типичная структура существительных, глаголов, прилагательных, наречий, предлогов, союзов и т.д. С объектно-ориентированной точки зрения каждый из этих источников знаний является потенциальным кандидатом на роль класса в архитектуре системы. Каждый объект имеет определенное состояние (знание), особое поведение (источник знаний о суффиксах может реагировать на слова с общим окончанием) и индивидуальностью (источник знаний о коротких словах не зависит от источника знаний о шаблонах). Перечисленные источники знаний могут образовать иерархию. В частности, одни источники знаний оперируют с предложениями, а другие — со словами, группами смежных букв и отдельными буквами. Такая иерархия соответствует объектам, которые могут возникать на информационной доске: предложениям, словам, частям слов и буквам. 10.2 Разработка Перейдем к решению задачи криптоанализа с использованием модели информационной доски. Эта модель представляет собой классический пример крупномасштабного повторного использования, в котором основой проекта является испытанный архитектурный шаблон. Архитектура информационной доски предполагает, что на верхнем уровне абстракции находятся информационная доска, несколько источников знаний и модуль управления. На следующем этапе необходимо определить классы и объекты предметной области, конкретизирующие эти основные абстракции. Объекты информационной доски Информационная доска представляет собой сложную структуру с несколькими уровнями абстракции. Абстракции реализуются в виде объектов, возникающих на доске в иерархическом порядке. Иерархическая структура объектов повторяет разные уровни абстракций, на которых расположены источники знаний. Источники знаний используют информационную доску как глобальный источник входных данных, частичных решений, альтернатив, окончательных решений и управляющей информации. Для того чтобы начать разработку иерархической структуры информационной доски, выделим следующие три класса. • Sentence Полная криптограмма • Word Отдельное слово в криптограмме
Глава 10. Искусственный интеллект: криптоанализ 461 • CipherLetter Отдельная буква в слове Источники знаний должны иметь доступ к общей информации о всех предположениях, поэтому необходимо включить в иерархию следующий класс. • Assumption Предположение, сделанное источником знаний. Наконец, следует знать предположения о буквах в открытом и зашифрованном тексте, которые делают источники знания. Для этого вводится следующий класс. • Alphabet Алфавит исходного текста, алфавит криптограммы и соответствие между ними. Есть ли между этими пятью классами что-либо общее? Разумеется есть: все эти классы соответствуют объектам информационной доски и этим значительно отличаются от других объектов, например, источников знаний и модуля управления. По этой причине в иерархию включается суперкласс для всех ранее перечисленных объектов. Предварительная структура абстракции Blackboard (Информационная доска) показана на рис. 10.2. Blackboard Blackboard Object + г*gist*О : void + rtsignQ: void CIpharLattar Alphabet Assumption Рис. 10.2. Диаграмма классов для абстракции Blackboard Для взаимодействия с внешним миром в классе BlackboardOb j ect (Объект информационной доски) определяются две операции. • register Добавить объект на информационную доску. • resign Удалить объект с информационной доски. Почему они определены как операции над объектами класса Blackboard- Object, а не над объектом класса Blackboard? Это напоминает ситуацию, когда объект сам себя рисует в окне. Безошибочным критерием при выборе места для размещения этих операций является ответ на вопрос: "Имеет ли сам объект достаточно знаний и полномочий, чтобы выполнять такие операции?". Ситуация с операциями register и resign представляет собой именно такой случай.
462 Часть III. Приложения Класс BlackboardObject — это лишь абстракция с подробной информацией о способах его прикрепления на информационной доске и удаления с нее (хотя для этого необходимо организовать взаимодействие с другими объектами класса BlackboardOb j ect). Каждый объект класса Blackboard должен действовать самостоятельно, поскольку он может активизироваться только в подходящей ситуации. Зависимости и утверждения Отдельные предложения, слова и буквы шифра также связаны между собой: у них есть соответствующие источники знаний. Конкретный источник знаний может проявлять интерес к одному или нескольким таким объектам, и поэтому предложение, слово и буквы шифра должны поддерживать связь со своим источником знаний, чтобы при появлении предположения об изменении объекта эти источники знаний получали извещения. Для реализации этого механизма вводится простой абстрактный класс: Dependent (Зависимый). Для того чтобы разработать класс Dependent, включим в него объект, представляющий собой набор источников знаний. • references Набор источников знаний. Кроме того, определим в этом классе следующие операции. • add Добавить ссылку на источник знаний. • remove Удалить ссылку на источник знаний. • numberOf Dependents Возвратить число зависящих объектов. • notify Известить каждый зависящий объект. Операция notify имеет семантику пассивного итератора, т.е. при ее вызове указывается действие, которое необходимо выполнить над всеми зависящими объектами в коллекции. Зависимость может быть внешним свойством и примешиваться к другим классам. Например, объект класса CipherLetter относится как к классу BlackboardObject, так и к классу Dependent, поэтому мы можем скомбинировать две этих абстракции для получения желательного поведения. Такое использование примесей способствует повторному использованию и разделению понятий в нашей архитектуре. Классы CipherLetter (Бука шифра) и Alphabet (Алфавит) имеют еще одно общее свойство: объекты этих классов допускают предположения о своем поведении (напомним, что объект класса Assumption (Предположение) является одним из объектов класса BlackboardOb j ect). Например, некоторый источник знаний может предположить, что буква К в шифре соответствует букве Ρ исходного текста. По мере решения задачи может абсолютно точно выясниться, что
Глава 10. Искусственный интеллект: криптоанализ 463 буква G соответствует букве J. Итак, нам нужен один класс, поддерживающий предположения и утверждения относительно связанных с ним объектов. Этот класс называется Af f 1гта1:10п(Утверждение). В нашей архитектуре допускаются высказывания только об отдельных буквах — объектах классов CipherLetter и Alphabet. В ранее рассмотренном сценарии буквы шифра соответствовали отдельным буквам открытого текста, допускающих высказывания, а алфавит состоял из многих букв, каждая из которых может допускать свои собственные высказывания. Определение независимого класса Affirmation позволяет разделить это свойство между этими двумя классами. Определим следующие операции для экземпляров класса Affirmation. • make Сделать высказывание. • retract Отменить высказывание. • chiphertext Вернуть шифрованный эквивалент для заданной буквы открытого текста. • plaintext Вернуть исходный текстовый эквивалент для заданной буквы зашифрованного текста. Анализ показывает, что следует ясно различать две роли высказываний: временные предположения о соответствиях между буквами зашифрованного и открытого текста и доказанные утверждения, остающиеся постоянными. По мере расшифровки криптограммы источники знаний могут делать разные предположения, но по мере приближения к концу эти предположения становятся утверждениями. Для того чтобы смоделировать эти роли, уточним класс Assumption (Предположение) в подклассе Assertion (Утверждение). Экземпляры обоих классов управляются объектами класса Affirmation и могут помещаться на информационную доску. Сначала мы определим сигнатуры операций make и retract в классе Assumption или Assertion, а затем определим следующие селекторы. • isPlainLetterAsserted Селектор: определена ли эта буква текста достоверно? • isCipherLetterAsserted Селектор: определена ли эта буква шифра достоверно? • plainLetterHasAssumptlon Селектор: есть ли предположение об этой букве текста? • cipherLetterHasAssumption Есть ли предположение об этой букве шифра?
464 Часть III. Приложения Объекты класса Assumption относятся к классу BlackboardObject, поскольку информация о сделанных предположениях используется всеми источниками знаний. Члены этого класса должны выражать следующие свойства. • target Объект доски, насчет которого делается предположение. • creator Источник знаний, который сделал предположение. • reason Основание для сделанного предположения. • cipherLetter Предполагаемое значение буквы исходного текста. Необходимость каждого из этих свойств в основном объясняется самой природой предположения: источник знания формирует предполагаемое соответствие о буквах открытого и зашифрованного текста, исходя из каких-то причин (например, некоторого правила). Тем не менее, предназначение первого свойства target менее очевидно. Оно необходимо для отката. Если предположение не подтверждается, то об этом следует сообщить всем объектам класса BlackboardObject, сделавших это предположение, а они, в свою очередь, должны известить об этом зависимые источники знаний, используя механизм зависимости. Далее определим подкласс Assertion класса Assumption. Оба эти класса содержат одну и ту же операцию. • isRetractable Селектор: является ли соответствие временным? Для всех объектов класса Assumption предикат isRetractable является истинным, а для всех объектов класса Assertion — ложным. Кроме того, сделанное утверждение нельзя ни изменить, ни отвергнуть. Диаграмма классов, представленная на рис. 10.3, иллюстрирует взаимодействие между классами Dependent и Affirmation. Следует обратить особое внимание на роли, которые играют перечисленные абстракции в различных сочетаниях. Например, объект класса KnowledgeSource (Источник знаний) в одном аспекте может генерировать предположения (creator), а в другом — ссылаться на букву шифра (ref erencer). Поскольку роли изменяют внешний вид абстракций, следует ожидать, что протокол взаимодействия источников знаний и предположений будет отличаться от протокола взаимодействия между источниками знаний и буквами. 103 Конструирование Продолжим проектирование, добавив к классу Alphabet (Алфавит) классы Sentence (Предложение), Word (Слово) и CipherLetter (Буква шифра).
Глава 10. Искусственный интеллект: криптоанализ 465 BtackboardObJect ♦ regfsterQ: void ♦ resignQ: void ♦ addO: void — # references: UnboundedColfectlon addO;void removeO: void numberOfPependenteQ: int notltyo ^ void ODhttUtttr valueO: Strtno, IsSolvedQ: boolean ♦target 0..* AfflnnaHon • assumptlonStatement: Assumption • aesertlonStatement: Assertion make(A«sumptton): void makeCftssertton): void retractG: Assumption retractO: Affirmation clphertextO: char plaintext©: char IsPlalnLetterAssertedO: boolean isCtpheitetterAseertedQ; boolean plainLetterHasAssumptlonO: boolean cIpheitetterHasAssumptlonQ: boolean mostRecentO: As'sumptlon statementAtO; statements # letter: char # affirmations: Affirmation ♦retractableStatement • plalnLetter: char - reason: String • clphedatter char IsRetractableO: boolean retractO: void AssumptlonO; void +nonretractabla8tatemeht ♦referencer Assertion interenceEngfne KnowtodfleSource ♦creator ♦creator Рис. 10.3. Классы зависимостей и подтверждений Проектирование объектов класса Blackboard Предложение описывается довольно просто — это объект классов Black- boardObject и Dependent, представляющий собой список слов. Суперкласс Dependent сделаем абстрактным1 (рис. 10.4), поскольку могут существовать подклассы класса Sentence, одновременно являющиеся производными от класса Dependent. Оставив это отношение наследования абстрактным, 1В языке UML 2.0 имя абстрактного класса выделяется курсивом. Кроме того, в список свойств можно добавить ключевое слово {abstract}.
466 Часть III. Приложения iC ref«reno«s: UnboundedCollection I + addQ ' void | + «moveO: void В + numberOfDependentO: int В + notifjO " void Ε Рис. 10.4. Схема класса Sentence с абстрактным классом Dependent мы позволяем таким подклассам разделять общие свойства с суперклассом Dependent. К операциям register и resign, определенным в суперклассе Black- boardObject, и четырем операциям, определенным в классе Dependent, добавим еще две операции для обработки предложений. value Текущее содержание предложения. is Solved Истинно, если обо всех словах в предложении высказаны некие утверждения. Вначале операция value возвращает исходную криптограмму. Как только селектор isSolved примет значение true, операция value вернет исходный открытый текст. Оценка результатов операции value, пока селектор isSolved не принял значение true, позволяет найти частичное решение задачи. Как и класс Sentence, класс Word является разновидностью классов Black- boardObject и Dependent. Более того, класс Word обозначает список букв. Для того чтобы источникам знаний было удобно манипулировать словами, в класс Word включена ссылка на все предложение, а также на предыдущее и следующее слова в предложении. Как и в классе Sentence, в классе Word определим две дополнительные операции. • value Текущее значение слова. • isSolved Истинно, если обо всех буквах слова сделаны утверждения. Определим теперь класс CipherLetter. Экземпляры этого класса относятся к классам BlackboardObject и Dependent. Кроме их унаследованных свойств, каждый объект класса CipherLetter имеет значение, представляющее собой букву в зашифрованном тексте, например, н, а также набор предположений и утверждений о соответствующих буквах исходного текста. Для организации этого набора можно использовать класс Affirmation. Схема класса Cipher- Letter представлена на рис. 10.5. Подчеркнем, что в этот класс включены селекторы value и isSolved, аналогичные селекторам, содержащимся в классах Sentence и Word. Для клиентов BiackboMrctOQeot S«nt*no· # words: Ust<Word*> + vilu«0 · String + IsSolvedQ: boolean r L
Глава 10. Искусственный интеллект: криптоанализ 467 BtackboardObject Sentence # words: List<Word*> + valusf): String + isSolvedO: boolean Dependent # references: UnboundedCollection + addQ : void + removeQ: void + numberQfDependentsQ: int + notifyQ: void BtackboardObject Word # letters: List<CipherLetter*> + valueQ: String + isSolvedQ: boolean + sentenceQ: Sentence + previousO: Word + nextQ: Word BtackboardObject CipherLetter # letter: char # affirmations: Affirmation + valueQ : String Affirmation assumptionStatement: Assumption assertionStatement: Assertion + make(A8Sumption): void + make(Assertion): void + retractQ: Assumption + retractQ: Affirmation + ciphertextO: char + plaintextQ : char + isPlainLetterAssertedO; boolean + isCipherLetterAssertedQ ; boolean + ptainLetterHasAssumptionO : boolean + cipheitetterHasAseumptionQ: boolean + moetRecentQ : Assumption + statementAtQ : statements Рис. 10.5. Схема классов CipherLetter и Word класса CipherLetter предусмотрены операции, обеспечивающие им доступ к предположениям и утверждениям. Объекты класса Affirmation представляют собой коллекцию предположений и утверждений, упорядоченных по времени их выдвижения, причем последний элемент этой коллекции содержит текущее предположение или утверждение. Хранение всех промежуточных результатов решения задачи позволяет источни-
468 Часть III. Приложения кам знаний просматривать отвергнутые предположения и учиться на ошибках. По этой причине в класс Affirmation включены две дополнительные операции. • mostRecent Селектор: возвращает последнее предположение или утверждение. • statementAt Селектор: возвращает η-oe высказывание. Итак, мы уточнили поведение класса Affirmation и теперь можем принять обоснованные решения, касающиеся его реализации. В частности, в него можно включить защищенный член statements, представляющий собой список предположений. Рассмотрим класс Alphabet. Он содержит буквы, из которых состоят открытый и зашифрованный тексты, а также правила определения соответствий между ними. Эта информация имеет большое значение, поскольку каждый источник знаний может использовать этот класс, чтобы узнать, какие соответствия уже выявлены, а какие — еще нет. Например, если уже доказано, что букве С в шифрограмме соответствует буква Μ открытого текста, то это соответствие регистрируется в алфавите, чтобы источники знаний не выдвигали новых предположений о букве Μ в открытом тексте. Для повышения эффективности запрос о соответствии букв шифра и текста следует подавать двумя способами: по букве шифрограммы и по букве открытого текста. Схема класса Alphabet показана на рис. 10.6. Аналогично классу CipherLetter, в класс Alphabet необходимо включить защищенный член affirmations и описать операции доступа к его состоянию. Теперь можно определить класс Blackboard, хранящий коллекцию экземпляров класса BlackboardObject и его подклассов. Таким образом, класс BlackboardObject является разновидностью класса DynamicCollection (Динамическая коллекция). Мы решили использовать наследование, а не включение экземпляра класса DynamicCollection, поскольку класс Blackboard удовлетворяет условиям использования наследования. По существу, класс Blackboard представляет собой разновидность коллекции. Класс Blackboard содержит операции add и remove, унаследованные от класса Collection (Коллекция), а также следующие пять операций, характерных для информационной доски. • reset Очищает доску. • assertProblem Помещает на доске начальные условия задачи. • connect Подключает к доске источник знаний. • is solved Возвращает истину, если предложение расшифровано. • retriaveSolution Возвращает расшифрованный открытый текст. Вторая операция необходима для создания зависимости между информационной доской и источниками знаний.
Глава 10. Искусственный интеллект: криптоанализ 469 Dependent # references: UnboundedColiectionI addQ: void removeO "■ void numberOfDependentsO: int notityQ - void г BlackboardObject] Sentence # words: Ust«Word*> valueO: String isSolvedQ; boolean BtackboardObject\ Word # letters: List«CipherLetter*> valueO: String isSolvedQ: boolean sentence^: Sentence previousQ: Word nextp: Word BiackboardObject] CiphefLetter # letter: char # affirmations: Affirmation valueO: Strjng IsSolvedQ: boolean BSackboardObjecq Alphabet # affirmations: Affirmation plalntext(char): char clphertext(char); char IsBound(char): Int makeO: void _ • assumptlonStatemerrt: Assumption ~ assertionStatement: Assertion # statements: UnboundedColiection (Assumption) {ordered} make(Assumptlon); void make(Assertion): void retracto: Assumption retractQ: Affirmation clphertextO: char plaintext: char IsPlainLetterAssertedO: boolean IsOlpherLetterAssertedOί boolean ptalnLeiterHasAssumptionO: boolean cjpherLetterHasAssumptionO; boolean mustRecentO: Assumption statement; statements Рис. 10.6. Схема класса Alphabet Итоговая схема классов, взаимодействующих с классом Blackboard, приведена на рис. 10.7. Обратите внимание на то, что класс Blackboard одновременно конкретизирует шаблонный класс DynamicCollection (Динамическая коллекция) и наследует его свойства. Кроме того, диаграмма ясно иллюстрирует удачное использование абстрактного класса Dependent. В частности, класс Dependent обладает лишь частью функциональных свойств подклассов класса BiackboardObject. Поскольку класс Dependent является абстрактным, шансы его повторного использования повышаются.
470 Часть III. Приложения Blackboard KnowledgeSource Word Sentence Dependent i Class:BlackboardObjectj DynamicCollection resetQ ' void assertProblemQ . void connectO : void isSolvedQ : boolean retrieveSolutionQ Sentence «instantiate» Jiu J Item DynamicCollection BlackboardObject + registerQ: void + resignfl: void CIpherLetter Alphabet Assumption Affirmation Рис. 10.7. Уточненная диаграмма класса Blackboard Проектирование источников знаний В предыдущем разделе мы идентифицировали 13 источников знаний, относящихся к поставленной задаче. Точно так же, как это было сделано для объектов класса Blackboard, можно разработать структуру абстрактного класса, описывающую эти источники знаний и обладающую всеми их общими свойствами. Проектирование специализированных источников знаний Предположим, что существует абстрактный класс KnowledgeSource (Источник знаний), аналогичный классу BlackboardObject. Вместо определения всех 13 источников в качестве непосредственных подклассов одного более общего
Глава 10. Искусственный интеллект: криптоанализ 471 класса, полезно сначала провести предметный анализ и определить, не группируются ли источники знаний каким-нибудь образом. Действительно, такие группы есть: некоторые источники знаний оперируют целыми предложениями, а другие — целыми словами, непрерывными цепочками букв или отдельными буквами. Эту схему можно выразить с помощью следующих подклассов. • SentenceKnowledgeSource Правила, связанные с предложениями • WordKnowledgeSource Правила, связанные со словами • LetterKnowledgeSource Правила, связанные с буквами • StringKnowledgeSource Правила, связанные со строками Для каждого из этих классов можно определить специализированные подклассы. В частности, подклассы класса SentenceKnowledgeSource выглядят так. • SentenceStructureKnowledgeSource Правила, связанные со структурой предложений • SolvedKnowledgeSource Найденное предложение криптограммы Аналогично, подклассы промежуточного класса WordKnowledgeSource определяются так. • WordStructureKnowledgeSource Правила, связанные со структурой слов • Smal 1 WordKnowledgeSource Правила, связанные с короткими словами • PatternmatchKnowledgeSource Правила сопоставления шаблонов Последний класс требует пояснений. В списке 13 источников знаний указано, что цель этого класса — подбирать слова, соответствующие определенному шаблону. В частности, для этого можно использовать систему записи регулярных выражений. • Любой элемент ? • Не элемент - • Символ замыкания * • Начало группы { • Конец группы } Используя эти символы, можно передать объекту этого класса шаблон ?Е~ {А Ε Ι О U}, укажите ему найти в своем словаре слово из трех букв, начинающееся с любой буквы, после которой идет буква Е, а затем — любая буква, за исключением гласной. Все экземпляры этого класса имеют доступ к общему словарю, причем каждый объект имеет собственного агента для сопоставления слов
472 Часть III. Приложения и шаблонов. Подробное описание функционирования этого класса в данный момент не представляет интереса, поэтому мы отложим изучение его интерфейса и реализации на будущее. Продолжая проектирование, объявим следующие подклассы класса String- Knowledge. • CommonPref ixKnowledgeSource Правила, связанные с префиксами • CommonSuff ixKnowledgeSource Правила, связанные с суффиксами • DoubleLetterKnowledgeSource Правила, связанные с двойными буквами, например, оо, 11 и т.п. • LegalStringKnowledgeSourсе Правила, связанные со структурой слов В заключение, определим следующие подклассы класса LetterKnowledge- Source. • DirectSubstitutionKnowledgeSource Правила, связанные с постановками букв • VowelKnowledgeSource Правила, связанные с гласными • ConsonantKnowledgeSource Правила, связанные с согласными • LetterFrequencyKnowledgeSource Правила, связанные с частотой букв Обобщение источников знаний Анализ показывает, что только две операции относятся ко всем перечисленным специализированным классам. • reset Перезапуск источника знаний. • evaluate Оценка состояния информационной доски. Простота этого интерфейса объясняется тем, что источники знаний являются относительно автономными: мы указываем на интересующий нас объект класса Blackboard и просим источник знаний применить его к текущему состоянию информационной доски. Выполняя полученное задание, источник знаний может осуществить следующие действия. • Высказать предположение о подстановке. • Найти противоречие среди предыдущих предположений и отменить неправильные. • Высказать утверждение о подстановке. • Сообщить модулю управления о новом предложении.
Глава 10. Искусственный интеллект: криптоанализ 473 InferenceEngine KnowledgeSource Sentence Knowledge Source Letter Knowledge Source Sentence Structure Knowledge Source Pattern Matching Knowledge Source Direct Substitution Knowledge Source Vowel Knowledge Source Consonant Knowledge Source Common Prefix Knowledge Source Letter Frequency Knowledge Source Рис. 10.8. Иерархия обобщений класса KnowledgeSource Все эти действия не зависят от вида источника знаний. Продолжая обобщение, можно сказать, что все они характерны для определенного механизма логического вывода. Следовательно, необходимо определить класс InferenceEngine (Генератор логического вывода), который, имея определенный набор правил, либо выполняет их, либо генерирует новые правила (прямая последовательность рассуждений), либо доказывает некоторую гипотезу (обратная последовательность рассуждений). Разрабатывая конструктор класса InferenceEngine, основное внимание следует уделить созданию экземпляра этого класса и ознакомлению его с набором правил, применяемых для оценки предположений. Фактически, этот класс предусматривает только одну операцию, доступную для источников знаний.
474 Часть III. Приложения • evaluate Выполнить правило механизма вывода Опишем взаимодействие источников знаний. Каждый специализированный источник знаний определяет свои собственные правила и делегирует ответственность за их выполнение на класс Inf erenceEngine. Точнее говоря, операция KnowledgeSource: : evaluate вызывает операцию Inf erenceEngine : : evaluate, что приводит к выполнению одной из четырех упомянутых выше операций. На рис. 10.9 представлен сценарий такого взаимодействия. : Control ler : Кпоу/1 edge Source ; Inference Enfling :Assu motion evaluateQ addHinlQ evaluateQ ■*ύ retractp notifyp Рис. 10.9. Сценарий выполнения правил источниками знаний Эта диаграмма последовательностей иллюстрирует следующие этапы сценария. 1. Выбрать объект класса KnowledgeSource. 2. Попросить его оценить состояние объекта класса Blackboard. 3. Выполнить определенную операцию, например, удалить объект класса Assumption (отменить предположение). 4. Сообщить всем объектам класса KnowledgeSource об удалении объекта класса Assumption (отмене предположения). 5. Сообщить объекту класса Controller о том, что объект класса KnowledgeSource имеет новую подсказку, помогающую решить задачу. Что означает это правило? Источник знаний о суффиксах может выполнить это правило с помощью алгоритма сопоставления с шаблоном и распознать, например, шаблон *1??. Этому шаблону могут соответствовать суффиксы ING, IES и IED. С точки зрения структуры класса можно сказать, что источники знаний являются разновидностью механизма логического вывода. Кроме того, они связаны
Глава 10. Искусственный интеллект: криптоанализ 475 с объектами доски, поскольку действуют на объекты, расположенные на ней. Наконец, каждый источник знаний должен быть связан с модулем управления, которому он посылает свои подсказки, а тот, в свою очередь, может время от времени активизировать источники знаний. Эти проектные решения продемонстрированы на рис. 10.10. InferenceEngine + evaluateQ : void DynamicColtecthn Blackboard + makeQ ■ void I \ I KnowledgeSource # pastAssumptions: UnboundedOrderedCollection + resetQ . void + evaluateQ : void 1 + notifyQ ■ void ♦creator 0..* BlackboardObject Assumption - plainLetter: char - reason; String - cipherLetter char + isRetractableQ · boolean + retractO : void + AssumptionQ · void 1 v? Г4" 1 I Controller + addHint(KnowledgeSource): void + resetQ , void I + connect(KnowledgeSource); void I + removeHint(KnowledgeSource). void! + processNextHintQ . void I + isSolvedQ : int I + unableToProceedQ ; int 1 Рис. 10.10. Предварительная схема класса KnowledgeSource В схему введена коллекция pastAssumptions (Прошлые предположения), чтобы источник знаний могут отслеживать все предположения и учиться на ошибках. Экземпляры класса Blackboard служат хранилищем объектов класса BlackboardOb j ect. По аналогичным причинам необходим также класс Know- ledgeSources, хранящий все источники знаний, относящиеся к решаемой задаче.
476 Часть III. Приложения Одной из обязанностей этого класса является создание 13 индивидуальных объектов класса KnowledgeSource при создании экземпляра Knowledge- Sources. Экземпляры этого класса выполняют три операции. • restart Перезапустить источник знаний. • StartKnowledgeSource Задать начальные условия для источника знаний. • connect Связать источник знаний с информационной доской или модулем управления. Уточненная структура класса KnowledgeSource показана на рис. 10.11. _] Class:KnowledgeSourcei DynamlcCollection + restartQ: void + startKnowledgeSourceQ \ void + connectO! void InferenceEngine + evaluateQ: void KnowledgeSources KrtowledgeSourcB # pastAssumptions; UnboqndedOrderedGolfafctfon + resetQ: void + evaluateQ: void + notifyO: void +creator \DynamicCo!lectiorf Blackboard + makeQ: void Controller addHint(KnowledgeSource) ■ void resetQ: void connect(KnowledgeSource): void removeHint(KnowledgeSource): void proeessNextHintO: void isSolvedQ: fnt unableToProcaedQ: int BlackboantObject Assumption plainLetter: char reason: String cipherLetter: char + «RetractabteQ: boolean + retractO: void + AssumptionQ: void Рис. 10.11. Уточненная схема класса KnowledgeSource
Глава 10. Искусственный интеллект: криптоанализ 477 Проектирование модуля управления Рассмотрим взаимодействие модуля управления с отдельными источниками знаний. На каждом этапе расшифровки криптограммы отдельные источники знаний могут выяснить полезную информацию и сообщить подсказку контроллеру. И наоборот, источник знаний может прийти к выводу, что предыдущая подсказка была неверной и ее надо отменить. Поскольку все источники знаний имеют равные права, модуль управления должен выбрать наиболее перспективную подсказку и вызвать операцию evaluate. Как модуль управления определяет, какой из источников знаний следует активизировать? Для этого можно предложить несколько подходящих правил. • Объект класса Assertion имеет более высокий приоритет, чем объект класса Assumption. • Объект класса SolvedKnowledgeSource дает наиболее ценные подсказки. • Подсказки объектов класса PatternMatchingKnowledgeSource имеют более высокий приоритет, чем подсказки объектов класса Sentence- StructureKnowledgeSource. Модуль управления действует как агент, ответственный за взаимодействие между разными источниками знаний, связанными с информационной доской. Модуль управления должен иметь связь с источниками знаний, обеспечиваемую классом KnowledgeSources. Кроме того, в качестве одного из своих свойств он должен иметь коллекцию подсказок, упорядоченных по приоритету. Тем самым модуль управления может легко выбрать для активизации источник знаний с наиболее интересной подсказкой. Проанализировав проект класса, мы предлагаем включить в класс Controller следующие операции. • reset Перезапуск модуля управления. • addHint Добавить подсказку от источника знаний. • removeHint Удалить подсказку от источника знаний. • processNextHint Оценить следующую подсказку. • is Solved Селектор: возвращает истинное значение, если задача решена. • UnableToProceed Селектор: возвращает истинное значение, если источники знаний зашли в тупик. • connect Устанавливает связь с источником знаний. Модуль управления в некотором смысле управляется подсказками, поступающими от источников знаний, поэтому для описания его динамического поведения хорошо подходят конечные автоматы.
478 Часть III. Приложения Рассмотрим, например, диаграмму переходов, изображенную на рис. 10.12. Из нее видно, что контроллер может находиться в одном из пяти основных состояний: Initializing (Инициализация), Selecting (Выбор), Evaluating (Вычисление), Stuck (Тупик) и Solved (Решение найдено). Наибольший интерес представляет поведение модуля управления при переходе из состояния Selecting в состояние Evaluating. В состоянии выбора модуль управления переходит из состояния CreatingStrategy (Создание стратегии) в состояние ProcessingHint (Генерация подсказки) и, в конце концов, — в состояние Se- lectingKS (Выбор источника знаний). Если источник знаний выбран, то модуль управления переходит в состояние Evaluating, а затем — Updating Blackboard. Если на доску добавляются объекты, то модуль управления переходит в состояние Connecting и в состояние Backtracking, если предположение отменено, уведомляя об этом все зависимые источники знаний. Если модуль управления не может выдвинуть ни одной подсказки, то он переходит в состояние Stuck. Если же решение найдено, то модуль управления переходит в состояние Solved. Интеграция модели Определив основные абстракции предметной области, мы можем приступить к их соединению в действующее приложение. Для этого следует реализовать и проверить вертикальный срез архитектуры, а затем поочередно завершить разработку механизмов. Интеграция объектов верхнего уровня На рис. 10.13 показана диаграмма композитной структуры, иллюстрирующая объекты системы, находящиеся на самом верхнем уровне. Она соответствует структуре обобщенной информационной доски, показанной на рис. 10.1. Физическое содержание объектов доски в коллекции theBlackboard и источников знаний в коллекции theKnowledgeSources показано схематически, аналогично тому, как это было сделано при описании вложенности классов. На диаграмме показан экземпляр нового класса Cryptographer. Этот класс агрегирует доску, источники знаний и модуль управления. Приложение может создавать несколько экземпляров этого класса и работать с несколькими информационными досками одновременно. В классе Criptography определены две основные операции: • reset Перезапустить информационную доску. , · decipher Расшифровать заданную криптограмму. Конструктор этого класса должен создать зависимости между информационной доской и источниками знаний, а также между источниками знаний и модулем
Глава 10. Искусственный интеллект: криптоанализ 479 Initializing + On Entry / connect I геас|У>| + On Event / restart n_u2iJ Stuck > Selecting F^ (Creating Л Strategy I ready /^Processing Hlnt\ v ZZ / [unableToProceed] selected /evaluateQ found hint Selecting KS ) [isSolved] Solved KSCompteted Evaluating Updating Blackboard (Connecting "\ added _^J ^nn^^n9 retracted /notifyQ /^Backtracking^ j Рис. 10.12. Конечный автомат Controller управления. Метод reset аналогичен: он восстанавливает связи и возвращает информационную доску, источники знаний и модуль управления в начальное состояние. Операция decipher содержит строку, представляющую собой криптограмму, подлежащую расшифровке. Теперь структура приложения становится предельно простой, что характерно для объектно-ориентированных систем. Операция decipher немного сложнее, что не удивительно. Сначала необходимо вызвать операцию assertProblem (Поставить задачу) и поместить задание на информационную доску. Затем следует активизировать источники знаний, привлекая их к решению задачи. В заключение выполняется циклический процесс обращения к модулю управления за дальнейшими подсказками, пока задача
480 Часть III. Приложения Cryptographer :BlackboardOblect Ε I theKnowtedgeSourcet | 1 0-Ί iKnowledqeSource Ε theController Рис. 10.13. Диаграмма композитной структуры не будет решена окончательно или источники знаний не зайдут в тупик. Соответствующий поток управления показан на рис. 10.14. Завершим описание системы архитектурными интерфейсами, необходимыми для выполнения алгоритма расшифровки криптограммы. Хотя в данный момент он обладает минимальной функциональностью, его реализация в виде вертикального среза системной архитектуры позволяет обосновать ключевые системные решения. Рассмотрим две основные операции, определенные в классе decipher, а именно: assertProblem и retrieveSolution (Найти решение). Операция assertProblem особенно интересна тем, что создает всю совокупность объектов класса Blackboard. Опишем наш алгоритм в виде псевдокода. удалить из строки все начальные и концевые пробелы если получилась пустая строка вернуть управление создать объект-предложение занести предложение на доску
Глава 10. Искусственный интеллект: криптоанализ 481 :theCryptographer ith»BtockNard р. decipherQ assertProblemO rthtKnttwIgdflgSfttirctt resetQ TJ rthgCgntrrttor (IthejCJontroller, isSolvedO II theCpntroller.unableTo ProceedO):] : processNextHintQ "*u ait у [true] isSolvedQ no retrieveSolutionQ 3L Рис. 10.14. Диаграмма последовательностей desipher создать объект-слово (крайнее слева) занести слово на доску добавить слово к предложению для каждого символа строки слева направо если символ является пробелом сделать текущее слово предыдущим создать объект-слово занести слово на доску добавить слово к предложению иначе создать объект "буква шифра" занести букву на доску добавить букву к слову Цель проектирования — создание эскиза для реализации. Данный псевдокод представляет достаточно подробный алгоритм, так что показывать его полную реализацию нет необходимости. Операция retrieveSolution намного проще: она лишь возвращает предложение, записанное в данный момент на доске. Вызывая эту операцию до того,
482 Часть III. Приложения как функция isSolved вернет истинное значение, можно получать частичные решения. Реализация механизма оценки предположений Итак, мы реализовали механизм, позволяющий устанавливать и извлекать значения для объектов класса Blackboard. На следующем этапе необходим механизм выдвижения предположений об объектах класса Blackboard. Он особенно интересен тем, что предположения носят динамический характер (т.е. постоянно создаются и уничтожаются в ходе решения задачи, порождая события, связанные с модулем управления). На рис. 10.15 показан основной сценарий выдвижения предположений. Эта диаграмма коммуникаций демонстрирует, что как только объект класса Know- ledgeSource создает объект класса Assumption, он сообщает об этом объекту класса Blackboard, который, в свою очередь, создает объект класса Assumption для объекта класса Alphabet, а затем — для каждого объекта класса BlackboardObject, к которым относится объект класса Assumption. 1: Assu :Knowledqe$o»rce mptionO τ : Assumption 2: makeQ —► 3: ma blackboard <e0 Τ Alphabet I 4: addO -*■ 5 :BlacJkboar_clObiect 1 1 notifyO τ iKitowledcieSource Все зависимости регистрируются Рис. 10.15. Механизм предположений з В простейшем случае, чтобы отменить предположение, достаточно выполнить откат. Например, чтобы отменить предположение о букве шифра, следует продвинуть вверх стек предположений, пока отменяемое предположение не окажется на вершине. Возможен более тонкий механизм. Например, предположим, что однобуквен- ное слово является буквой I (допустим, нужна гласная буква). Затем мы можем сделать предположение, что некоторое двухбуквенное сочетание — это буквы NN (допустим, нужны согласные). Если первое предположение окажется ошибочным, то второе вполне может быть истинным. Таким образом, класс Assumption необходимо дополнить еще одним методом, позволяющим отслеживать взаимоза-
Глава 10. Искусственный интеллект: криптоанализ 483 висимость предположений. Реализацию этого поведения целесообразно отложить на более поздний срок, поскольку оно мало влияет на архитектуру. Добавление новых источников знаний Теперь, когда определены основные абстракции информационной доски и механизмы выдвижения и проверки предположений, необходимо реализовать класс Inf erenceEngine (Логический вывод), от которого зависят все источники знаний. Как уже отмечалось, этот класс содержит только одну интересную операцию — evaluateRules (Применить правило). Мы не будем углубляться в излишние подробности, поскольку этот метод не влияет на проектные решения. Убедившись в правильной работе механизма логического вывода, можно последовательно вводить в систему новые источники знаний. Использование этого процесса объясняется двумя причинами: • Трудно заранее выяснить, какие правила действительно важны для каждого из источников знаний, не испытав систему на конкретной задаче. • Отладка базы знаний существенно упрощается при тестировании небольших наборов правил, а не всех целиком. В принципе, реализация источников знаний является предметом инженерии знаний. Для создания конкретного источника знаний требуется консультация с экспертами (например, криптографами), чтобы выбрать осмысленные правила. При тестировании источников знаний может оказаться, что одни правила бесполезны, другие слишком специфичны или носят слишком общий характер, а некоторых недостает. После тестирования мы можем изменить правило или даже добавить новое. При создании источников знаний могут обнаружиться общие для нескольких источников правила и/или функции. Например, классы WordStructureKnow- ledgeSource (Источник знаний о структуре слов) и SentenceStructure- KnowledgeSource (Источник знаний о структуре предложения) могут иметь общие функции, поскольку они оба должны знать, как применять правила следования определенных языковых конструкций. В первом случае источник знаний должен знать правила упорядочения букв, а во втором — слов. В обоих случаях процессы одинаковы. Таким образом, целесообразно ввести новый абстрактный класс StructureKnowledgeSource (Источник знаний о структуре), реализующий общее поведение. Новая иерархия источников знаний подчеркивает тот факт, что процесс применения правил зависит не только от источников знаний, но и от разновидности объектов информационной доски. Например, источник знаний может реализо- вывать прямую последовательность рассуждений в отношении одних объектов
484 Часть III. Приложения и обратную последовательность — в отношении других. Кроме того, операции над объектом зависят от применяемого источника знаний. 10.4 Сопровождение В данном разделе рассматриваются усовершенствования функциональных свойств системы криптоанализа и соответствующие изменения проекта. Расширение функциональных возможностей В любой интеллектуальной системе важно не только найти решение, но и понять, как оно было получено. Для этого система должна обладать способностью самоанализа: отслеживать, какие источники знаний активизируются и когда, какие предположения были выдвинуты и почему и т.д. Это необходимо, чтобы иметь возможность запросить у системы, почему было сделано то или иное конкретное предположение, к каким результатам оно привело и когда был активизирован конкретный источник знаний. Для реализации такого свойства необходимо сделать две вещи. Во-первых, нужно изобрести механизм отслеживания действий модуля управления и источников знаний, а во-вторых — модифицировать некоторые операции, чтобы они записывали соответствующую информацию. Идея состоит том, чтобы регистрировать действия источников знаний и модуля управления в некотором центральном хранилище. Начнем с классов, обеспечивающих работу данного механизма. Во-первых, определим класс Action (Действие), регистрирующий действия источников знаний и модуля управления. Схема класса Action изображена на рис. 10.16. Например, если модуль управления выбрал конкретный источник знаний, он может создать экземпляр этого класса, установить указатель who (кто) на модуль управления, указатель what (что) — на активный источник знаний, указатель why (почему) — на какую-либо строку объяснения (например, содержащую приоритет предположения), и занести в аргумент when (когда) информацию о моменте создания. Первая часть нашей задачи решена, вторая тоже не очень сложна. Где же в нашей системе происходят важные события? Оказывается, основными являются следующие пять операций. • Методы, выдвигающие предположения. • Методы, отменяющие предположения. • Методы, активизирующие источники знаний. • Методы, применяющие правила. • Методы, регистрирующие подсказки, поступающие от источников знаний.
Глава 10. Искусственный интеллект: криптоанализ 485 Controller + addHint(KnowledgeSource): void + re set 0 : void + connect(KnowledgeSource): void + removeHirrt(KndwtedgeSource); void ι + processNextHirrtO; void + IsSolvedO: int + unabieToProceedQ: int \ f InferenceEngine KnowledgeSourc« |# + + + pastAssumptions: UnboundedOrderedCollsction iff! +creator Action flil ♦creator 0.* BlackboardObJect + registerQ: void + resignO: void + addO: void — π— Assumption .- plainLetter: char - reason: String - cipherLetter: char I + isRetractableQ : boolean I + retractO : void [ + AssumptionO ; void 1 1 II ,11111 III, II 11 1 li 11,1 II llllllll IIII II1 III Ш——HP—JI Рис. 10.16. Дополнительные функциональные свойства, обеспечиваемые классом Action Все эти события в основном сконцентрированы в двух местах: в конечном автомате модуля управления и в механизме выдвижения предположений. Следовательно, достаточно реализовать указанные методы. Это довольно утомительная, но не сложная задача. Для завершения работы необходимо реализовать классы, отвечающие на вопросы пользователя: кто, что, когда, почему? Разработать такой объект несложно, поскольку вся необходимая информация может быть найдена в экземплярах класса Actions.
486 Часть III. Приложения Изменение технических требований Если система работает устойчиво, то новые технические требования потребуют лишь минимальных изменений проекта. Рассмотрим три разновидности требований. • Возможность дешифровки криптограмм на иностранных языках. • Возможность дешифровки криптограмм с помощью перестановочного и простого подстановочного шифров. • Способность к самообучению. Первое требование самое простое, поскольку связь приложения с английским языком несущественна. Для того чтобы учесть новый язык, достаточно изменить правила, связанные с каждым источником знаний. Изменить набор символов несложно, поскольку даже класс Alphabet не зависит от символов, которым он манипулирует. Второе требование намного сложнее, но, тем не менее, вполне возможно в модели информационной доски. Наш подход предусматривает введение новых источников знаний о перестановочных шифрах. В данном случае также не требуется изменять основные абстракции проекта или механизмов. Достаточно лишь добавить новые классы, которые будут использовать существующие возможности, например, класс Inf erenceEngine и механизм выдвижения предположений. Третье требование выполнить труднее всего, так как обучение компьютеров относится к области искусственного интеллекта. Можно, например, предложить модулю управления в тупиковых ситуациях обращаться за подсказкой к пользователю системы. Такие предположения могут регистрироваться вместе с последовательностью действий, заведших систему в тупик, позволяя ей предотвращать подобные проблемы в будущем. Этот простейший механизм обучения можно внедрить в систему без излишнего изменения структуры классов, используя лишь действующие механизмы.
ГЛАВА 11 СБОР ДАННЫХ: МЕТЕОРОЛОГИЧЕСКАЯ СТАНЦИЯ Во многих научных системах автоматический сбор данных, как правило, осуществляется с помощью датчиков или других устройств. Этот процесс сбора информации связан с обработкой сигналов. В число компонентов таких систем входят датчики, преобразующие измеренные показатели в электрические сигналы, поступающие в аппаратуру для сбора данных. Для интерпретации этих сигналов изобретаются специальные управляющие устройства. Объектно-ориентированное проектирование систем сбора данных позволяет отделить оборудование, измеряющее показатели и накапливающее данные, от приложения, анализирующего эту информацию. С помощью этих методов можно создать устойчивую архитектуру, позволяющую добавлять или заменять датчики, не нарушая сложившуюся структуру системы. Применение интерфейсов, действующих в качестве оболочки оборудования, позволяет изолировать измеряющие устройства от приложения, обрабатывающего информацию. В главе приводится пример системы сбора данных на метеорологической станции. Эта система использует датчики и устройства, измеряющие погодные условия, которые отображаются на дисплее и подвергаются анализу. Этот пример иллюстрирует объектно-ориентированное решение, представляющее собой систему управления в реальном времени с архитектурой, допускающей повторное использование компонентов и отделение аппаратного оборудования от программного обеспечения. 11Л Начало Система мониторинга погоды — это простая задача, для решения которой достаточно лишь нескольких классов. Действительно, дилетант, слабо владеющий объектно-ориентированными методами, может попытаться решить эту за-
488 Часть III. Приложения дачу обычным способом, рассматривая поток данных и разные преобразования входных и выходных значений. Однако, как будет показано далее, для надежной работы даже такой небольшой системы лучше использовать объектно-ориентированную архитектуру. Помимо прочего, это позволяет проиллюстрировать некоторые из основных принципов, лежащих в основе объектно-ориентированного проектирования. Требования к метеорологической станции Проектируемая система должна обеспечивать автоматический мониторинг погодных условий, перечисленных ниже. • Скорость и направление ветра. • Температура воздуха. • Атмосферное давление. • Влажность воздуха. Кроме того, система должна вычислять производные параметры. • Коэффициент комфортности, или коэффициент охлаждения ветром (wind chill). • Точка росы (dew point temperature). • Тренд изменения температуры (temperature trend). • Тренд изменения атмосферного давления (barometric pressure trend). Система должна иметь средства для определения текущего времени и даты, чтобы создавать отчеты о максимальных и минимальных значениях четырех основных показателей за последние 24 часа. Система должна непрерывно выводить на дисплей текущие значения всех восьми первичных и производных показателей, а также текущее время и дату. С помощью клавиатуры пользователь может затребовать максимальные и минимальные значения любого из первичных параметров за 24 часа, а также момент измерения. Система должна предоставлять пользователю возможность проводить калибровку датчиков по известным значениям, а также устанавливать текущие время и дату. Определение границ рассматриваемой задачи Начнем анализ с рассмотрения аппаратной части системы, на которой будет работать программное обеспечение. По существу, эта задача относится к системному анализу и включает в себя вопросы, связанные с возможностями производства и стоимостью системы, которые выходят за рамки выбранной темы. Для того
Глава 11. Сбор данных: метеорологическая станция 489 чтобы очертить границы задачи и сосредоточиться на анализе и проектировании программного обеспечения, сделаем следующие стратегические предположения. • Процессор может находиться в персональном компьютере или ручном устройстве. • Время и дата поддерживаются встроенными часами. • Температура, атмосферное давление и влажность определяются удаленными датчиками. • Направление и скорость ветра измеряется с помощью флюгера, способного определять одно из 16 направлений, и анемометра со счетчиком оборотов. • Ввод команд пользователя осуществляется с помощью клавиатуры. • Экраном служит серийный жидкокристаллический дисплей. • Встроенный таймер выполняет прерывания каждые 1/60 долю секунды. Диаграмма развертывания, иллюстрирующая указанную аппаратную платформу, приведена на рис. 11.1. «Device» □ Keypad «Device» i Clock «Device» Q Graphics Display a «Device» Wind-direction Sensor J «Processor» ^ CPU «Device» r] Temperature и Sensor «Device» JU Humidity Sensor =w) «Device» m Wind-speed и Sensor «Device» Q Presssure Sensor _JJ Рис. 11.1. Диаграмма развертывания для системы TTMS Мы не будем рассматривать части аппаратного оборудования, чтобы уделить больше внимания программному обеспечению. Очевидно, можно было бы некоторые функции аппаратного оборудования перенести на программное обеспечение (например, исключить устройства для ввода команд и отображения графической информации). Однако в рамках данного приложения, имеющего объектно-ориентированную архитектуру, этот вопрос не имеет существенного значения. Действительно, одной из особенностей объектно-ориентированной системы является стремление использовать словарь проблемной области и наличие виртуальной
490 Часть III. Приложения машины, соответствующей абстракциям основных сущностей, образующих задачу. Изменения аппаратного обеспечения оказывают влияние лишь на абстракции, расположенные на нижних уровнях системы. Детали интерфейсов аппаратных устройств можно легко отделить от программных абстракций, скрыв их внутри соответствующих классов. Например, можно создать простой класс, обеспечивающий доступ к текущему времени и дате. Сначала мы проведем небольшой анализ и рассмотрим роли и обязанности этой абстракции1. Можно решить, что данный класс несет ответственность за отслеживание текущего времени в часах, минутах и секундах, а также в месяцах, днях и годах. Допустим, что в результате анализа было выделено две функции: currentTime (Текущее время) и currentDate (Текущая дата). Операция currentTime возвращает текстовую строку, содержащую текущие час, минуту и секунду: 13:56:42 Операция currentDate возвращает строку, показывающую текущие месяц, день и год. 6-10-93 Дальнейший анализ показывает, что более полные абстракции должны дать клиенту возможность выбирать между 12- и 24-часовым форматом представления времени с помощью дополнительного модификатора setFormat (Установить формат). Определяя поведение этой абстракции с точки зрения внешнего клиента, мы проводим четкую разграничительную линию между интерфейсом класса и его реализацией. Основная идея состоит в том, чтобы сначала определить внешний интерфейс каждого класса на основе предположения, что мы полностью контролируем базовую аппаратную платформу, а затем реализовать этот класс как мостик, соединяющий его внешний интерфейс с внутренним устройством. Таким образом, реализация класса на границе между аппаратным и программным обеспечением осуществляет связь между внешним представлением об абстракции и базовой аппаратной платформой, которую инженер-программист изменить не в состоянии. Разумеется, разрыв между программной абстракцией и внутренним устройством класса не должен быть слишком большим и требовать громоздкой реализации, "склеивающей" эти два слоя. Класс, обеспечивающий определение времени и даты, должен допускать начальную установку данных. Для этого необходимо добавить новые операции: setHour (Установить часы), setMinute (Установить минуты), setSecond *На самом деле, прежде чем проектировать новый класс, следует поискать уже существующий класс, соответствующий нашим целям. Класс, обеспечивающий доступ к времени и дате, определенно является хорошим кандидатом на повторное использование. Однако будем предполагать, что такого класса в готовом виде не существует.
Глава 11. Сбор данных: метеорологическая станция 491 (Установить секунды), setDay (Установить день), setMonth (Установить месяцы) и set Year (Установить год). Итоговая абстракция класса времени и даты выглядит следующим образом. Имя класса: TimeDate Ответственность: Отслеживать текущее время и дату. Операции: currentTime currentDate setFormat setHour setMinute setSecond setMonth setDay setYear Атрибуты: time date Экземпляры этого класса имеют динамический жизненный цикл, который можно отразить в диаграмме переходов на рис. 11.2. Как видим, при инициализации экземпляра этого класса происходит обнуление атрибутов time и date и безусловный переход в 24-часовый режим. Находясь в состоянии Running (Рабочий режим), класс может переключать 12- и 24-часовой режимы с помощью операции setFormat. Независимо от глубины вложения состояния объекта, переустановка времени и даты сопровождается автоматической нормализацией атрибутов. Аналогично, запрос текущего времени или даты заставляет объект вычислять новую текстовую строку. Мы описали функциональные возможности этой абстракции достаточно подробно, для того чтобы использовать ее в рамках сценариев работы с другими клиентами, которые могут выявиться при анализе. Прежде чем переходить к изучению этих сценариев, опишем поведение других объектов системы. Класс Temperature Sensor (Температурный датчик) является аналогом аппаратного температурного датчика. Изолированный анализ этого класса в первом приближении приводит к следующей абстракции внешнего интерфейса. Имя класса: Temperature Sensor
492 Часть III. Приложения i Initializing Вход / обнуление времени и даты текущее время или дата / вычисление текстовой строки установить время или дату / нормализовать значение Рис. 11.2. Жизненный цикл класса TimaDate Ответственность: Отслеживание текущей температуры. Операции: currentTemperature setiLowTemperature setHighTemperature Атрибуты: temperature Название операции currentTemperature (Текущая температура) вполне информативно. Назначение двух других операций непосредственно следует из требований к системе, предусматривающих калибровку датчиков. Предположим, что каждый температурный датчик представляет результат измерения в виде числа с фиксированной точкой из диапазона, калиброванного по известным предельным значениям. Промежуточные значения температуры вычисляются с помощью линейной интерполяции между двумя точками, как показано на рис. 11.3. Внимательный читатель может поинтересоваться, зачем мы предлагаем специальный класс для этой абстракции, в то время как в требованиях сказано, что в системе может быть только один температурный датчик? Дело в том, что мы выделяем эту абстракцию в отдельный класс, чтобы иметь возможность повторно ее использовать. На самом деле количество температурных датчиков, управляемых системой, не должно влиять на ее архитектуру. Разрабатывая любой класс, мы допускаем возможность его использования в других системах, содержащих не один, а несколько датчиков. Абстракция датчика атмосферного давления может выглядеть так. Имя класса: Pressure Sensor
Глава 11. Сбор данных: метеорологическая станция 493 Фактическая температура 20 Η Показания датчика Рис. 11.3. Калибровка датчика температуры Ответственность: Отслеживание текущего атмосферного давления. Операции: currentPressure setLowPressure setHighPressure Атрибуты: pressure Изучение требований к системе показывает, что была упущена одна важная характеристика классов Temperature Sensor и Pressure Sensor: определение тренда изменения температуры и атмосферного давления. Поскольку сейчас мы пребываем на этапе анализа, а не проектирования, достаточно сосредоточиться на природе этих функций и, что самое важное, решить, какая абстракция должна отвечать за их выполнение. Объекты класса Temperature Sensor и Pressure Sensor (Датчик атмосферного давления) могут показывать тренд изменения в виде числа с плавающей точкой, изменяющегося в диапазоне от —1 до 1 и представляющего собой наклон графика изменений температуры и давления на некотором интервале времени2. Таким образом, описание двух этих классов следует дополнить ответственностью и соответствующей операцией. 2Нулевое значение означает, что температура или давление остаются неизменными. Значение 0,1 свидетельствует о небольшом росте, значение -0,3 соответствует резкому падению температуры или давления. Значения, близкие к -1 и 1, являются признаком стихийного бедствия, выходящего за рамки допустимых сценариев.
494 Часть III. Приложения Ответственность: Определение тренда изменения давления или температуры в виде наклона линейного графика, аппроксимирующего значения показателя за указанный интервал времени. Операции: trend Поскольку эта функциональная возможность является общей для обоих классов Temperature Sensor и Pressure Sensor, целесообразно создать общий суперкласс Trend Sensor (Датчик тренда). Для полноты картины заметим, что возможна альтернативная точка зрения. В данном проекте ответственность за определение тренда возлагается на датчики. В то же время, можно было бы реализовать эту функциональную возможность во внешнем агенте, который периодически опрашивал бы датчики и вычислял тренд. Однако мы отвергли этот подход как неоправданно сложный. Первоначальное описание классов Temperature Sensor и Pressure Sensor подразумевало, что эти абстракции обладают достаточными знаниями, позволяющими вычислять тренд самостоятельно. Объединив общие функции в суперклассе Trend Sensor, мы получили простую и связную абстракцию. Абстракцию, соответствующую датчику влажности, можно определить так. Имя класса: Humidity Sensor Ответственность: Отслеживание текущей влажности, выраженной в процентах насыщения от 0% до 100%. Операции: currentHumidity setLowHumidity setHighHumidity Атрибуты: humidity Класс Humidity Sensor (Датчик влажности) не обязан вычислять тренд и поэтому не является подклассом класса Trend Sensor. Анализ требований, предъявляемых к системе, подразумевает наличие общих функциональных возможностей у всех трех классов Temperature Sensor, Pressure Sensor и Humidity Sensor. В частности, датчики должны сообщать максимальные и минимальные значения каждого показателя за последние 24 часа. Мы пока не будем описывать реализацию этих функциональных возможностей, поскольку этот вопрос относится к проектированию, а не к анализу системы. Однако, поскольку эта функция является общей для всех трех классов,
Глава 11. Сбор данных: метеорологическая станция 495 целесообразно создать общий суперкласс Historical Sensor (Датчик ретроспективных данных). Имя класса: Historical Sensor Ответственность: Отчеты о максимальных и минимальных значениях за 24 часа. Операции: highValue lowValue timeOfHighValue timeOfLowValue Класс Humidity Sensor, как и класс Trend Sensor, являющийся промежуточным абстрактным классом, соединяющим абстрактный класс Historical Sensor и конкретные классы Temperature Sensor и Pressure Sensor, — это прямой потомок класса Historical Sensor. Абстракция датчика скорости ветра может выглядеть так. Имя класса: WindSpeed Sensor Ответственность: Отслеживание текущей скорости ветра. Операции: currentSpeed setLowSpeed setHighSpeed Атрибуты: speed Требования к системе не предусматривают непосредственное измерение скорости ветра. Этот показатель должен вычисляться как отношение количества оборотов анемометра к продолжительности измерений. Полученное число необходимо умножить на масштабирующий множитель, значение которого определяется конструкцией анемометра. Совершенно очевидно, что этот алгоритм должен быть скрыт внутри класса. Клиенты могут не беспокоиться о том, как именно выполняется операция currentSpeed, если она полностью соответствует контракту и возвращает осмысленные значения. Беглый анализ последних четырех классов системы (Temperature Sensor, Pressure Sensor, Humidity Sensor и WindSpeed Sensor) показывает, что у них есть общее функциональное свойство: в каждом из этих классов калибровка осуществляется с помощью линейной интерполяции. Для того чтобы
496 Часть III. Приложения не реализовывать эту функцию в каждом из классов, мы предпочли создать особый суперкласс Calibrating Sensor (Датчик калибровки). Его спецификация приводится ниже. Имя класса: Calibrating Sensor Ответственность: Осуществляет линейную интерполяцию значений, лежащих в известном интервале. * Операции: currentValue setLowValue setHighValue Класс Calibrating Sensor является непосредственным суперклассом по отношению к классу Historical Sensor3. Последний рассматриваемый датчик, предназначенный для определения направления ветра, немного отличается от всех остальных, поскольку не производит калибровку и не хранит предыдущие значения. Эту абстракцию можно описать следующим образом. Имя класса: WindDirection Sensor Ответственность: Отслеживание текущего направления ветра по компасу. Операции: currentDirection Атрибуты: direction Для того чтобы объединить все абстракции, мы создали абстрактный базовый класс Sensor (Датчик), являющийся непосредственным суперклассом для WindDirection Sensor (Датчик направления ветра) и Calibrating Sensor (Датчик калибровки). Полная иерархия классов приведена на рис. 11.4. Абстракция клавиатуры имеет относительно простую спецификацию. Имя класса: Keypad Ответственность: Реакция на нажатие клавиш. 3Эта иерархия удовлетворяет условиям критерия: класс Temperature Sensor является разновидностью класса Trend Sensor, который в свою очередь является разновидностью класса Historical Sensor» производного от класса Calibrating Sensor.
Глава 11. Сбор данных: метеорологическая станция 497 Sensor Calibrating Sensor + currentVaiueQ •f setHighValueQ + setLowValueQ Humidity Sensor humidity: 4 currentHumidityQ WlndDirectlon Sensor direction: + currentDirectionQ Historical Sensor + highValueQ 4- lowVatueQ ■f timeOfHighVatueO 4 limeOfLowValueQ —_ Trend Sensor 4 trendQ WindSpeed Sensor speed: 4 currentSpeedQ Temperature Sensor temperature: 4 currentTemperatureO Pressure Sensor pressure: 4 currentPressureQ Рис. 11.4. Иерархия класса Sensor Операции: lastKeyPress Атрибуты: key
498 Часть III. Приложения Следует подчеркнуть, что в этом классе предназначение клавиш неизвестно: экземпляр данного класса реагирует лишь на нажатие одной из нескольких клавиш. Ответственность за интерпретацию смысла этих нажатий возложена на другой класс, который будет определен, когда мы станем применять эти классы в рамках разработанных сценариев. Абстракция LCD Device позволяет отделить программное обеспечение от используемого аппаратного оборудования. Для этого необходимо создать прототипы дисплеев и затем определить основные требования к интерфейсу. Один из таких прототипов продемонстрирован на рис. 11.5. Здесь проигнорированы требования показывать коэффициент комфортности и точку росы, а также детали представления максимальных и минимальных измерений за последние 24 часа. Тем не менее, существует несколько шаблонов: необходимо выводить на экран только текст (используя два размера и два стиля) и линии (различной толщины). Кроме того, одни элементы изображения являются статическими (например, метка TEMP), а другие — динамические (например, направление ветра). Как статические, так и динамические элементы изображения генерируются с помощью программного обеспечения. Это позволяет снять нагрузку на аппаратное оборудование и не создавать специальные метки на жидкокристаллических дисплеях за счет усложнения программного обеспечения. ДАТА: 6-10-2005 ВРЕМЯ: 13:56:42 ТЕМПЕРАТУРА: 14°С ДАВЛЕНИЕ: 29.96 ВЛАЖНОСТЬ: 38% Рис. 11.5. Дисплей в системе мониторинга погодных условий Эти требования можно выразить с помощью следующей спецификации класса. Имя класса: LCD Device Ответственность: Управление жидкокристаллическим дисплеем для изображения графических элементов. Операции: drawText drawLine drawCircle W-i 7км/час }—Ε СКОРОСТЬ
Глава 11. Сбор данных: метеорологическая станция 499 setTextSize setTextStyle setPenSize Как и класс Keypad (Клавиатура), в классе LCD Device (Жидкокристаллический дисплей) смысл графических элементов не определен. Экземпляры этого класса умеют только выводить текст и линии, но не интерпретируют смысл изображаемых фигур. Это разделение понятий позволяет создать слабо связанные абстракции, однако требует посредника между датчиками и дисплеем. Отложим разработку этой абстракции до момента, когда начнем изучать сценарии работы системы. Последним классом, который необходимо рассмотреть, является таймер. Для простоты предположим, что в системе есть только один таймер, выполняющий системные прерывания 60 раз в секунду. Эта часть системы особенно запутанная, поэтому лучше всего скрыть детали реализации таймера от остальных абстракций программного обеспечения. Для этого можно создать класс, использующий функцию обратного вызова и экспортирующий только статические элементы класса (тем самым мы выполним требование, допускающее только один таймер). На рис. 11.6 приведена диаграмма взаимодействий, иллюстрирующая прецедент использования описанной выше абстракции. Как видим, сначала клиент передает таймеру функцию обратного вызова, а затем с периодичностью в 1/60 секунды таймер вызывает эту функцию. Таким образом, клиент может не заботиться о том, как именно выполняются прерывания, а таймер не обязан знать, что делать при выполнении прерываний. Единственная обязанность клиента — выполнение функции обратного вызова не должно превышать 1/60 секунды, иначе таймер может пропустить событие. Перехватывая временные события, класс Timer (Таймер) является активной абстракцией, т.е. корнем потока управления. Эту абстракцию можно описать с помощью следующей спецификации. Имя класса: Timer Ответственность: Перехват всех временных событий и управление функцией обратного вызова. Операции: setCallbackO Сценарии Определив основные абстракции системы, рассмотрим некоторые прецеденты использования системы. Для начала перечислим основные прецеденты использования системы (рис. 11.7) с точки зрения ее пользователя.
500 Часть III. Приложения aClitntiClltnt timtrmmtr D" 3etCallback(Tlck) Установка функции обратного в 5 сг О" I I * » г / Класс Timer перехватывает программные прерывания каждые 1/60 с и передает клиенту функцию обратного вызова {1/60 сек.} Рис. 11.6. Диаграмма взаимодействий класса Timer • Мониторинг основных погодных показателей: скорости и направления ветра, атмосферного давления, температуры и влажности воздуха. • Мониторинг производных показателей: коэффициента комфортности, точки образования росы, трендов температуры и атмосферного давления. • Демонстрация максимальных и минимальных значений выбранных показателей. • Установка времени и даты. • Калибровка выбранных датчиков. • Активизация системы. Укажем два вторичных прецедента использования системы. • Отказ питания. • Отказ датчика. 11.2 Проектирование Рассмотрим несколько сценариев, позволяющих понять поведение (но не структуру) системы.
Глава 11. Сбор данных: метеорологическая станция 501 Измерения погодных показателей Включение Отсдокивание производных показателей Демонстрация максимального и минимального значений W J Установка даты и времени Калибровка датчика Рис. 11.7. Основные прецеденты использования системы мониторинга погодных условий Прецеденты использования системы мониторинга погодных условий Главной задачей системы является мониторинг основных погодных показателей. Одно из ограничений системы состоит в невозможности обрабатывать информацию с частотой, превышающей 60 измерений в секунду. К счастью, наиболее интересные погодные показатели изменяются гораздо медленнее. Анализ показывает, что показатели достаточно измерять с частотой, указанной ниже. • Направление ветра: каждые 0,1 секунды. • Скорость ветра: каждые 0,5 секунды. • Температура, атмосферное давление и влажность: каждые 5 минут. Было решено, что классы, описывающие основные датчики, не должны обрабатывать временные события. Следовательно, необходим внешний агент, взаимодействующий с датчиками. Описание поведения этого агента пока преждевременно, так как способ инициализации измерений относится к проектированию. Этот сценарий иллюстрируется диаграммой взаимодействий, приведенной на рис. 11.8. Как видим, когда агент начинает измерения, он последовательно опрашивает датчики, произвольно пропуская некоторые из них, чтобы уменьшить частоту их опроса. Опрос датчиков обеспечивает более предсказуемое поведение системы, поскольку агент может контролировать поток событий. Стремясь сделать имена как можно более информативными, назовем этот класс Sampler (Коллектор).
502 Часть III. Приложения anAgent:' ©: WinDirection Sensor: ; ©:WinSpeed Sensor: \ ©:Temperature Sensor: i' ©:Pressure Sensor: j ©:Humidity Sensor: {1c} I 1: sample () J | {.5 c} —| HL!gtel» {5 мин.} —^- I {5 мин.} —*- I ι {5 мин.} 'h- 3: sample () I 4: sample () 13 5: sample () и Рис. 11.8. Сценарий основных измерений Продолжим изучение этого сценария и решим, какие из объектов, представленных на диаграмме взаимодействий, обязаны выводить показатели на экран дисплея, т.е. передавать данные экземпляру класса LCD Device. Можно было бы возложить ответственность за это на классы датчиков (подобная схема реализована в архитектурах, подобных MVC (Model-View-Controller — Модель-Вид- Контроллер)) либо создать отдельный объект. Выберем второй вариант, чтобы можно было инкапсулировать все проектные решения, касающиеся механизмов реализации вывода параметров на экран, внутри отдельного класса4. Итак, анализ привел нас к описанию нового класса. Имя класса: Display Manager Ответственность: Управление выводом элементов изображений на экран дисплея. Операции: drawS tat id terns displayTime displayDate displayTemperature displayHumidity displayPressure displayWindChill displayDewPoint displayWindSpeed displayWindDirection displayHighLow 4Основная проблема — где показать элемент, а не как он должен выглядеть. Поскольку вполне вероятно, что это решение будет изменено, лучше инкапсулировать внутри класса всю информацию о месте изображения элементов на жидкокристаллическом дисплее.
Глава И. Сбор данных: метеорологическая станция 503 Операция drawStaticItems показывает постоянные элементы изображений, например, розу ветров для индикации направления ветра. Кроме того, предполагается, что операции displayTemperature и displayPressure должны выводить на экран тренды соответствующих показателей (следовательно, на этапе реализации необходимо указать подходящую сигнатуру для этих операций). На рис. 11.9 приведена диаграмма классов, иллюстрирующая абстракции, взаимодействующие в рамках одного сценария. Обратите внимание на роль, которую каждая абстракция играет в отношениях с другими классами. г_. ,„, .,, ', О WindSpeed Sensor I О WlndDirection Sensor r j . }— — ~~ j L77I,r~~~~~~ ~Τ7ΤΓΙ.~ ..J Θ Temperature Sensor j - источник данных \ L·^,^—,„_.,_ „.._.„ J /-источник данных -источникданных "^.. \ F φ Sampler i α sensors: Sensors „„ I «^display ^Display Manager j © LCD Device j Г# setSamplingRate (Τ i ΰ__~ Γ-Γ JZi I · sample () - сбор данных - менеджер дисплея ._ -источникданных # sampler (_)_}"" , q нит^цу sensor У \ \ β Display Manageil r _ ~ \" источник данных \ _ _._j Θ Pressure Sensor j 1^Г(ЭДаТ(')~^'""'' 1 JZZZZZIZII UI ] Рис. 11.9. Классы Sampler и Display Manager Включение класса Display Manager (Менеджер дисплея) имеет важный побочный эффект5. В результате этого решения интернационализация программного обеспечения, т.е. его адаптация к разным странам и языкам, становится намного проще, поскольку имена и метки элементов (например, TEMP и WIND) скрыты внутри одного класса. Интернационализация вынуждает нас рассмотреть вопросы, не указанные среди требований. Как измерять температуру: по Цельсию или по Фаренгейту? Как измерять скорость ветра: в километрах в час или в милях в час? Очевидно, программное обеспечение не должно жестко ограничивать пользователей. Поскольку система должна обладать гибкостью, в классы Temperature Sensor и Wind- Speed Sensor следует добавить еще одну операцию — setMode (Установить систему измерений). Кроме того, необходимо добавить в описание этих классов новую функцию, предусматривающую перевод создаваемых объектов в заранее выбранное состояние. В заключение, необходимо изменить сигнатуру операции 5На каком этапе следует принимать это решение: на этапе анализа или проектирования? Этот вопрос носит несколько академичный характер. Если решение помогает глубже понять поведение системы и приводит к элегантной архитектуре, не имеет значения, на каком этапе оно принято.
504 Часть III. Приложения DisplayManager: : drawStaticItems так, чтобы при изменении единиц измерений панель дисплея могла обновляться. Итак, необходимо добавить один сценарий: • Установка единиц измерения температуры и скорости ветра. Отложим рассмотрение этого сценария до того момента, когда мы изучим другие прецеденты использования системы, имеющие отношение к пользовательскому интерфейсу. Мониторинг производных показателей, в частности, трендов температуры и давления, можно обеспечить с помощью протоколов, установленных для классов Temperature Sensor и Pressure Sensor. Однако, чтобы завершить разработку сценария измерения всех вторичных показателей, следует ввести два новых класса, Wind Chill (Коэффициент комфортности) и Dew Point (Точка росы). Ни одна из этих абстракций не является датчиком, поскольку они не описывают работу какого-либо материального устройства в системе. Они действуют как агенты, взаимодействующие с другими классами. В частности, класс Wind Chill сотрудничает с классами Temperature Sensor и WindSpeed Sensor, а класс Dew Point сотрудничает с классами Temperature Sensor и Humidity Sensor. В свою очередь, классы Wind Chill, Dew Point и Sampler используют один и тот же механизм опроса датчиков. На рис. 11.10 показаны классы, вовлеченные в анализируемый сценарий. В целом, эта диаграмма классов мало отличается от диаграммы классов, приведенной на рис. 11.9. Θ Wind СЫН G WindSpeed Sensor ©Dew Point С Ι Θ Display Manager h» dispTiyT) : © Sampler | a~!£nsorsΤ Sensors a display : Display Manager (•setSamplingRate () ~>1 · sample () ! · sampler () - сбор данных _ - . Ν/ „ Θ Humidity Sensor Рис. 11.10. Классы для измерения производных показателей Почему абстракции Wind Chill и Dew Point определены в виде классов, а не с помощью самостоятельных функций? Дело в том, что они удовлетворяют
Глава 11. Сбор данных: метеорологическая станция 505 критерию объектно-ориентированных абстракций. Экземпляры этих классов обладают определенными функциональными возможностями (а именно, вычисляют некие величины), инкапсулируют определенное состояние (каждый из них обязан взаимодействовать с конкретным экземпляром одного из двух датчиков) и обладают уникальной индивидуальностью (в каждой ассоциации датчика скорости ветра и температуры должен участвовать отдельный экземпляр класса Wind Chill). "Объективация" этих, на первый взгляд, алгоритмических абстракций повышает вероятность их повторного использования: классы Wind Chill и Dew Point можно легко использовать в других системах программного обеспечения, поскольку каждый из них обладает ясным контрактом и четко отделен от всех остальных абстракций. Перейдем к изучению сценариев взаимодействия пользователя и системы. Определение оптимальной последовательности действий пользователя в ходе работы со встроенным контроллером, как и проектирование графического интерфейса, является скорее искусством, а не наукой. Описание принципов разработки интерфейсов выходит за рамки данной книги, но разработчики должны знать, что использование прототипов является эффективным способом и позволяет существенно уменьшить риск, связанный с разработкой интерфейса пользователя. Более того, реализация проектных решений в виде объектно-ориентированной архитектуры облегчает внесение изменений и не требует переделки проекта. Рассмотрим некоторые из возможных прецедентов использования системы. Название прецедента: Display Max and Min Value of Measurement (Вывод на экран максимального и минимального показателя) Описание: В результате выполнения этого сценария на экран выводятся максимальное и минимальное значения указанного показателя. Основной поток: 1. Пользователь нажимает клавишу SELECT (Выбрать). 2. Система выводит на экран сообщение SELECTING (Выбор). 3. Пользователь нажимает одну из следующих клавиш: WIND (Ветер), TEMP (Температура), PRESSURE (Давление) или HUMIDITY (Влажность). Нажатие любой другой клавиши (кроме клавиши RUN (Выполнить)) игнорируется. 4. На экране начинает мигать соответствующая метка. 5. Пользователь нажимает клавишу UP (Вверх) или DOWN (Вниз), выбирая вариант вывода — максимальное или минимальное значение. Нажатие любой другой клавиши (кроме клавиши RUN) игнорируется.
506 Часть III. Приложения 6. Система выводит на экран выбранное значение, а также время его измерения. 7. Управление передается на пункт 3 или 5. Обратите внимание на то что, нажимая клавишу RUN, пользователь может послать команду или прекратить ее выполнение. В этом случае мигающая метка и сообщение SELECTING удаляются с экрана. Этот сценарий показывает, что необходимо расширить описание класса Dis- playManager, добавив к нему операции f lashLabel (вызывает мигание метки на экране и его прекращение в зависимости от аргумента) и displayMode (выводит на жидкокристаллический дисплей текстовое сообщение). Процесс установки времени и даты описывается аналогично. Название прецедента: Set Date and Time (Установка времени и даты). Описание: Процесс установки времени и даты. Основной поток: 1. Пользователь нажимает клавишу SELECT. 2. Система выводит на экран сообщение SELECTING. 3. Пользователь нажимает клавишу TIME (Время) или DATE (Дата). Нажатие любой другой клавиши (кроме клавиши RUN и клавиш, перечисленных в пункте 3 предыдущего сценария) игнорируется. 4. На экране начинают мигать соответствующие метка и первое поле выбранного пункта (час или месяц). 5. Для выбора другого поля (выбранные поля выводятся рядом) пользователь нажимает клавишу LEFT (Влево) или RIGHT (Вправо). Увеличить или уменьшить значения можно, нажав клавишу UP или DOWN. 6. Управление передается на пункт 3 или 5. Обратите внимание на то что, нажимая клавишу RUN, пользователь может послать команду или прекратить ее выполнение. В этом случае мигающая метка и сообщение SELECTING удаляются с экрана, а время и дата устанавливаются заново. Калибровка конкретного датчика производится следующим образом. Название прецедента: Calibrate Sensor (Калибровка датчика). Описание:
Глава И. Сбор данных: метеорологическая станция 507 Процесс калибровки датчика. Основной поток: 1. Пользователь нажимает клавишу CALIBRATE (Калибровать). 2. Система выводит на экран сообщение CALIBRATING (Калибровка). 3. Пользователь нажимает одну из следующих клавиш: WIND, TEMP PRESSURE или HUMIDITY. Нажатие любой другой клавиши (кроме клавиши RUN) игнорируется. 4. Соответствующая метка начинает мигать на экране. 5. Для того чтобы указать минимальное и максимальное значения для калибровки, пользователь нажимает клавишу UP или DOWN. 6. Соответствующее калибровочное значение начинает мигать на экране. 7. Для того чтобы изменить значение выбранной величины, пользователь нажимает клавиши UP или DOWN. 8. Управление передается на пункт 3 или 5. Обратите внимание на то что, нажимая клавишу RUN, пользователь может послать команду или прекратить ее выполнение. В этом случае мигающая метка и сообщение CALIBRATING удаляются с экрана, а калибровочная функция сбрасывается. В процессе калибровки все экземпляры класса Sampler (Коллектор) должны прекратить опрос датчиков, иначе на экран будут выведены неверные данные. Следовательно, в класс Sampler необходимо включить две операции: inhibit- Sample (Прекратить опрос) и resumeSample (Возобновить опрос). Последний из основных сценариев описывает процесс установки единиц измерений. Название прецедента: Set Unit of Measurement (Установка единиц измерений). Описание: Процесс установки единиц измерения. Основной поток: 1. Пользователь нажимает клавишу MODE (Режим). 2. Система выводит на экран сообщение MODE. 3. Пользователь нажимает одну из следующих клавиш: WIND, TEMP PRESSURE или HUMIDITY. Нажатие любой другой клавиши (кроме клавиши RUN) игнорируется. 4. Соответствующая метка начинает мигать на экране.
508 Часть III. Приложения 5. Для того чтобы выбрать единицы измерения, пользователь нажимает клавишу UP или DOWN. 6. Система изменяет единицы измерения. 7. Управление передается на пункт 3 или 5. Обратите внимание на то что, нажимая клавишу RUN, пользователь может послать команду или прекратить ее выполнение. В этом случае мигающая метка и сообщение MODE удаляются с экрана, и происходит возврат к предыдущей единице измерения. Изучение прецедентов использования системы приводит к эскизу клавиатуры (системное решение), представленному на рис. 11.11. ШетЛВШ1Ш/*%ШШЛ: Pressure Humidity ШМ1Ш11ШМпс1 ISclecflll Calibrate IHlModel Рис. 11.11. Клавиатура для системы мониторинга погодных условий Каждый из рассмотренных сценариев носит модельный характер, т.е. зависит от определенных событий. По этой причине их удобно представлять в виде диаграмм состояний. Поскольку эти сценарии тесно связаны друг с другом, мы решили выделить отдельный класс InputManager (Диспетчер ввода), имеющий следующую концептуальную спецификацию. Имя класса: InputManager Ответственность: Управление и диспетчеризация команд пользователя. Операции: processKeyPress Единственная операция класса — processKeyPress (Обработать нажатие клавиши) — приводит в действие конечный автомат, лежащий в основе каждого экземпляра данного класса. Как показано на рис. 11.12, диаграмма конечного автомата, лежащего в основе класса InputManager, охватывает четыре состояния: Running, Calibrating, Selecting и Mode. Эти состояния соответствуют рассмотренным выше сценариям. Переход в новое состояние определяется первой клавишей, нажатой
Глава 11. Сбор данных: метеорологическая станция 509 в состоянии Running, а возврат в состояние Running осуществляется после нажатия клавиши Run. При возврате в состояние Running сообщение стирается с экрана. *х. I Running ρ 11 Стереть сообщение γ-γγ-ττ-χ^ Calibrate / Run- Run ^-· ΟΙ Selecting \ ('Run ι *н 1аа?общвния \ / ~ JlL I Calibrating •It Вывод сообщения 4. ΓΙ' Calibrating «Mode HI Вывод сообщения Mode >/ m waiting) \ Temp '-.. Wind •flf ••Processing .-Ж τη Wnd Tempi ШТетР! *im I Wind J (H ) Up | Down/переключение режима ( Рис. 11.12. Диаграмма конечных автоматов для класса InputManager Для того чтобы показать, как можно формализовать динамическую семантику сценария, мы раскрыли состояние Mode на диаграмме. При первом переходе в это состояние на экране появляется соответствующее сообщение. Затем система переходит в состояние Waiting (Ожидание), пока пользователь не нажмет одну из клавиш TEMP или WIND, переводя систему во вложенное состояние Processing (Обработка), или клавишу Run, переводя систему в состояние Running. Каждый раз при переходе в состояние Processing на экране начинает мигать соответствующая метка. В дальнейшем при переходе в это состояние система сразу переходит в предыдущее вложенное состояние TEMP или WIND. Находясь в состояниях Temp или Wind, система перехватывает нажатие пяти клавиш: UP или DOWN (Переключение режимов), TEMP или WIND (Переход в другое вложенное состояние) и RUN (выход из состояния Mode). Состояния Selecting и Calibrating можно раскрыть аналогично, но не будем этого делать, чтобы не загромождать диаграмму6. естественно, при создании реального продукта всеобъемлющий анализ должен завершиться составлением полной диаграммы переходов. Мы пропускаем эту часть работы, потому что она достаточно утомительна и не добавляет новых знаний о создаваемой системе.
510 Часть III. Приложения Последний из основных сценариев относится к включению системы в работу. Для этого необходимо создать все ее объекты в требуемой последовательности и привести их в устойчивое начальное состояние. Соответствующий сценарий выглядит следующим образом. Название прецедента: Power On (Включение системы) Описание: Процесс включения питания. Основной поток: 1. Выполнение прецедента начинается, когда в систему поступает электрический ток. 2. Создаются датчики. Датчики, хранящие предыдущие показания, стирают свою память. Датчики с трендом выполняют алгоритм вычисления тренда. 3. Инициализируется буфер клавиатуры, при этом из него удаляется случайная информация, вызванная помехами при включении электропитания. 4. На экран выводятся статические элементы. 5. Начинается опрос датчиков. Постусловия: Последние минимальные и максимальные значения параметров устанавливаются равными результатам их первого измерения. Тренды температуры и давления являются плоскими. Класс InputManager находится в состоянии Running. Обратите внимание на то, что постусловия описывают ожидаемое состояние системы после завершения сценария. Этот сценарий выполняют несколько взаимодействующих агентов, каждый из которых самостоятельно приводит себя в устойчивое начальное состояние. На этом изучение основных сценариев работы системы мониторинга погодных условий завершается. Для полноты анализа можно было бы рассмотреть несколько вторичных сценариев, но мы описали достаточно много функциональных свойств системы, так что пора перейти к проектированию ее архитектуры и обоснованию принятых стратегических решений. В основе каждой системы программного обеспечения должны лежать простые, но хорошо продуманные организационные принципы. Система мониторинга погоды не исключение. На следующем этапе процесса разработки системы необходимо определить ее архитектурную основу, образующую устойчивый фундамент для реализации всех функциональных возможностей системы.
Глава 11. Сбор данных: метеорологическая станция 511 Архитектурная основа В области сбора данных и процессов управления существует много архитектурных шаблонов, но наиболее распространенными являются синхронизация автономных действующих лиц и модель временных рамок (time-frame-based processing). В первом шаблоне архитектура системы объединяет множество относительно независимых объектов, каждый из которых имеет собственный поток управления. Например, можно было бы сконструировать несколько новых объектов, построенных из более простых аппаратных и программных абстракций и предназначенных для сбора информации, поступающей с определенного датчика, и передачу ее центральному агенту, обрабатывающему полученные данные. Подобная архитектура имеет свои преимущества. При проектировании распределенной системы, накапливающей данные, поступающие от удаленных датчиков, такая архитектура является единственной приемлемой моделью. Кроме того, она позволяет оптимизировать процесс сбора данных (каждый объект, собирающий информацию, может приспосабливаться к изменению окружающих условий, например, увеличивая или уменьшая частоту опроса). Однако этот архитектурный шаблон не всегда подходит для создания жестких систем реального времени, которые должны обеспечивать предсказуемость процесса обработки. Несмотря на то что систему мониторинга погодных условий нельзя отнести к этой категории, она должна функционировать надежно и предсказуемо. По этой причине мы выбрали альтернативный вариант — модель временных рамок (кадров). Как показано на рис. 11.13, в этой модели процесс мониторинга разбивается на временные интервалы (как правило, фиксированной длины), которые далее делятся на подынтервалы, каждый из которых предназначен для выполнения определенной функции. Различные временные интервалы могут быть предназначены для разных действий. Например, направление ветра можно измерять через 10 кадров, а скорость ветра — через 30 кадров7. Основное преимущество этой модели заключается в том, что она допускает более жесткий контроль последовательности событий. Временная рамка Рис. 11.13. Модель временных рамок Например, если продолжительность кадра равна 1/60 секунды, то продолжительность 30 кадров составит 0,5 секунды.
512 Часть III. Приложения На рис. 11.14 приведена диаграмма классов, отражающая архитектуру системы мониторинга погодных условий. Большей частью она состоит из классов, выявленных на предыдущем этапе анализа. В отличие от предыдущих диаграмм, на диаграмме классов показаны способы взаимодействия между ключевыми абстракциями. Как правило, на диаграммах классов не показываются все существующие классы и все отношения между ними. Например, на рис. 11.14 не продемонстрирована иерархия классов, описывающих работу датчиков. ΓΊ§ Pressure Sensor 4^ ^ WindSpeed Sensor PbwindChlR ©Humidity Sensor rwi^p^ggpi 0 Temperature Sensor Рис. 11.14. Архитектура системы мониторинга погодных условий Кроме того, мы включили в архитектуру системы новый класс Sensors, представляющий собой коллекцию всех физических датчиков. Поскольку по крайней мере два агента (Sampler и InputManager) должны взаимодействовать со всеми датчиками, их размещение в одном и том же контейнерном классе позволяет рассматривать все датчики как одно логическое целое.
Глава 11. Сбор данных: метеорологическая станция 513 11.3 Конструирование Основные функциональные возможности системы реализуются классами Sampler и Timer. Следовательно, чтобы обосновать наши предположения, при разработке архитектуры следует проявлять особую осторожность. Механизм временных рамок Начнем с уточнения внешнего интерфейса класса Timer, осуществляющего диспетчеризацию функции обратного вызова. Его структура показана на рис. 11.15. • setCallback (Tick) • startTimhg () • numberOfiicte (); Tick Рис. 11.15. Структура класса Timer Класс Timer довольно интересен — он содержит необычную информацию. Функция-член setCallback используется для передачи таймеру функции обратного вызова. Таймер запускается с помощью вызова функции startTiming, после чего единственный экземпляр класса Timer начинает вызывать функцию обратного вызова каждую 1/60 секунды. Обратите внимание на то что функция запуска указана явно, поскольку нельзя полагаться ни на одну конкретную реализацию порядка обработки объявлений. Прежде чем перейти к классу Sampler, введем новое объявление, перечисляющее разные датчики, входящие в систему. Класс SensorNames содержит литеральные перечисления всех датчиков системы. Его интерфейс показан на рис. 11.16. «enumeration» [ :~SensorName ^DirectiorT ι ο Speed о WindChill о Temperature о DewPoint о Humidity о Pressure^ j Рис. 11.16. Интерфейс класса SamplerClass «type» j ©Tick ι f -* такты часов. I отсчитывает каждые 1/60 сек. Θ Sampler • setSamplingRate (Tick, SensorName ) • sample (Tick ) • samplingRate (): Tick
514 Часть III. Приложения Для того чтобы клиент мог динамически изменять поведение объекта, собирающего данные, мы включили в класс модификатор setSamplingRate (Установить скорость опроса) и его селектор samplingRate (Скорость опроса). Для того чтобы связать классы Timer и Sampler друг с другом, необходимо написать фрагмент кода на языке C++. Сначала объявим экземпляр класса Sampler, а потом опишем функцию, не являющуюся частью этого класса. Sampler sampler; void acquire(Tick t) { sampler.sample(t); } Теперь можно написать функцию main, связывающую функцию обратного вызова с таймером и запускающую процесс опроса датчиков. main () { Timer::setCallback(acquire); Timer::startTiming(); while(1){ r } return 0; } Эта программа довольно типична для объектно-ориентированных систем: она короткая (потому что реальная работа поручена основным объектам, входящим в систему) и содержит цикл диспетчеризации (в данном случае тело цикла оставлено пустым, поскольку в системе нет никаких фоновых процессов)8. Продолжим изучение архитектуры системы и определим интерфейс класса Sensors (рис. 11.17). Предположим пока, что существует несколько классов, описывающих работу датчиков. По существу, этот класс представляет собой коллекцию и поэтому он объявляется подклассом фундаментального класса Collection (Коллекция)9. Класс 8Эта программа демонстрирует еще один популярный архитектурный шаблон: циклы диспетчеризации перехватывают внешние или внутренние события, а затем передают их для обработки соответствующим агентам. 9Класс Collection является абстрактным суперклассом, обеспечивающим общие операции для сбора элементов, включенных в библиотеки языка программирования.
Глава 11. Сбор данных: метеорологическая станция 515 Θ Collection О Sensors ^~addSensor~( SensorName : SehsoTjcHTnteger - оГ)' • numberOfSensors (): Integer • numberOfSensors (SensorName ): Integer • sensor (SensorName, id : Integer - 0 ): Sensor • currentValue () Q Sensor l*~cufr9ntVakk ( ) • Sensor () • rawVahe ( ) • name () • id() Рис. 11.17. Интерфейс класса Sensors Collection описан как суперкласс, поскольку нужно было скрыть детали его структуры от клиентов класса Sensor. Набор операций в классе Sensors невелик, поскольку датчики могут лишь добавляться в коллекцию, но не удаляться из нее. Таким образом, мы разработали обобщенный класс, описывающий коллекцию датчиков и способный манипулировать многочисленными экземплярами датчиков определенного типа, причем каждый экземпляр конкретного класса имеет уникальный идентификационный номер, отсчитывая от нуля. В классе Sampler определена ассоциация с классами Sensors и Display- Manager (рис. 11.18). Θ Sampler π sensors : Sensors о display : Display Manager • setSampilngRate (Tick, SensorName ) • sample (Tick ) • samplingRate (): Tick Ι ι "^ ^«enumeration» Ί :z& SensorName о Direction о Speed о WindChill о Temperature о DewPoInt о Humidity j о Pressure 4 J Θ Sensors ~ i • addSensor (SensorName : Sensor, • numberOfSensors (): Integer • numberOfSensors (SensorName ) • sensor (SensorName, id : Integer | · currentValue () id: Integer - : Integer - 0 ): Sensor 0)| © Display Manager • displayTfioat, SensorName Jd: integer "■ 0 ) Рис. 11.18. Схема класса Sampler Конструктор объекта Sampler устанавливает связь этого агента с конкретной коллекцией датчиков и заданным экземпляром менеджера дисплея, используемого в системе.
516 Часть III. Приложения Опишем основную операцию класса Sampler. void Sampler::sample(Tick t) { for (SensorName name = Direction; name <= Pressure; name++) for (unsigned int id = 0; id < repSensors.numberOfSensors(name); id++) if (!(t % samplingRate(name))) repDisplayManager.display(repSensors.sensor(name, id).currentValue(), name, id); } Эта функция-член перебирает типы датчиков и каждый датчик конкретного типа в коллекции. Для каждого датчика она проверяет, не наступил ли момент для считывания информации, и в случае положительного ответа определяет ссылку на датчик в коллекции, считывает его текущие показания и передает их менеджеру дисплея, ассоциированному с данным экземпляром класса Sampler10. Семантика этой операции основывается на полиморфном поведении метода currentValue (), определенного в базовом классе Sensor. Эта операция также основывается на функции display из класса DisplayManager. Теперь, уточнив этот элемент нашей архитектуры, мы можем представить новую диаграмму классов, отражающую модель временных рамок (рис. 11.19). Оценив архитектуру системы с помощью анализа нескольких сценариев, можно продолжить поступательный процесс разработки функциональных частей системы. Планирование выпусков Рассмотрим последовательность выпусков, каждый из которых основан на предыдущем. • Разработка версии программы, обладающей минимальными функциональными свойствами и осуществляющей мониторинг только одного датчика. • Разработка иерархии датчиков. • Разработка классов, ответственных за управление дисплеем. 10В качестве альтернативы можно было бы в каждом датчике предусмотреть функцию-член, возвращающую скорость опроса, и другую функцию-член, выводящую показания на жидкокристаллический дисплей. Эта схема позволила бы упростить класс Sampler, одновременно усложнив классы датчиков.
Глава 11. Сбор данных: метеорологическая станция 517 Рис. 11.19. Механизм временных рамок • Разработка классов, управляющих пользовательским интерфейсом. Порядок версий может быть произвольным, но мы выбрали только одну последовательность, в которой риск постепенно снижается от максимального до минимального. Это позволяет в первую очередь решать сложные задачи. Разработка версии программы с минимальными функциональными возможностями вынуждает нас сделать вертикальный разрез архитектуры и частично реализовать все основные абстракции. Эта задача связана с наиболее крупным риском, поскольку она сводится к выбору правильных абстракций, а также их свойств и обязанностей. Кроме того, решая эту задачу, мы уже на ранних этапах включаем обратную связь, взаимодействуя с работающей системой. Ранняя разработка системы дает множество технических и социальных преимуществ. С технической точки зрения, это позволяет заранее согласовать аппаратную и программную части. С социальной точки зрения, обратная связь с реальными пользователями позволяет оценить внешний вид и работу системы. Реализация первой версии по существу представляет собой тактическую задачу, поэтому она не представляет особого интереса. Исходя из этого, мы перейдем к изучению элементов последующих выпусков, что позволит выявить интересные особенности процесса разработки. Механизм датчиков В процессе разработки архитектуры системы можно проследить, как постепенно и поступательно развивается абстракция классов датчиков. Эволюционный
518 Часть III. Приложения подход предполагает, что разработка системы начинается с минимальной версии и завершается подробной иерархией классов. На данном этапе разработки иерархия классов, представленная на рис. 11.4, остается устойчивой, хотя придется уточнить место некоторых полиморфных операций, чтобы обеспечить максимальную общность иерархии. В частности, ранее мы сформулировали требования, предъявляемые к операции currentValue (Текущее значение), объявленной в абстрактном базовом классе Sensor. Структура этого класса представлена на рис. 11.20. | Q Sensor | · Sensor (SensorName, id • rawVabef ) ί · name (): SensorName 1 ♦ id (): Integer Рис. 11.20. Механизм временных рамок Обратите внимание на то, что конструктор класса присваивает экземпляру его имя и идентификационный номер. По существу, эта процедура представляет собой разновидность динамической идентификации типов динамического определения типа. Кроме того, это необходимо, поскольку одно из требований к системе указывает, что каждый из датчиков должен иметь конкретный интерфейс. Эти секреты можно скрыть, установив зависимость интерфейса от имени и идентификационного номера датчика. Добавив новое свойство, можно вернуться немного назад и упростить сигнатуру функции DisplayManager: : display так, чтобы она имела только один аргумент, а именно ссылку на объект класса Sensor. Остальные аргументы можно игнорировать, поскольку объект класса Display Manager может запросить свое имя и идентификационный номер у класса Sensor. Это усовершенствование желательно, поскольку позволяет упростить межклассовые интерфейсы. Действительно, если не пытаться их минимизировать, то по мере накопления изменений архитектура начнет ухудшаться. Объявление промежуточного подкласса Calibrating Sensor (Датчик с калибровкой) основано на базовом классе Sensor (рис. 11.21). В класс Calibrating Sensor включены две операции (setHighValue и setLowValue) и реализована ранее определенная функция currentValue. Теперь рассмотрим объявление подкласса HistoricalSensor (Датчик с историей), базирующегося на классе CalibratingSensor (рис. 11.22). В классе Historical Sensor определены четыре новые операции, для реализации которых необходимо взаимодействие с классом Time Date (Время и дата). Подчеркнем, что класс HistoricalSensor остается абстрактным, по- : Integer - 0 )
Глава 11. Сбор данных: метеорологическая станция 519 © Calibrating Sensor *~currentVabe ( } # setHighValue (float, float) # setLowValue (float, float) # CalibratingSensor (SensorName, id : Integer = 0 ) # rawVabe ( ) © Sensor ё currehWabe(j\ • Sensor () \ mrawVabef) \ • name () j • id () Рис. 11.21. Структура класса Calibrating Sensor © Mstoricaf Sensor • highVafueO • lowValue () • timeOfHighValue () • timeOfLowValue () • HistoricalSensor (SensorName, id : Integer - 0 ) | © Cafibrating Sensor j •"ЯЬгаОпЙегеогТУ —-θ| · currentVabe ( ) | · setHighValue () \ · setLowValue () ! « rawVabeO Рис. 11.22. Структура класса Historical Sensor скольку мы еще не завершили определение абстрактной функции rawValue, отнесенное к ответственности конкретного подкласса. Класс TrendSensor (Сенсор с трендом) является производным от Historical Sensor (рис. 11.23). О Trend Sensor • trend () • TrendSensor (id : Integer - 0 ) 0 Historical Sensor m highValue () • lowValue () • timeOfHighValue () • timeOfLowValue () • HistoricalSensor () Рис. 11.23. Структура класса Trend Sensor В класс Trend Sensor включена новая функция. Как и некоторые другие операции, добавляемые в промежуточные классы, функция trend объявлена конкретной, поскольку не требуется, чтобы подклассы изменяли ее поведение. В заключение, перейдем к конкретным подклассам, таким как Temperature Sensor (рис. 11.24). Сигнатура конструктора этого класса немного отличается от конструктора суперкласса — на этом уровне абстракции известно конкретное имя класса. Кроме того, в класс включена новая операция currentTemperature (Текущая температура). С семантической точки зрения эта операция совпадает с полиморфной функцией currentValue, но мы включили в описание обе функции, поскольку операция currentTemperature чуть более безопасна с точки зрения типов.
520 Часть III. Приложения G temperature Sensor • sample () • TemperatureSensor (id : Integer - 0 ) • rawValue () • currentTemperature () „f ь Рис. 11.24. Структура класса Temperature Sensor Успешно завершив реализацию всех классов этой иерархии и согласовав ее с предыдущей версией, можно переходить к следующему уровню функциональных свойств системы. Механизм работы дисплея Реализация следующей версии, завершающей разработку функциональных свойств классов DisplayManager и LCD Device, не требует принятия новых проектных решений. Достаточно принять несколько тактических решений, касающихся сигнатуры и семантики определенных функций. Сочетание решений, принятых в процессе анализа, с первым архитектурным прототипом, в котором реализованы важные решения, относящиеся к протоколу отображения показаний датчиков, позволяет определить интерфейс, показанный на рис. 11.25. ©Display Manager • display (sensor: Sensor) # dear () # refresh () # drawStatlcItems (speedScale : SpeedScale, tempScale ; TemperatureScale ) • displayTlme (time : String ) # displayDate (date : String ) • dlsplayTemperature (float, id : Integer - 0 ) • dlsplayHumidity (float, Id : Integer - 0 ) • dlsplayPressure (float, id : Integer - 0 ) • displayWIndChill (float, id : Integer - 0 ) • displayDewPdnt (float, id : Integer - 0 ) • dlsplayWindSpeed (float, id : Integer - 0 ) • displayWindDlrectlon (direction : Integer, id : Integer - 0 ) • dlsplayHighLow (float, value, sensorName : SensorName, id • setTemperatureScale (tempScale : TemperatureScale ) • setSpeedScale (speedScale : SpeedScale ) Integer · -0) ! Рис. 11.25. Структура класса Display Manager Ни одна из указанных операций не является виртуальной, поскольку вывод подклассов этого класса не предусмотрен. Обратите внимание на то, что этот класс экспортирует несколько простых операций (таких как displayTime и refresh), а также сложную операцию display, присутствие которой сильно упрощает взаимодействие клиентов с экземпляром класса Display Manager. Φ Trend Sensor ~1 trend () • TrendSensor ()
Глава 11. Сбор данных: метеорологическая станция 521 Класс Display Manager в конечном итоге использует ресурсы класса LCD Device, который, как указывалось ранее, служит программной оболочкой аппаратного обеспечения. Тем самым класс DisplayManager поднимает уровень абстракции, обеспечивая протокол, несущий информацию о природе предметной области. Механизм пользовательского интерфейса Последняя версия реализует тактические решения, касающиеся классов Keypad (Клавиатура) и InputManager (Диспетчер ввода). Подобно классу LCD Device, класс Keypad служит программной оболочной аппаратного оборудования, освобождающей класс InputManager от детальной информации об аппаратном обеспечении. Разделение этих двух абстракций сильно облегчает процесс замены физических устройств ввода без нарушения архитектуры системы. Начнем с определения названий физических объектов из проблемной области. Определение класса Key (Клавиша) приведено на рис. 11.26. ( «enumeration» 1 I IB Kef I мГШйп Ί о kSelect i о kCalibrate j о kMode J о kUp о kLeft I o kDown j о kRight о kTemperature о kPressure о kHumidity о kWind j о kTlme о kDate L? kUnassigned j Рис. 11.26. Структура класса Key Для того чтобы избежать совпадения с именами, определенными в классе SensorName, мы использовали префикс к. Теперь обратимся κ абстракции класса Keypad, показанной на рис. 11.27. Протокол этого класса является результатом предыдущего процесса анализа. Мы добавили операцию inputPending, чтобы клиент мог узнать, вводил ли пользователь информацию или нет. Класс InputManager имеет похожий интерфейс (рис. 11.28). Наиболее существенные функциональные свойства этого класса реализуются его конечным автоматом. Как показано на рис. 11.14, обработка ввода обеспечивается взаимодействующими экземплярами классов Sampler, InputManager и Keypad. Для интегра-
522 Часть III. Приложения Θ Keypad • inputPending (): Integer • lastKeyPress (): Key «enumeration» SKey ~o kRUn о kSelect о kCalibrate о kMode о kUp о kLeft о kDown о kRIght о kTemperature о kPressure о kHumldlty о kWind о kTime о kDate о kUnasslgned Рис. 11.27. Структура класса Keypad Г 0 InputManager <> repKeypad^Keypac[ • processkeyPress () Рис. 11.28. Структура интерфейса класса Inputmanager ции этих трех абстракций необходимо немного изменить интерфейс класса Sampler, включив в его описание новый объект repInputManager (рис. 11.29). Θ Sampler | V sensors Τ Sensors' | ° display : Display Manager о repSensors: Sensors о repDisplayManager: Display Manager о fepJ^pu^Manag^iJn^u^Manag^ J • setSampfngRate (Tick, SensorName ) ~ ~ ~" ] • sample (Tick ) • sampler (sensors, display ): Sampler • Sampler ( : InputManager, : Display Manager, : Sensors) j • samplingRate (): Tick | Рис. 11.29. Структура интерфейса класса InputManager Реализуя данное проектное решение, мы устанавливаем связь между экземплярами классов Sensors, DisplayManager и InputManager в момент конструирования объекта класса Sampler. Это решение предполагает, что каждый экземпляр Sampler должен иметь коллекцию датчиков, менеджер экрана и диспетчер ввода. Реализацию функции Sampler: : sample следует уточнить следующим образом.
Глава 11. Сбор данных: метеорологическая станция 523 void Sampler::sample(Tick t) { repInputManager.processKeyPress(); for (SensorName name = Direction; name <= Pressure; name++) for (unsigned int id = 0; id < repSensors.numberOfSensors(name); id++) if (!(t % samplingRate(name))) repDisplayManager.display(repSensors.sensor (name, id)); } В начале каждого временного интервала (кадра) мы добавили вызов метода processKeyPress (Обработать нажатие клавиши). Операция processKeyPress является точкой входа в конечный автомат, управляющий работой экземпляров данного класса. Существует два подхода к реализации любого конечного автомата: можно явно представить состояния в виде объектов (положившись на их полиморфное поведение) или просто перечислить состояния, обозначив их литералами. Для конечных автоматов с умеренным количеством состояний, таких как класс InputManager, можно ограничиться вторым подходом. Сначала определим имена объемлющих состояний класса (рис. 11.30). ! «enumeration» I ! :И InputState ί о Running j ο Selecting j о Calibrating | о Mode Рис. 11.30. Структура класса InputState Затем определим защищенные вспомогательные функции класса (рис. 11.30). «enumeration» :Ξ InputState о Running о Selecting о Calibrating о Mode 0 InputManager ~о~ герКедаН1 Keypad о repState : InputState • processKeyPress () • enterSelecting () • enterCalibratlng () • enterMode () Рис. 11.31. Класс InputManager и структура класса InputState В заключение, начнем реализацию переходов между состояниями, указанными на рис. 11.12.
524 Часть III. Приложения void InputManager::process Keypress() { if (repKeypad.inputPending()) { Key key = repKeypad.lastKeyPress(); switch (repState) { case Running: if (key == kSelect) enterSelecting(); else if (key == kCalibrate) enterCalibrating(); else if (key == kMode) enterMode(); break; case Selecting: break; break; case Calibrating; break; case Mode: break; } } } Таким образом, реализация этой функции и связанных с ней вспомогательных функций отражает содержание диаграммы переходов, изображенной на рис. 11.12. 11.4 Эксплуатация Полная реализация системы мониторинга погодных условий не слишком велика — примерно 20 классов. Однако любой работающий фрагмент программного обеспечения в дальнейшем обязательно подвергнется изменениям. Попробуем определить, к каким последствиям приведет необходимость сделать два усовершенствования данной системы. На данный момент разработанная система позволяет измерять многие погодные показатели, однако вскоре может выясниться, что пользователь хочет измерять количество осадков. Какие изменения необходимо внести в систему? К счастью, наша архитектура не подвергнется радикальным изменениям. Достаточно просто дополнить ее новыми функциональными возможностями. Ос-
Глава 11. Сбор данных: метеорологическая станция 525 новываясь на архитектуре, представленной на рис. 11.14, необходимо сделать следующее. • Создать новый класс RainFall Sensor (Датчика уровня осадков); и включить его в соответствующее место в иерархии классов, описывающих работу датчиков (класс RainFal 1 Sensor является разновидностью класса Historical Sensor). • Обновить перечисление SensorName. • Модифицировать класс Display Manager, чтобы он мог выводить на экран показатели нового датчика. • Изменить класс InputManager, чтобы он мог реагировать на нажатие клавиши RainFall (Осадки). • Добавить экземпляры класса RainFallSensor в коллекцию Sensors. Для интеграции нового класса потребуется решить несколько тактических вопросов, но это ни при каких условиях не должно нарушить архитектуру и ее основные механизмы. Рассмотрим совершенно другой вид функциональных свойств. Предположим, что нужно обеспечить возможность пересылки собранных за день данных на удаленный компьютер. Для реализации этой задачи необходимо сделать следующее. • Создать новый класс SerialPort (Последовательный порт), ответственного за управление последовательным портом. • Разработать новый класс Report Manager, ответственный за сбор информации. Этот класс должен использовать возможности класса Sensors и ассоциированных с ним конкретных датчиков. • Изменить реализацию функции Sampler: : sample, чтобы она периодически опрашивала последовательный порт. Возможность добавлять новые функциональные возможности за счет повторного использования существующих механизмов без вмешательства в структуру системы является признаком хорошо продуманной объектно-ориентированной архитектуры.
ГЛАВА 12 WEB-ПРИЛОЖЕНИЕ: СИСТЕМА ПЛАНИРОВАНИЯ ОТПУСКОВ В настоящее время во многих компаниях усиливается автономность сотрудников. Все чаще они делят свое рабочее время между несколькими проектами и подчиняются сразу нескольким менеджерам одновременно. В результате неформальные отношения между менеджерами и подчиненными ослабевают. Менеджерам все труднее узнавать о планах сотрудников и управлять сроками и продолжительностью их отпусков. В описанном далее примере некая гипотетическая компания решила разработать и внедрить систему, которая позволила бы менеджерам гибко управлять отпусками, а их подчиненным оптимально планировать свое время. Решение крупной промышленной организации внедрить аналогичную систему не может приниматься без учета всех обстоятельств. Вряд ли предлагаемая система является первым приложением, создаваемым данной организацией. Такая система должна рассматриваться в контексте всех других существующих (и даже планируемых) систем. В итоге, многие архитектурные решения обусловлены заранее. Решение разработать Web-приложение, обладающее заданными функциональными возможностями, должно учитывать возможности расширения внутренней системы, существующей в организации, обеспечивая конечным пользователям наибольший комфорт. В последующих разделах описываются наиболее важные и интересные архитектурные аспекты этой системы. Учитывая ограниченный объем книги, мы сосредоточились лишь на самых необходимых аспектах, позволяющих понять сущность приложения. В реальности подробное и полное обсуждение такой системы потребовало бы намного больше моделей и примеров, а ее содержание было бы намного шире. В главе проиллюстрированы основные принципы объ-
Глава 12. Web-приложение: система планирования отпусков 527 ектной ориентации, влияющие на разработку описываемого Web-приложения, и обсуждаются некоторые уникальные аспекты, присущие этой системе. 12.1 Начало Требования к системе излагаются в документе, содержащем описание концепции, основных функциональных свойств, моделей использования, сценариев использования и архитектурных аспектов. Требования Концепцию проекта сформулировать довольно легко. Система планирования отпусков (Vacation Tracking System — VTS) даст сотрудникам возможность планировать свои годовые отпуска, брать больничные и отгулы, не нарушая правил, принятых в компании или офисе. Самая важная цель системы — дать сотрудникам возможность брать на себя ответственность за управление конкретными аспектами своего договора с компанией. Это обусловлено необходимостью рационализировать работу отдела кадров (Human Resources Department — HR), минимизировать деятельность менеджеров, не связанную с производством, и создать у сотрудников ощущение самостоятельности. Эти цели будут достигнуты, только если система будет легкой в использовании, интуитивно понятной и интеллектуальной. Таким образом, основная цель совершенно ясна. Система должна быть легкой в использовании. Читателя, когда-либо принимавшего участие в разработке коммерческого программного обеспечения, может испугать такая туманная формулировка. Такие тривиальные и субъективные требования нельзя вносить в документ, не так ли? Вовсе не обязательно. Несмотря на кажущуюся простоту, это требование выражает основное свойство системы. Это очень важно, поскольку игнорирование данного условия приведет к провалу проекта. Такие абстрактные и нечеткие свойства иногда должны перечисляться в официальных документах, не столько потому что их легко проконтролировать, сколько потому что на их основе можно сформулировать более конкретные и четкие требования. Например, рассмотрим требование, в соответствии с которым Web- приложение в конкретной точке должно предложить конечному пользователю ввести некоторый форматированный текст (например, текст, набранный полужирным шрифтом или курсивом, списки, абзацы и т.д.). Архитекторы могут принять два потенциально возможных решения. Они могут предложить конечному пользователю вставить в текст специальные фрагменты кода, как это принято во многих
528 Часть III. Приложения популярных электронных досках объявлений, или использовать встроенный или коммерческий апплет на языке Java, позволяющий осуществлять форматирование в режиме WYSIWYG. Несмотря на то что применение апплета связано с большими техническими сложностями и риском, его преимущества с точки зрения конечного пользователя очевидны. Если одна из основных целей системы — простота использования, то использование апплета становится вполне обоснованным решением. Однако если простота использования системы является желательным, но не критически важным свойством системы, то потенциальную техническую сложность и риск применения апплета оправдать не удастся. Основная цель описываемого приложения — улучшить внутренние бизнес- процессы или по крайней мере, ускорить процедуру планирования отпусков. В прошлом сроки всех отпусков должны были согласовываться с непосредственными начальниками, а затем сверяться в отделе кадров. Иногда эта процедура занимала несколько дней. Автоматизированная система может ускорить этот процесс и потребует не более одного согласования с непосредственным начальником (некоторые из высших административных работников вообще не обязаны согласовывать сроки своих отпусков с кем бы то ни было). Эта система поможет сэкономить время и деньги за счет оптимизации работы отдела кадров, поскольку длительная процедура согласования будет заменена автоматизированной системой, действующей по строгим правилам. Отдел кадров будет по-прежнему отвечать за ввод и изменение сроков отпуска в системе, однако теперь им не придется запрашивать и согласовывать каждый запрос. Система должна отличаться следующими основными свойствами. • Основываться на гибкой системе правил оценки и верификации запросов. • Предусматривать санкции менеджера (по возможности). • Обеспечивать доступ к запросам, поступившим накануне, и позволять вводить запросы на год и полгода вперед. • Использовать электронную почту для уведомления о решении менеджера и изменениях статуса запроса, поданного сотрудником. • Использовать существующее аппаратное оборудование и промежуточное программное обеспечение. • Расширять возможности внутренней сети и использовать механизмы портала для аутентификации пользователей. • Хранить активные данные о регистрации для всех транзакций. • Позволять сотрудникам отдела кадров и системным администраторам отменять все действия, нарушающие правила, регистрируя причины отказа. • Позволять менеджерам непосредственно задавать дополнительные дни отдыха для персонала (в пределах лимитов, оговоренных в системе).
Глава 12. Web-приложение: система планирования отпусков 529 • Обеспечить средства Web-интерфейса для других внутренних систем, запрашивающих суммарную информацию о запросах. • Обеспечить интерфейс с юридическими системами отдела кадров, чтобы получать информацию о сотрудниках и изменениях в их статусе. Модель использования Наиболее абстрактная модель использования системы состоит из четырех действующих лиц и восьми сценариев использования, показанных на рис. 12.1. Степень детальности этих сценариев выбрана разумно низкой. Например, сценарий использования Manage Time (Управление сроками) описывает функциональные возможности, необходимые действующему лицу Employee (Сотрудник). К ним относятся просмотр, создание и отмена запроса на отпуск. Сценарий использования — это не просто описание функциональных возможностей. Он описывает нечто, имеющее ценность для действующего лица, в форме сценария. Например, сама по себе возможность просмотра запроса на отпуск имеет наименьшую важность для пользователя, но возможность самостоятельно планировать сроки своего отпуска несомненно имеет большое значение. Рис. 12.1. Абстрактная модель использования Интересным свойством сценариев использования Web-систем является возможность их реализации исключительно на основе запросов и ответов. Иначе
530 Часть III. Приложения говоря, сценарий использования таких систем обычно представляет собой список действий действующих лиц и немедленных реакций системы. Кроме того, эти системы, как правило, тесно связаны с реальными Web-страницами или сайтами. Это отличает их от других приложений, в которых содержание сценария больше сконцентрировано на информации и действиях пользователя, а не на идентификации дискретных единиц пользовательского интерфейса, таких как Web-страницы и сайты. Описываемая система состоит из следующих действующих лиц. • Employee (Сотрудник). Основной пользователь системы. Сотрудник использует систему для управления сроками своего отпуска. • Manager (Менеджер). Сотрудник, возможности и цели которого не отличаются от целей и возможностей обычных сотрудников, но дополнительно несущий ответственность за одобрение запросов на отпуск, поступающих от подчиненных. Менеджер может одобрить запрос, руководствуясь правилами, принятыми в системе. • Clerk (Клерк). Сотрудник отдела кадров, имеющий право просматривать личное дело остальных сотрудников и обязанный обновлять и корректировать записи. Клерк может добавлять и удалять практически любую запись в системе. На самом деле клерки отделов кадров могут и не быть сотрудниками компании. Однако если они являются сотрудниками компании, то могут использовать два разных идентификационных номера для входа в систему, играя две разные роли. Перечислим основные сценарии использования. • Manage Time (Управление сроками). Описывает, как сотрудник запрашивает и просматривает запросы на отпуск. • Approve Request (Одобрение запроса). Описывает, как менеджер реагирует на запрос, поступивший от подчиненного. • Award Time (Дополнительные дни отпуска). Описывает, как менеджер может выделить сотруднику дополнительные дни отпуска (компенсируемое время). • Edit Employee Record (Редактирование записи о сотруднике). Описывает, каким образом клерк редактирует запись о сотруднике, существующую в системе. Включает в себя процедуры оформления отгулов и максимальное компенсируемое время, назначенное менеджером. • Manage Locations (Управление размещением записей). Описывает, каким образом клерк управляет размещением записей и правилами. • Manage Leave Categories (Управление отпусками). Описывает, как и по каким правилам клерк оформляет отпуска.
Глава 12. Web-приложение: система планирования отпусков 531 • Override Leave Records (Аннулирование запросов). Описывает процедуру отказа по правилам системы. • Back Up System Log (Резервное копирование системной информации). Описывает, как системный администратор копирует регистрационные записи. 12.2 Разработка Иногда неясно, когда начинается анализ или заканчивается сбор требований, происходящий на начальном этапе. Именно поэтому итеративная процедура разработки настолько популярна, а практичность разработки по методу "водопада" подвергается сомнению. В любом случае сначала необходимо сформулировать наиболее важные сценарии использования системы, влияющие на ее архитектуру. Подробной детализации сценариев на этом этапе не требуется, но важные архитектурные аспекты следует уточнить. В идеале анализ системы не должен зависеть от архитектуры. Однако априорное знание особенностей архитектуры может повлиять на ход анализа. Это особенно верно для Web-приложений, поскольку некоторые аспекты Web- архитектуры известны уже на начальном этапе. В нашем случае решение реализовать систему в виде Web-страницы было принято уже в начале проекта. Например, предложение в основном потоке сценария Manage Time — "Сотрудник должен иметь доступ к визуальному календарю, чтобы иметь возможность выбирать и сравнивать данные" — обусловлено априорным знанием о том, что большинство Web-браузеров не имеют готовых элементов для управления датами или календарем. В спецификации Windows-приложения это требование было бы излишним, поскольку в операционной системе Windows уже есть такие средства. Таким образом, указанное требование явно учитывает возможности Web-браузеров, чтобы обеспечить удобство пользователей. Более тонким свидетельством того, что автор сценария использования уже знал особенности архитектуры, является постоянная ссылка на "навигацию по Web-страницам" и "представление" информации, поскольку эти понятия тесно связаны с Web-архитектурой. К сожалению, не существует общепризнанной точки зрения на способы представления произвольной архитектуры. В данном случае мы использовали архитектурную модель 4+1 [3], описанную в главе 6. Ниже приведено краткое описание архитектуры Web-приложения, которое нельзя считать исчерпывающей дискуссией. Однако мы рассмотрели достаточно важные аспекты, чтобы обосновать главные решения, которые будут приняты позже.
532 Часть III. Приложения Представление развертывания Web-приложение является разновидностью приложений клиент/сервер. Следовательно, оно содержит, как минимум, два узла — сервер и браузер клиента. Сервер — это узел, имеющий известный адрес в сети и опрашивающий конкретный порт, как правило, порт 80, в ожидании запросов по протоколу HTTP. Браузер клиента делает запрос на ресурсы сервера, сформатированные в соответствии с протоколом HTTP. Чаще всего сервер одновременно предоставляет большое количество услуг, выполняя другие Web-приложения и служа сервером базы данных, приложений и т.д. Узлы Client (Клиент) и Server (Сервер) продемонстрированы на рис. 12.2. ЦЖ,^^ Deploy ,'i Firefcx.exe / г Ш Server Farm Deploy Nested Nodes ■ Tomcat , , , ,, , , .., „ \d «deployment» «artifact» 3Firefox.exe JvfsWeb.war K~«^oyment»- I Tomcat Deploy ,'iVTSWeb.war «artifact» t- _, , _. |3|VTS.sql [^"""^oepioyment^- I Database 1 Servers Deploy ,£VTS.sql Рис. 12.2. Диаграмма развертывания компонентов Web-системы На диаграмме развертывания основные компоненты среды выполнения программ Tomcat и Cloudscape показаны в виде вложенных узлов сервера. Узел Tomcat — это среда выполнения Web-приложения, основанная на языке Java. Узел Tomcat содержит артефакт VTSWeb.war — архивный файл Web-приложения. Среда выполнения программ Cloudscape — это сервер базы данных, способный выполнять файлы SQL и содержащий артефакт VTS. sql.
Глава 12. Web-приложение: система планирования отпусков 533 Узел Client, показанный на рис. 12.2, содержит артефакт Firefox.exe, представляющий собой исполняемое приложение HTML-браузера. Узлы Client и Server соединены каналом связи, который может быть любым — от телефонной линии до широкополосного или радиоканала. Следует подчеркнуть, что с помощью этого канала связи клиент также взаимодействует с вложенными Web- серверами базы данных. Это упрощенное представление Web-системы. В более крупных системах диаграммы развертывания, демонстрирующие топологию всех узлов, компонентов, серверов и каналов связи, могут быть намного сложнее и требовать использования современных систем визуализации и документации, таких как язык UML. На рис. 12.3 продемонстрирована абстрактная диаграмма развертывания, показывающая, как можно использовать интеллектуальный маршрутизатор и группу серверов, а также как можно выполнить весь набор программ, поступающих с сервера приложений. Детали таких стратегий могут оказаться довольно сложными, но общая стратегия масштабирования приложений с помощью дополнительных узлов обработки Web-приложений оказалась вполне жизнеспособной. Рис. 12.3. Диаграмма развертывания группы серверов с параллельными и резервными узлами обработки Логическое представление Обычное Web-приложение содержит, как минимум, четыре логических компонента: браузер, запускаемый клиентом, Web-контейнер или контейнер, отдельный компонент для логики приложения и компонент сервера базы данных. На рис. 12.4 показан компонент Firef ох. ехе, представляющий собой популярный многоплатформный браузер, а также компонент Tomcat — распространенный Web-контейнер, основанный на спецификации Java Server Pages (JSP). Компонент VTSWeb является бизнес-приложением, а компонент Cloudscape — простым мобильным сервером базы данных. Наиболее важная логическая особенность этой диаграммы заключается в том, что браузер клиента никогда не вступает в непосредственный контакт с базой данных и даже компонентов бизнес-приложения. Доступ к ресурсам сервера управляется Web-контейнером. Благодаря этому он имеет особую важность и должен быть очень надежным.
534 Часть III. Приложения «component» €1 tomcat ■■'·"""■ »т ■■.« « » i I «ijjse» , V [ «component» J £]VTSWeb «use» % JJ4 «component» | «Ocloudscape Рис. 12.4. Логическое представление основных компонентов Web- приложения Web-серверы опрашивают определенные порты, — как правило, порт 80, — и ждут поступления запросов GET и POST. Эти запросы являются командами, определенными протоколом HTTP. Они обеспечивают два простых способа получения информации от Web-сервера. Метод POST обладает чуть более широкими возможностями и чаще используется, когда данные или файлы посылаются пользователем на сервер. Выбор команд для выполнения определяется содержанием HTML-страницы, отображаемой браузером в данный момент. Как правило, информация, возвращаемая браузером, представляет собой документ, отформатированный по правилам языка HTML и изображаемый браузером на экране. Однако сервер может вернуть данные в любом виде, оставляя за клиентом право сохранять их или передавать на обработку другому инсталлированному приложению. На рис. 12.5 показаны логические классы, представляющие элементы, связывающие клиента и сервер между собой. Со стороны клиента браузер обязан запрашивать Web-страницы (точнее говоря, ресурсы) с помощью простых команд GET или POST. Эти услуги могут быть либо предоставлены операционной системой, либо выполняться самим браузером (в этом случае браузер вызывает программный интерфейс низкоуровневых приложений сети). Web-контейнер постоянно опрашивает определенные порты (например, порт 80), ожидая поступления HTTP-запросов, которые упаковываются и отсылаются браузером. Контейнер содержит идентификатор ресурса, указывающий на конкретную Web-страницу или ссылку на Web-приложение. Запрос можно сопровождать парами ключевых значений (параметров), представленных в виде строк1. Некоторые запросы по протоколу HTTP упаковываются в более сложном виде, который определяется пользователем непосредственно перед открытием страницы. Когда Web-контейнер получает запрос на ресурс, он должен сначала определить, какой файл или приложение вызывается. Контейнер вызывает соответствующий ресурс. Если указано, что файл или приложение являются динамическими подробности форматирования и передачи параметров можно найти на Web-сайте World Wider Web Consortium www. w3. org. Большинство этих деталей автоматически определяется средой выполнения Web-приложений. «component» OHrefbx.exe
Глава 12. Web-приложение: система планирования отпусков 535 Рис. 12.5. Абстрактное логическое представление объектов, из которых состоит Web-приложение и подлежат обработке, Web-контейнер выполняет его. В ходе обработки информация, содержащаяся в HTTP-запросе (параметры и форма данных) проверяется, а затем приложение реализует необходимую бизнес-логику. Часто эта логика выполняется на отдельном сервере приложений (например, EJB-контейнере), имеющем доступ к другим серверам баз данных. С логической точки зрения, Web-приложение состоит из Web-страниц, контроллеров и сущностей (три основных стереотипа, содержащихся в аналитических моделях). Статичные Web-страницы (не предусматривающие обработки) могут храниться в файловой системе, а Web-страницы, выполняющие бизнес-функции, должны выполняться и загружаться в контексте контейнера. Контроллеры часто встроены в компоненты, а персистентные сущности управляются базами данных. Представление процессов С обычным Web-приложением связаны, как минимум, два процесса (обычно их бывает больше). Клиент и сервер функционируют асинхронно, за исключением обработки запросов в рамках протокола HTTP. Часто в Web-приложения входят дополнительные базы данных, а также серверы аутентификации и обработки сообщений. Они могут сосуществовать в одном узле сервера или быть распределенными по нескольким узлам. Схема процессов в Web-приложении обладает
536 Часть III. Приложения гибкостью, присущей любой клиент-серверной архитектуре. От нее требуется лишь, чтобы узлы клиента запускали определенную программу, инициализирующую приложение на стороне сервера. Как уже указывалось, для того чтобы понять архитектуру Web-приложений, следует помнить, что они выполняются автономно. Иначе говоря, клиент и сервер никогда не поддерживают контакт дольше, чем это требуется для обработки команд GET и POST. Как только сервер получает от браузера запрос на ресурс (например, на Web-страницу, сформатированную на языке HTML) и выполняет его, соединение между сервером и клиентом разрывается. На рис. 12.6 показан клиент, посылающий простой запрос GET на сервер Tomcat. Этот сервер определяет, какое Web-приложение и ресурс необходимо вызвать. При этом инициализируется или вызывается Web-страница, находящаяся внутри приложения. Именно это событие является ключевым в процессе обработки команд GET и POST. Когда процесс завершается, приложение открывает страницу ответа (т.е. следующей Web- страницы в сценарии). Важно помнить, что как только запрос на выделение Web- ресурсов будет выполнен, приложение прекратит работу с конкретным клиентом. 1:GET К- 1.1: doGet ь Jf 1.1.1: invoke application logic Z-3 j~ | 1.1.3: prepare response page Рис. 12.6. Типичная диаграмма последовательностей при обработке запроса Get Сложность заключается в том, что не всегда очевидно, каким образом серверное приложение может отслеживать историю клиентских запросов и контролировать внутреннее состояние клиента. Например, без использования некоторых свойств протокола HTTP или реализации определенных архитектурных механизмов серверному приложению было бы трудно управлять даже простой карточкой заказа или следить за перемещениями клиента по страницам многостраничного мастера приложений. К счастью, среда большинства Web-приложений предо-
Глава 12. Web-приложение: система планирования отпусков 537 Управление состоянием клиента Управление состоянием клиента представляет собой одну из наиболее интересных проблем, связанных с Web-приложениями. Поскольку каждый запрос и ответ, пересылаемые между клиентом и сервером, выполняются в рамках новых и уникальных сеансов связи, серверу трудно отслеживать последовательность запросов, поступающих от конкретного клиента. Управление состоянием имеет большую важность для многих приложений, поскольку отдельные сценарии использования системы часто предусматривают навигацию по многочисленным Web-страницам. Если бы не было механизма управления состоянием, то пришлось бы постоянно пересылать всю информацию, собранную ранее при перемещении, по предыдущим Web-страницам. Даже в простейших приложениях этот процесс довольно утомителен. Представьте себе, что каждый раз при переходе на новую страницу Интернет-магазина вам придется заново заполнять форму заказа или вводить имя и пароль при новой проверке электронного почтового ящика. Наиболее популярным решением этой проблемы является механизм управления состоянием, основанный на протоколе HTTP (HTTP State Management Mechanism), предложенный консорциумом W3C (World Wide Web Consotrium). Этот механизм использует маркёры (cookies). Маркёр — это фрагмент данных, который Webserver может попросить Web-браузер временно сохранить у себя и возвращать каждый раз, когда браузер будет делать следующие запросы на HTTP-ресурсы у данного сервера. Как правило, размер этих данных невелик и колеблется от 100 до 1000 байтов. Среды Web-приложений управляют состоянием клиента, генерируя уникальный идентификатор каждый раз, когда клиент впервые вступает во взаимодействие с приложением, и размещая этот идентификатор в качестве маркёра. Этот идентификатор используется в качестве ключа для соединения с сервером, содержащим всю информацию о конкретном клиенте. Альтернативный подход основан на перенаправлении унифицированного указателя информационного ресурса (URL — Uniform Resource Locator). В рамках этого подхода каждая гиперссылка и форма размещают идентификатор в конце унифицированного указателя, посланного на сервер при переходе на следующую страницу. В этом случае идентификатор играет роль маркёра и браузер, которому запрещено хранить маркёры, может использовать его в качестве параметра унифицированного указателя. Недостатком этого подхода является требование, чтобы каждая страница на Web-сайте была динамической, т.е. пользователь не может выйти из приложения посреди сценария использования, не прекратив очередной сеанс связи между клиентом и сервером. Два других подхода к управлению состоянием клиента сводятся к разделению параметров унифицированного указателя на последовательности или на маркёры. По ряду причин они не получили широкого распространения. В частности, они менее безопасны, поскольку сервер возвращает состояние клиента браузеру, в то время как другие методы предусматривают, что сервер автономно управляет состоянием. Кроме того, когда все параметры состояния хранятся в маркёрах, они
538 Часть III. Приложения занимают лишь 4К, а количество маркёров не превышает 20 на один домен. Все данные о состоянии должны быть закодированы в виде простого текста (без пробелов, точек с запятыми и т.д.). Это означает, что состояние клиента в рамках определенного сеанса сложно зафиксировать с помощью высокоуровневых объектов. ставляет в распоряжение пользователя много полезных утилит и механизмов для управления состоянием клиента. Второй недостаток этой архитектуры состоит в том, что сервер не знает, прекратил ли пользователь выполнение сценария использования системы, не завершив его до конца. Это напоминает ситуацию, когда дистанционный пользователь отключается от сети и не может завершить начатую транзакцию. В большинстве классических клиент-серверных приложений сервер может получать от клиента уведомления о преждевременном разрыве связи, но в Web-приложениях такие уведомления не предусмотрены. Следовательно, Web-приложения должны точно помнить, какие ресурсы были открыты и к каким ресурсам они получили доступ при переходе с одной Web- страницы на другую. Например, одно из основных правил разработки Web-приложений запрещает открывать транзакцию на одной странице и завершать ее на другой. Время между запросами на переход между Web-страницами обычно измеряется секундами, и в любой момент связь может оборваться. Большое количество транзакций и блокировок может в итоге привести к отказу приложения. Представление реализации На рис. 12.7 показана модель реализации системы планирования отпусков, а также уровни и пакеты системы. Как следует из этой диаграммы, основной Web-компонент связи VTSWeb.war содержит артефакты Web-страницы (JSP- и HTML-файлы), а также набор классов Java в пакетах web и sdo. Этот код используется для обработки и вызова EJB-функций на бизнес-уровне. Общим пространством имен для всех компонентов Java является пакет com. acme. vts, показанный на заднем плане. Подробное описание размещения компонентов на уровнях системы описывается представлением развертывания (Deployment View), а сущность и предназначение компонентов — ее логическим представлением (Logical View). Представление сценариев использования Представление развертывания, логическое представление, а также представления процессов и реализации системы объединяются вместе для реализации основных сценариев использования по принципу "запрос-ответ". Клиент посы-
Глава 12. Web-приложение: система планирования отпусков 539 63JSP «artrfact» ©HTML «component» CIVTSWeb.wa Sweb c=x ... j {ffpagecode •fj&ctmacme.vts hnpl ; фе*» *}. Рис. 12.7. Модель реализации лает серверу HTTP-запрос на открытие Web-страницы. Сервер проверяет запрос и определяет, какие ресурсы приложения необходимо загрузить и выполнить. Одни ресурсы выполняют бизнес-функции, а другие просто выводят на экран статические данные. После завершения обработки приложение формирует ответ, который обычно имеет вид Web-страницы, размеченной с помощью языка HTML и изображаемой вместо предыдущей Web-страницы. Эта страница содержит новую информацию и дает пользователю возможность послать новый запрос или вызвать новую функцию. Для того чтобы полностью выполнить бизнес-приложение, необходимо собрать вместе все Web-страницы, предназначенные для представления и получения информации. В этой главе основное внимание уделяется архитектурному аспекту сценария использования Manage Time (Управление временем). Этот сценарий наиболее часто выполняется действующими лицами системы. Следовательно, необходимо добиться эффективности выполнения этого сценария и гарантировать, что он соответствует всем поставленным целям, включая легкость использования. Существует множество шаблонов для создания спецификаций сценариев. Мы выбрали наиболее надежный из них. Он позволяет избежать стиля "запрос-ответ", характерного для Web-приложений. Кроме того, выбранный стиль хорошо подходит для ситуаций, когда в системе существуют сложные или постоянные альтернативные потоки управления. И наконец, этот стиль позволяет повысить уровень формализации сценария. Рассмотрим краткую спецификацию прецедента использования Manage Time. Название прецедента: Manage Time Действующее лицо: Employee
540 Часть III. Приложения Цель: сотрудник желает подать новый запрос на отпуск. Предусловия: посетитель аутентифицирован порталом и идентифицирован как сотрудник компании, имеющий право самостоятельно планировать свой отпуск. Основной поток: 1. Сотрудник начинает работу, выбирая гиперссылку внутрисетевого портала на систему VTS. 2. Система VTS использует мандат сотрудника для проверки текущего статуса всех его запросов и баланса рабочего времени. На экран выводится информация о запросах, поступивших в течение последних 6 месяцев, ^ и возможностях отпуска в течение следующих 18 месяцев. 3. Сотрудник хочет создать новый запрос. Сотрудник выбирает одну из категорий отпуска с положительным балансом. 4. Система VTS предлагает сотруднику ввести дату и продолжительность отпуска. Сотрудник должен иметь доступ к визуальному календарю, чтобы выбирать даты и сравнивать их между собой. 5. Сотрудник выбирает желательные даты и количество часов в расчете на один день отпуска (например, четыре часа означают, что сотрудник просит отгул на половину рабочего дня). Сотрудник вводит короткое название и описание запроса (не более одного абзаца), чтобы менеджер смог получить информацию, позволяющую одобрить запрос. После ввода всей информации сотрудник посылает запрос. 6. Если поданная информация является неполной или неправильной и не проходит процедуру верификации, то Web-страница открывается заново, а ошибки подсвечиваются и регистрируются. 7. Сотрудник имеет возможность изменять информацию или отзывать свой запрос. 8. Если информация является полной и проходит процедуру верификации, то сотрудник возвращается на главную страницу VTS. Если дата и продолжительность отпуска должны быть согласованы с менеджером, то система электронной почты немедленно отправит запрос менеджеру, ответственному за одобрение запросов на отпуск. 9. Запрос на отпуск переводится в состояние ожидания. 10. Менеджер отвечает системе электронной почты, щелкая на гиперссылке, встроенной в письмо, или явно регистрируясь на внутрисетевом портале и переходя на главную страницу системы VTS. 11. Система может потребовать у менеджера мандат на доступ.
Глава 12. Web-приложение: система планирования отпусков 541 12. На главной странице системы VTS перечисляются все запросы на отпуск и баланс рабочего времени сотрудников, входящие в компетенцию менеджера, а также запросы, ожидающие решения. Менеджер выбирает каждый из них по отдельности и либо одобряет, либо отклоняет запрос. 13. Система VTS выводит на экран время поступления запроса и предлагает менеджеру одобрить или отклонить запрос. Если запрос отклоняется, то менеджер должен указать причины. Как только менеджер введет свой ответ, внутреннее состояние запроса изменяется на "одобрен" или "отклонен". 14. Независимо от того, одобрен запрос или отклонен, сотруднику, пославшему запрос, немедленно отправляется электронное уведомление. Экран менеджера возвращается на главную страницу системы VTS, а сам менеджер может приступить к рассмотрению следующих запросов, послать собственный запрос или просто выйти из приложения. Альтернативный поток: Withdraw Request (Отзыв запроса). Цель: сотрудник желает отозвать еще не рассмотренный запрос на отпуск. Предусловия: сотрудник сделал запрос на отпуск, но он еще не рассмотрен менеджером. (См. также предусловия основного потока.) 1. Сотрудник переходит на главную страницу системы VTS через внутрисе- тевой портал, осуществляющий аутентификацию, идентификацию и проверку его привилегий. 2. Главная страница системы VTS содержит краткое описание запроса на отпуск, текущий баланс рабочего времени, а также текущий статус всех запросов на отпуск за период времени, начинающийся 6 месяцев назад и простирающийся на 18 месяцев вперед. 3. Сотрудник выбирает еще не рассмотренный запрос, который он желает отозвать. 4. Система VTS предлагает сотруднику подтвердить желание отозвать ранее посланный запрос. 5. Сотрудник подтверждает свое желание отозвать запрос, и запрос удаляется из списка запросов, ожидающих одобрения менеджера. 6. Система посылает уведомление менеджеру по электронной почте. 7. Система обновляет состояние запроса, переводя его в состояние "отозван". Альтернативный поток: Cancel Approved Request (Отмена одобренного запроса). Цель: сотрудник желает аннулировать уже одобренный запрос на отпуск.
542 Часть III. Приложения Предусловия: сотрудник сделал запрос на отпуск, менеджер одобрил его и внес в расписание будущих и прошлых отпусков (за предыдущие 5 рабочих дней). (См. также предусловия основного потока.) 1. Сотрудник переходит на главную страницу системы VTS через внутрисе- тевой портал, осуществляющий аутентификацию и идентификацию, проверяя его привилегии. 2. Главная страница системы VTS содержит краткое описание запроса на отпуск, текущий баланс рабочего времени, а также текущий статус всех запросов на отпуск за период времени, начинающийся/6 месяцев назад и простирающийся на 18 месяцев вперед. 3. Сотрудник выбирает рассмотренный запрос, который он желает аннулировать. 4. Если запрос относится к будущему времени, то сотруднику предлагается подтвердить его отмену. Если запрос относится к прошлому, то сотруднику предлагается подтвердить его отмену и дать краткое объяснение. Если сотрудник подтверждает желание аннулировать запрос и предоставляет требуемую информацию, то система электронной почты посылает менеджеру уведомление, а запрос переводится в состояние "аннулирован". Сотруднику возвращается информация о том, что его запас времени на отпуск восстановлен. Кроме того, сотрудник может прекратить выполнение процедуры аннулирования запроса, сохранив его предыдущее состояние. 5. Сотрудник возвращается на главную страницу системы VTS. Система обновляет краткое описание запроса, чтобы отразить все изменения его статуса. Альтернативный поток: Edit Pending Request (Редактирование запроса, ожидающего решения). Цель: сотрудник желает изменить еще не рассмотренный запрос на отпуск. Предусловия: сотрудник сделал запрос на отпуск, но менеджер еще не рассмотрел его. (См. также предусловия основного потока.) 1. Сотрудник переходит на главную страницу системы VTS через внутрисе- тевой портал, осуществляющий аутентификацию и идентификацию, проверяя его привилегии. 2. Главная страница системы VTS содержит краткое описание запроса на отпуск, текущий баланс рабочего времени, а также текущий статус всех запросов на отпуск за период времени, начинающийся 6 месяцев назад и простирающийся на 18 месяцев вперед. 3. Сотрудник выбирает еще не рассмотренный запрос, который он желает отредактировать.
Глава 12. Web-приложение: система планирования отпусков 543 4. Система VTS выводит на экран запрос, доступный для редактирования. Сотрудник может изменить его название, комментарии или даты. Кроме того, сотрудник может вообще отозвать запрос. 5. Сотрудник изменяет информацию о запросе и вводит новые данные в систему. 6. Если сотрудник отзывает запрос, система VTS предлагает ему подтвердить желание отменить запрос. Если изменения касаются лишь информации о запросе, они принимаются, а экран переходит на главную страницу системы VTS. Если в ходе изменения запроса возникают ошибки или проблемы, то система VTS обновляет страницу редактирования и выделяет ошибки, сопровождая их комментариями. Это описание сценария использования содержит довольно мало информации о системе VTS и способе ее использования. По существу, оно представляет собой функциональное описание системы с точки зрения действующего лица Employee. Действительно, сценарий был разработан именно с этой целью. К сожалению, это описание недостаточно для анализа. Необходимо дополнить его нефункциональными требованиями и привести намного больше информации из предметной области. К нефункциональным требованиям, как правило, относятся требования, касающиеся среды, производительности, масштабируемости, безопасности и т.д. Знания из предметной области могут формулироваться дискретно. • Все сотрудники работают по восемь часов в день. • Каждый запрос на отпуск подчиняется правилам, установленным в конкретном отделе компании. • Правила верификации запросов определяются отделом кадров. Эти виды ограничений и знаний могут быть внедрены в спецификации или перечислены отдельно. Знания из предметной области также могут быть открыты для доступа из всех документов. Например, подробные правила верификации запросов являются частью инструкции и открыты для доступа из многих источников (например, во внутренней сети, формах, документах, презентациях для новых сотрудников и т.д.). Проект может потребовать, чтобы система VTS лишь ссылалась на эти правила, но не дублировала их. 12.3 Конструирование При анализе потенциального Web-приложения, как и практически любого программного обеспечения, наиболее важной задачей является идентификация сущностей и процессов системы. Сущности и процессы приложения описывают концепции предметной области и, в идеале, не зависят от архитектуры, хотя это не
544 Часть III. Приложения обязательно. Наиболее важным множеством артефактов в Web-приложении является карта навигации и определения Web-страниц. Грубо говоря, эти элементы соответствуют стереотипам сущности, контроллера и границ, принятым в классическом анализе. Начнем изложение с модели Web-приложения: модели действий пользователя (User Experience — UX). Модель действий пользователя Модель действий пользователя [1,2] — это один из примеров, который описывает элементы интерфейса пользователя Web-приложения на достаточно высоком уровне абстракции, позволяющее задать навигацию по Web-страницам приложения без учета стилей (шрифтов, размеров, цветов и т.д.) и других элементов пользовательского интерфейса, которые целесообразно разрабатывать на более поздних этапах проектирования. На рис. 12.8 показан фрагмент высокоуровневой модели действий пользователя, описывающий экраны, используемые для реализации основного сценария. На диаграмме показаны два стереотипа: «Screen» и «Form». Стереотип «Screen» представляет собой класс, описывающий пользовательский интерфейс, изображенный на экране, т.е., грубо говоря, — Web- страницу. Некоторые экраны содержат элементы HTLM-форм, используемых для передачи информации на сервер. Эти стереотипные классы всегда связаны с экраном и управляют переходом с одной Web-страницы на другую. Направления отношений ассоциации указывают пути перехода между экранами. Рис. 12.8. Высокоуровневая модель действий пользователя Несмотря на то что диаграмма, представленная на рис. 12.8, очень полезна для понимания потока переходов между экранами системы, она дает мало информации о содержании страниц. На этом уровне абстракции были бы полезными более подробные диаграммы, описывающие содержание каждого экрана. Например, на рис. 12.9 показано содержание экрана VTSHome. Атрибуты стереотипного класса «Screen» описывают отдельные значения, которые обычно представляют со-
Глава 12. Web-приложение: система планирования отпусков 545 бой строки или простые типы, легко воспроизводящиеся с помощью языка HTML. Атрибуты employee name (имя сотрудника) и current data (текущие данные), скорее всего, используются в качестве заголовка или верхней надписи на экране. Атрибут message используется для отображения информации или сообщения об ошибке после произведенного действия. Например, когда сотрудник заполняет запрос и возвращается на главную страницу, он может получить такое сообщение: "Ваш запрос требует одобрения менеджера, который получит сообщение по электронной почте". «Content» Θ Request α state ο title α hours a dates g category Рис. 12.9. Подробная структура класса VTSHome Часто содержание экрана бывает разнообразным и сложным. Для того чтобы точно отобразить это содержание, в системе определен стереотипный класс «Content», идентифицирующий совокупность логически связанной информации. Элементами содержания экрана часто являются пункты списков. На рис. 12.9 показаны классы Request (Запрос) и PendingApproval (Ожидающие запросы), моделирующие содержание главной страницы. На экране могут отображаться многочисленные объекты этих классов. Классы содержания определяют атрибуты, как правило, представляющие собой атрибуты экрана, легко воспроизводимые с помощью языка HTML. На данном достаточно высоком уровне абстракции реальные типы данных можно игнорировать. Достаточно указать их название и дать краткое описание. Интересно отметить, что даже на этом, довольно раннем этапе, приходится принимать очень важные решения, которые будут сильно влиять на окончательную реализацию системы. Например, указав, что страница VTSHome содержит не только резюме запроса на отпуск, но и список запросов, ожидающих одобрения «Screen» Θ VTSHome a employee name о current date ρ message pendingapproval «Content» Θ PendingApproval ^request .1 31 α employee name ° title a dates
546 Часть III. Приложения менеджера, мы принимаем решение, что этот экран является главной страницей как для сотрудника, так и для менеджера. Следует подчеркнуть, что ни в спецификациях сценария использования, ни в списке нефункциональных требований к системе не указано, что сотрудники и менеджеры должны использовать одну и ту же главную страницу. Это условие не лишено смысла, поскольку и сотрудники, и менеджеры выполняют одинаковые действия. Модель действий пользователя предназначена именно для документации таких решений. Таким образом, окончательное решение можно принять на этапе реализации системы. Однако с точки зрения логической модели (и модели действий пользователя) сотрудники и менеджеры совместно используют одну и ту же главную страницу. Модели анализа и проектирования В ходе анализа необходимо описать сущности и процессы системы. Поскольку известно, что данная система будет реализована в виде Web-приложения, можно меньше заботиться о границах, поскольку они исследуются на этапе разработки модели действий пользователя. Анализ этой модели является первой попыткой идентифицировать элементы, образующие пространство решений, с использованием словаря предметной области. Это значит, что большинство элементов модели будут иметь имена, соответствующие предметам и действиям, которые описаны требованиями и заданы конечными пользователями и предметной областью. Для начала можно просто проанализировать спецификации сценариев использования и документы, содержащие требования к системе, выделив существительные и глаголы. Важные существительные будут представлены в виде классов, а глаголы — операциями, включенными в эти классы. Атрибуты и отношения представляют внутренние свойства классов, описывающих сущности предметной области и концепции, упомянутые в основном сценарии использования. Первый этап анализа, посвященный классам предметной области и концепциями основного сценария использования, описан на рис. 12.10. Рассматривая диаграмму классов, необходимо учитывать следующее. Во-первых, запросы на отпуск отличаются от процесса предоставления отпуска. Отпуск может быть предоставлен и без запроса. Эта процедура регулируется отделом кадров и определяется политикой компании. Однако в контексте сценария использования их основная обязанность — создавать новые запросы на отпуск. Их персистентными свойствами являются количество часов, которые можно запросить в течение года, и сроки действия разрешений (если это предусмотрено). Другое важное решение, воплощенное в этой диаграмме, заключается в идее, что менеджер также является сотрудником. Несмотря на естественность этого условия, такие предположения не всегда реализуются при разработке программного обеспечения. Диаграмма классов учитывает также, что сотрудник может иметь несколько начальников. Это утверждение не относится к описанию иерархии ком-
Глава 12. Web-приложение: система планирования отпусков 547 "Щосайоп - prlmaryWorkLocatlon - employee О Category "о" name rstTlng" α description: String manages • manager ^Employee о name: String - category 0..1 - grant * J α hours : Int α expires: Date g active: Date • request Π ψ- requests •grant о title: String a comments: String a hours: Int о dates: Date • validate () requests grant - reitrlcttonr •Tgpjjjjggjr a name: String о description: String • vJcbtoQ Рис. 12.10. Аналитическая модель диаграммы классов, поддерживающей основной сценарий использования пании и организации, а лишь описывает контекст принятия решения о запросе, которое может иметь несколько источников. Например, в некоторых компаниях высокопоставленные менеджеры имеют помощников по персоналу. Эти помощники могут передать право принимать решение исполнителям. Другие свойства сотрудника — имена и основное место работы. Следует отметить, что на данном уровне абстракции имя сотрудника представляет собой неразрывную строку. Другие приложения, управляющие информацией о сотруднике, могут разделять эту строку на имя, отчество и фамилию. Однако в этом приложении такое разделение не важно, так как имя сотрудника используется исключительно на экране главной страницы. Общее правило гласит: сложное решение следует принимать лишь тогда, когда это абсолютно необходимо. Другой интересный и важный аспект большинства аналитических моделей заключается в отсутствии определений идентификаторов. Практически во всех реализациях систем, содержащих персистентные сущности, присутствует концепция уникального идентификационного номера. Например, большинство компаний присваивают своим сотрудникам идентификационные номера, однозначно определяющие конкретных сотрудников и часто вновь используемые, когда сотрудники уходят, а затем возвращаются в компанию. Необходимость идентификационного номера очевидна, при условии что он является уникальным. Однако в нашем приложении атрибуты идентификационных номеров не определены. Это объясняется тем, что в большинстве аналитических моделей идентификационные номера и другие свойства можно добавлять по мере необходимости. Если это не обуслов-
548 Часть III. Приложения лено требованиями бизнеса, то на этапе анализа подобной информацией можно пренебречь. Предположим, например, что в системе существует еще одно действующее лицо Auditor, в обязанности которого входит просмотр всех запросов на отпуск и проверку правил. Разумеется, этому действующему лицу необходимо знать идентификационные номера сотрудников, а также другую информацию. В данном случае важно иметь возможность указывать атрибуты сотрудников. Некоторые интересные элементы модели можно представить в виде конечных автоматов. Например, класс Request (Запрос) можно описать так, как показано на рис. 12.11. На диаграмме, представленной на рис. 12.11, показаны три традиционных и четыре финальных состояния. Пути, проходящие через эти состояния, очень просты, поэтому диаграмма не содержит меток. создан j ®<- подан отклонен } -эф отозван одобрен 4 ) ■^® аннулирован завершен Рис. 12.11. Конечный автомат для класса Request До сих пор наиболее сложной частью анализа было создание элементов, которые бы проверяли, не нарушают ли поданные запросы правил и ограничений, установленных компанией и руководством отдела. В сценарии использования об этих правилах сказано мало. В них просто содержатся ссылки на действующие документы компании. Кроме того, требования предусматривают создание экс-
Глава 12. Web-приложение: система планирования отпусков 549 пертной системы, управляемой отделом кадров. Это требование само по себе означает, что подход к созданию системы должен быть гибким и допускать управление со стороны пользователей, не имеющих специальной подготовки в области компьютерных наук. Это важное условие, поскольку при использовании одного из языков описания сценариев, например, JavaScript, можно создать прозрачный и очень гибкий механизм реализации универсальной системы, основанной на правилах. Язык JavaScript способен интерпретировать большинство алгоритмов, простых или сложных, и легко взаимодействовать с персистентными сущностями и объектами. Разумеется, основная проблема заключается в том, что сотрудник отдела кадров, отвечающий за правильную работу системы, может не знать языка JavaScript. Задолго до принятия решения или даже выбора стратегии реализации необходимо идентифицировать высокоуровневые абстрактные элементы, содержащиеся в модели. На первых порах можно создать отдельный класс Restrictions (Ограничения) и возложить на него всю ответственность за оценку запросов с точки зрения правил, принятых в компании и отделе сотрудника. Однако нам необходимо глубже вникнуть в правила и законодательные акты, касающиеся отпусков. К сожалению, в сценариях использования очень мало говорится о внутренней структуре этих правил, а в документах компании приведены лишь конкретные нормы. Следовательно, необходимо тщательно проанализировать шаблоны, описывающие совокупность таких правил. Для этого часто приходится общаться с экспертами в предметной области. После тщательного исследования правил, принятых компанией, и консультаций с экспертами в предметной области, работающими в отделе кадров, можно подвести промежуточные итоги. • Сотрудник не имеет права получить более X дней подряд в качестве отпуска вида Y. • Отпуск вида X не может быть предоставлен, если он начинается сразу после праздников. • Срок отпуска вида X ограничен Υ часами в неделю или в месяц. • Отпуск не может быть предоставлен, если на работе остается только X из Υ сотрудников. • Отпуск не может быть предоставлен в определенные даты: X. • Отпуск определенного типа может быть предоставлен только в конкретные дни недели: {М, Т, W, Th, F, Sat, Sun}. Подробный анализ правил, регламентирующих предоставление отпусков, вынуждает нас внести в модель важные изменения. Очевидно, что реализация требования должна содержать конкретную информацию. Чтобы сформулировать стра-
550 Часть III. Приложения тегию реализации, создадим специализации абстрактного класса Restriction (Ограничение), по одной на каждый вид правил, как показано на рис. 12.12. Ъ'ШШГ о name : String g description : String • validate ( requestι Request): UafctotfonResuft _^ , G DateExclustonResti Ictlon О ConsecutlveDayRestrictton 0 DayOfWeekRestriction G CowoikerRestritlon G PeriodLlmttRestrictton Рис. 12.12. Иерархия класса Restriction В каждой специализации необходимо реализовать метод validate (), принимающий объект класса Request в качестве параметра. От объекта класса Request метод validate () получит информацию, необходимую для его оценки (Employee, Grant, Locvation). Поскольку правила разнообразны, информации может оказаться недостаточно для оценки запроса. Следовательно, каждая специализация должна управлять набором свойств или отношений с объектами, которые нельзя вывести из класса Grant или к которым нельзя перейти с его помощью. Например, класс CoworkerRestriction (Ограничение количества сотрудников) должен иметь возможность управлять списком коллег, чтобы определить минимальное количество сотрудников, назначенных на работу (рис. 12.13). Такие правила часто связаны с нормами безопасности (например, один из сотрудников отдела должен уметь оказывать первую медицинскую помощь). Θ Employee д nameiStrtng " GCowoHcerftertricttoo' ТУЩГ*1Г1*У1Г -OJ о mhCount: ht • vakJate (request: Request): VaMattonReaJt Рис. 12.13. Класс CoworkerRestriction и его свойства В первоначальном варианте абстрактный метод validate () возвращал простое булево значение, указывающее, прошел запрос проверку или нет. Однако если глубже изучить требования, то можно увидеть, что пользователю необходимо дать объяснение причин отказа. Поскольку правила проверки запросов теперь инкапсулированы в каждой из специализаций класса Restriction, будет удобно снабдить эти классы механизмом для возврата информации вызывающему процессу Кроме того, если произойдет несколько нарушений правил, результаты
Глава 12. Web-приложение: система планирования отпусков 551 проверки можно будет собрать в коллекцию. Это приводит нас к новому классу ValidationResult (рис. 12.14), объекты которого возвращаются методом validate (). О ValidationResult • validated (}: boolean # getErrors (): Collection Рис. 12.14. Класс ValidationResult Класс ValidationResult действительно довольно прост. В нем определены два метода: validated(), возвращающий булево значение, характеризующее статус запроса, и getErrors (), возвращающий набор сообщений, которые описывают выявленные ошибки. На этом уровне анализа можно не усложнять класс ValidationResult, отложив детали реализации до этапа проектирования деятельности. Следует подчеркнуть, что процесс должен иметь возможность верифицировать запросы на отпуск и сообщать об ошибках. Кроме того, анализ правил показывает, что эти ограничения можно связывать не с конкретными объектами класса Grant или Employee, а с классами Location или Category. Таким образом, прежнюю модель придется изменить (рис. 12.15). Определение этих отношений позволяет клеркам отдела кадров применять широкий набор общих правил, не дублируя их для каждого сотрудника по отдельности. Поскольку эта информация необходима на этапе верификации, мотивация для изменения проекта основана на желании облегчить использование системы. В данном случае облегчается работа сотрудников отдела кадров. OLocation о name ι String • primaryWorkLocatton Γ Q Restriction в name: String _ -J- - ,, „t|| , ll | „I. , -—' « в QeSOyUmt i SUFЩ • v*bte()~ о name:String ]♦—"У**^ '^^щщшпт в houre:int в expires:Date в active:Date • request О 1 -ΟΙ grants торг *»<"ywm»^mw'w о name:Strhg ρ description: String Рис. 12.15. Независимые и прямые отношения среди классов Location, Grant и Category
552 Часть III. Приложения После уточнения ограничений и правил целесообразно повторно рассмотреть сценарий использования системы сотрудниками отдела кадров, поскольку теперь известна информация о типе и природе сведений, необходимых при верификации запросов. За пределами нашего анализа, ограниченного объемом главы, остались многие Web-страницы, на которых сотрудники должны вводить соответствующие данные. В этом случае объекты класса Restriction должны публиковать желательные параметры (например, выводить поля редактирования для ввода значений X и F), чтобы сотрудник отдела кадров мог вводить значения, предусмотренные пользовательским интерфейсом. Для инкапсуляции этих значений предусмотрен вспомогательный класс RestrictionParameterDescriptior (Дескриптор параметров требования). Создание массивов, состоящих из объектов этого класса, входит в обязанности класса Restriction. Дескрипторы позволяют сотрудникам отдела кадров определять новые ограничения, касающиеся конкретного сотрудника, отдела или категории отпуска. Эта задача выполняется методами put и get, выключающими имя параметра. Оба эти класса приведены на рис. 12.16. Restriction о name: String о description; String и • Y^ieTrhquest: Requesf): Т/ШШжЯеяЖ Φ getPararnetefDesctytars (): RestrfctkrParameterDescriptor [*] • putParameter (name : String, object: Object): void • getParameter (name : String): Object ORestrictionP3rdn№t о name .String о description: String # ls&ximeratt)n*nTBbbie^ # getErxjmerattonUst (): Cofectton Рис. 12.16. Классы, облегчающие создание ограничений На любой стадии анализа полезно еще раз проверить идеи, на которых основана модель. Однако поскольку мы не выбирали фактическую архитектуру для каждой программы, модель следует анализировать немного абстрактнее. Для этого следует провести мысленный эксперимент с элементами модели, пытаясь понять, как действуют в сценарии включенные в нее структуры и функции. Обработка ограничений представляет собой удобный повод для верификации типичных сценариев использования, причем наиболее важные из них следует анализировать на основе реальных данных. Для этой задачи в языке UML подходят диаграммы объектов и связей. Предположим, нам требуется оценить способность системы верифицировать новый запрос на отпуск. Нужно убедиться, что поведение системы соответствует требованиям и правильно описывается соответствующим набором классов и объектов. В этом мысленном эксперименте можно использовать диаграммы для того, чтобы понять, каким образом будет обработан новый запрос сотрудника по имени Jim, работающего на заводе North Factory. На рис. 12.17 приведена диаграмма объектов, описывающая процесс верификации запросов сотрудника Jim, желающего получить дополнительные дни отпус-
Глава 12. Web-приложение: система планирования отпусков 553 ка за вовремя завершенную работу. На рисунке показаны зависимости, с помощью которых можно получить доступ к объектам. Экземпляры имеют реальные имена, соответствующие сценарию, и сопровождаются двоеточием и типом класса, к которому они относятся. Эту диаграмму можно сопроводить прямоугольниками, демонстрирующими три источника ограничений: Grant, Location и Category. jim :Employee τΐτ newRequest :Request safetyOfflcere :EmployeeGroup 7Г fireControtOfficere :EmployeeGroup /y J safetyOfficerRequired iCoworkerRestrictlon northFactory rLocation fireControlOfficerRequired :Locatlon X ^ bonus :C V rant 1 I ЧчА Isolated :ConsecutiveDayRestriction allHandsSafetyReview :DateExciusionRestriction l ___>» —^ award :Category \i/ q4 :PerlodLimit 1 ттщгтят ь mwmmm \ bonusValldatlon rValldationResult Рис. 12.17. Диаграмма объектов, описывающая процесс верификации запроса На рис. 12.18 показана диаграмма коммуникации, описывающая связи, задействованные при верификации запроса. Отметим, что на этой диаграмме линии связей между объектами не являются структурными отношениями, как на диаграмме классов. Взаимодействие между объектами выявляется в ходе отслеживания пронумерованных сообщений, проходящих по этим линиям связи. Основным координатором поведения системы является экземпляр Request, выполняющий большую часть работы в этом сценарии. Основной поток действий направлен на получение запроса и проверку разнообразных ограничений, перечисленных
554 Часть III. Приложения в источниках Location и Category, с последующим применением операции validate () к каждому из этих источников. Если ограничения нарушены, то сообщение передается экземпляру, хранящему результаты проверки. result :ValidatlonResult grant :Grant isolated : ConsecutiveDayRestrlction I allHandsSafetyReview: DateExclusionRestriction k щттк'щтт'шч'тчч'мгяпш'М'щ^гтч jim :Employee 2: getLocation northFactory: Location safetyOfficerRequired: | CoworkerRestriction q4 :PeriodLimit fireControlOfficers EmpioyeeGroup - 5 1 islnGroup Рис. 12.18. Диаграмма коммуникации, описывающая процесс верификации запроса Интересно проследить поток, описывающий проверку ограничения CoworkerRestriction. Для того чтобы проверить это ограничение, необходимо знать не только, к какой группе сотрудников (EmpioyeeGroup) оно относится, но и какой именно сотрудник (Employee) подал данный запрос. Беглого взгляда на сигнатуру операции validate () достаточно, чтобы увидеть, что объект класса Request передается ей как параметр, а затем управление переходит к объекту класса Employee. Кроме того, для проверки ограничения CoworkerRestriction необходим доступ к планам отпусков всех других членов группы, чтобы во время отпуска на рабочем месте оставался хотя бы один сотрудник. До сих пор данная модель не давала однозначного ответа на вопрос, как это сделать. Следовательно, наш мысленный эксперимент показывает, что необходимо пересмотреть модель и гарантировать, чтобы все ограничения имели доступ к информации, необходимой для оценки запросов.
Глава 12. Web-приложение: система планирования отпусков 555 Как указывалось в главе 6, начало и конец анализа не являются узловыми событиями. Деятельность, связанная с анализом, часто осуществляется на протяжении всего жизненного цикла проекта. Однако большая часть анализа сосредоточена на этапе изучения основных ограничений системы. Если анализ модели достигает достаточной глубины, наступает момент, когда следует переходить к проектированию. Разумеется, это определение чересчур расплывчато, но такова реальность. Момент, когда начинается проектирование, часто выбирается, исходя из местных условий, например, в зависимости от истории проекта или организации, а также от зрелости архитектуры. Теперь перейдем к воплощению результатов анализа в проект, который в конце концов будет реализован в виде программного обеспечения. Одни проектные модели идентичны исполняемым, а другие слишком абстрактны и требуют дополнительных усилий на этапе их реализации. Как правило, Web-приложения представляют собой смешение этих крайностей. Большинство элементов делового яруса (сущности и контроллеры) находят достаточно полное отражение в результирующем коде системы. В то же время многие презентационные модели требуют дополнительной работы при создании окончательного варианта системы. В обсуждении проекта системы VTS не рассматривались интересные аспекты проектирования Web-приложений. Вместо этого мы сосредоточились на нескольких важных вопросах, в частности, тех, которые наиболее характерны для Web- приложений. Кроме основных архитектурных компонентов сети Web, в проекте использованы такие элементы и технологии. • Клиентский ярус. Любой браузер, совместимый с языком HTML 3.2. • Ярус презентации. Технологии Java Server Pages (JSP), Servlets и Java Server Faces (JSF). • Деловой ярус. Компоненты Enterprise Java Beans (EJB) 2.x (в частности, Container Managed Persistence (CMP) и Service Data Objects (SDO)). • Безопасность. Протокол Central Authentication Service (CAS)2. Нами было принято решение разработать архитектуру на основе продуктов, созданных с помощью языка Java. Это не связано с тем, что решения, использующие язык Java, позволяют точнее обеспечить выполнение ограничений, чем другие технологии. Просто проектировщики, работающие в организации, исполняющей проект, лучше знают этот язык, причем он вполне подходит для решения поставленной задачи. В прошлом эта организация уже создала несколько промышленных приложений на основе языка Java, используя технологии J2EE. Таким образом, эта технология уже знакома разработчикам и они имеют готовые инструменты, 2Более подробную информацию можно найти на сайте www.ja-sig.org/products/cas.
556 Часть III. Приложения позволяющие создавать Web-приложения. В нашей ситуации нет никаких предпосылок изменять технологию. Есть лишь две причины, которые могли бы привести к переходу на другую технологию. 1. Недавний опыт выявил серьезные проблемы, связанные с используемой технологией, или неспособность выполнить задачи, поставленные перед разработчиками, обслуживающим персоналом и конечными пользователями. 2. Сама по себе технология больше не поддерживается или подверглась значительным изменениям, по существу, став новой технологией. Основная цель проекта на ярусах клиентов и презентации — реализовать интуитивно понятный пользовательский интерфейс, обеспечивающий быструю реакцию системы и легкую навигацию. Интерфейс не должен зависеть ни от одного браузера, или, точнее говоря, он должен корректно работать со всеми стандартными браузерами, совместимыми с языком HTML 3.2. Несмотря на то что в момент написания книги уже появилась версия языка HTML 4.01, решение поддерживать версию 3.2 (и более поздние) было продиктовано не столько доступностью или популярностью браузеров, сколько желанием обеспечить минимальную функциональность. Как выяснилось, старые версии языка HTML обладают всеми свойствами, необходимыми для реализации системы. Таким образом, если нет острой необходимости использовать новые браузеры и отказаться от старых, приложение может поддерживать более широкий спектр версий. Кроме основных технологий презентации, JSP и Servlets, при разработке интуитивного интерфейса архитекторы решили использовать компоненты JSF, представляющие собой программный интерфейс приложения (API) и библиотеку пользовательских дескрипторов, содержащую большое количество компонентов, позволяющих создавать формы интерфейсов, вводить и выводить данные, а также переходить со страницы на страницу. Следует отметить, что проектировщики отказались от среды Apache Struts, представляющей собой устаревшую модель MVC, по-прежнему широко распространенную среди JSP-приложений. Инструменты Struts и JSP хорошо согласуются друг с другом, даже если их функциональные свойства иногда перекрываются. В то время как среда JSP обеспечивает некоторые функциональные свойства среды JSF, ее сильной стороной являются функции контроллера. Инструменты Struts особенно полезны, когда Web-приложение реализует длинный бизнес-процесс, т.е. процесс, связанный с многочисленными переходами со страницы на страницу. Рассматриваемый бизнес-процесс является относительно коротким, поэтому преимуществ, которые может предоставить технология Struts, недостаточно для того, чтобы компенсировать затраты на создание дополнительного слоя приложения. Деловой ярус, на котором исполняется большинство, если не все функции системы, содержится в Web- или EJB-контейнере J2EE. Запуск Web- и EJB-контей-
Глава 12. Web-приложение: система планирования отпусков 557 неров на одной и той же машине, создание кластеров таких контейнеров и выбор другой конфигурации не зависит от проекта. Одно из преимуществ архитектуры, основанной на технологиях J2EE, заключается в способности откладывать такие решения до начала развертывания системы или до изменения первоначальных требований. Следует помнить, что в ходе анализа и реализации системы нельзя создавать программы, препятствующие нормальной работе контейнера J2EE. Для этого команды проектировщиков вырабатывают определенные правила программирования. Для хранения персистентных объектов мы решили использовать механизм СМР. Существует много аргументов за и против этого механизма. В качестве альтернативы можно было бы применить объекты Plain Old Java Objects (POJOs) и реляционные слои персистентных объектов Hibernate, Castor или Apache ObJect- RelationalBridge (OJB). Эти инструменты могли бы оказаться эффективнее, особенно если приложение запускается лишь на одном узле. Выбор механизма СМР был обусловлен производительностью разрабатываемой системы, не допускающей применения других технологий. Кроме того, использование SDO облегчает управление потоком данных между деловым ярусом и ярусом презентации. Нельзя не упомянуть об одной из частей архитектуры — использование протокола CAS для предъявления пароля для входа в систему. Идея заключается в том, что, работая с одним и тем же браузером, пользователь может только один раз ввести пароль, чтобы получить доступ ко всем приложениям системы. Это требование возникло еще на ранних стадиях анализа, поскольку создаваемая система должна была стать расширением существующего внутрисетевого портала компании, который в настоящее время использует протокол CAS. Следовательно, новое приложение VTS также должно использовать протокол CAS для идентификации и аутентификации конечных пользователей. Сущности Наиболее важной задачей проектирования и реализации сущностей является их идентификация. В любой аналитической модели все объекты, имеющие атрибуты, и даже объекты без атрибутов можно спроектировать в виде сущностей. Трюк заключается в выборе только тех классов, которые должны быть разработаны как персистентные сущности. Например, некоторые классы, даже имеющие атрибуты, могут быть просто промежуточными или описывать значения. Например, класс ValidationResult (Результат проверки) используется только как значение, возвращаемое методом validate. Результаты оценки не регистрируются и не записываются в системе, поэтому класс ValidationResult не обязан быть персистентным. При оценке запроса экземпляр этого класса возвращается вызывающему модулю для проверки результатов верификации. После завершения
558 Часть III. Приложения проверки эти результаты больше не обязательно хранить. Следовательно, класс ValidationResult может быть простым классом РОЮ. Система VTS использует компоненты СМР для управления всеми персистент- ными сущностями. За прошедшие годы технология СМР прошла долгий путь. Вначале с ней были связаны многочисленные проблемы, особенно большие сложности вызывали отношения и производительность. Однако в настоящее время появилась новая спецификация и улучшенные EJB-контейнеры, благодаря которым компоненты СМР широко используются для управления сущностями. Уже распространены новые шаблоны проектирования, разработанные на основе компонентов СМР. Как правило, компоненты СМР рекомендуются только для определения локальных интерфейсов. Доступ к локальному интерфейсу имеют только компоненты, находящиеся в том же самом контейнере. Распределение данных по локальным компонентам, связанным между собой, намного эффективнее, чем через инфраструктуру, поддерживающую перекрестные связи. Доступ к этим объектам осуществляется через фасадный объект, имеющий не только локальную связь с компонентами СМР, но и дистанционные интерфейсы, к которым могут получить доступ компоненты других сессий или дистанционных клиентов. Компоненты SDO используются для передачи данных внутрь и вовне яруса презентации. Эти объекты создаются и управляются фасадными объектами, находящимися на деловом ярусе. Компоненты SDO являются результатом сотрудничества компаний ΒΕΑ и IBM, двух крупных 12ЕЕ-контейнеров и воплощают наилучшие методы обработки данных в EJB-приложениях. Другим важным свойством компонентов СМР является требование, чтобы они разрабатывались с минимальным набором деловых функций. Проще всего рассматривать компоненты СМР как нечто немногим большее, чем упаковка для таблицы базы данных. Все деловые функции должны быть размещены в фасадных объектах компонента сессии, организовывающих работы разных компонентов СМР для реализации деловых функций. Это требование оказывает непосредственное влияние на анализ проектируемых и реализуемых сущностей. В процессе изучения класса Category (Категория) становится понятно, как реализуются все эти шаблоны проектирования и соглашения. Этот класс относительно прост, поскольку в нем определены лишь два персистентных свойства, а также отношение с экземплярами класса Grant. В счастью, на этапе анализа класс Category не содержит никаких важных деловых функций, иначе нам пришлось бы удалить их оттуда и разместить в фасадных объектах. Таким образом, проектирование системы начинается с очень простого класса. Спроектируем сущности, описанные стереотипными классами «Entity Веап>>. В этих классах определены персистентные атрибуты. Основные атрибуты в дальнейшем продолжают стереотипироваться. Методы классов «Entity Веап>> разделяются на локальные и дистанционные (хотя в данном случае в классе Category не определен ни один дистанционный метод), а также на
Глава 12. Web-приложение: система планирования отпусков 559 уровни экземпляра и класса. Каждая из этих категорий соответствует конкретному интерфейсу. Для того чтобы определить локальные методы, которые можно вызвать и применить к экземпляру компонента, а также домашнему и фабричному объектам, ответственным за создание и поиск экземпляров, в классе Category потребуется два интерфейса — CategoryLocal и CategoryLocalHome. На рис. 12.19 показана UML-подобная диаграмма3 компонента-сущности Category, имеющего отношение с сущностью Grant4. [ «Entity Bean» (jj| Category о 0\d : Integer о ® name : String °® description : String €F CategoryLocalHome • •create () • •flndByPrimaryKey () • "create Μ О CategoryLocal •L getName () •L setName () •L getDescription () •L setDescription () • getGrant () I · setGrant () Рис. 12.19. Представление класса Category Работая с отдельными элементами модели, соответствующими сущностям, легче понять отношения между ними. Однако в реализации каждая сущность на самом деле имеет большое количество разных классов, интерфейсов или файлов конфигурации. Например, класс Category имеет два интерфейса (Category- Local и CategoryLocalHome) и один класс реализации (CategoryBean), упакованный в другие компоненты архивного Java-файла (Java Archive — JAR), записывает информацию в дескрипторный файл развертывания компонентов EJB и регистрируется в таблице базы данных (рис. 12.20). При переходе от анализа к проектированию и реализации элементы модели будут уточняться и раскрываться. Элементы, выявленные на этапе анализа, часто воплощаются во многих элементах реализации, требующих координации. Фрагмент дескриптора развертывания компонентов EJB, содержащего элементы, связанные с сущностью категории, показан на листинге 12.1. 3Эта диаграмма представляет собой специальное изображение компонента для реализации сущностей, который в системе J2EE включает в себя класс реализации, а также его интерфейсы и определенную информацию о конфигурации. Кроме того, использование методов доступа к свойствам объекта не является объектно-ориентированным обычаем и диктуется применением сред Java и J2EE. 4Поскольку мы используем 12ЕЕ-архитектуру, применение системы обозначений, связанных с конкретной платформой, является неприемлемым. h category 0..1 + grant * «Entity Bean» ©Grant
560 Часть III. Приложения «Java Interface, Local Home Interface» €^ Category LocalHome • 'create () • *flndByPrlmaryKey() • * create () £f «EJB Implementation» «Java Interface, Local Interface» G CategoryLocal • fc getName () •L setName () •L getDesci iption () • LsetDescrlptlon() • getGrant () • setGrant () <4EJB Implementation» «Table» El CATEGORY о 1 NAME о g DESCRIPTION i<—«map»·- Я\ «manifestation» «Entity Bean» Щ Category о <$}id: Integer о ® name : String о © description : String €F CategoryLocalHome • ■"create () • ■"findByPrimaryKey () • * create () G CategoryLocal •L getName () •L setName () •l getDescription () •L setDescription () • getGrant () • setGrant () «EJ£ Realization» category «Java dan, Bean Class» QjCategoryBean a myEntityCtx: EntltyContext • setEntityContext () • getEntltyContext () • unsetEntityContext () • ejbCreate () • ejbCreate (} • ejbPostCreate () • ejbPostCreate (} • ejbActivate () • ejbLoad () • ejbPassivate () • ejbRemove () • ejbStore () • getld() • setld ( ) • getName ( ) • setName ( ) Ш getDesciption () • setOescnption () • getGrant ( ) • setGrant ( ) Ю..1 grant «EJB Jar» ^IVTSBeans «Entity Bean» 1® Grant Рис. 12.20. Элементы проекта класса Category Листинг 12.1. Фрагмент дескриптора развертывания компонентов EJB, содержащего элементы, связанные с сущностью категории <ejb-jar id="ejb-jar\_ID" version="2.1" xmlns="http://Java.sun.com/xml/ns/j2ee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://java.sun.com/xml/ns/j2ee http://java.sun.com/xml/ns/j2ee/ejb-jar_2_l.xsd"> <display-name>VTSEJB</display-name> <entity id="Category"> <ejb-name>Category</ejb-name> <local-home>com.acme.vts.CategoryLocalHome</local-home> <local>com.acme.vts.CategoryLocal</local> <ejb-class>com.acme.vts.CategoryBean</ejb-class> <persistence-type>Container</persistence-type> <prim-key-class>java.lang.Integer</prim-key-class> <reentrant>false</reentrant> <cmp-version>2.x</cmp-version> <abstract-schema-name>Category</abstract-schema-name> <cmp-field id="CMPAttribute_1107874632507"> <field-name>id</field-name>
Глава 12. Web-приложение: система планирования отпусков 561 </cmp-field> <cmp-field id=MCMPAttribute_l107874633048"> <field-name>name</field-name> </cmp-field> <cmp-field id=MCMPAttribute_1107874 633068"> <field-name>description</field-name> </cmp-field> <primkey-field>id</primkey-field> <query> <description></description> <query-method> <method-name>findAll</method-name> <method-params/> </query-method> <ejb-ql>select object(o) from Category o</ejb-ql> </query> </entity> </ejb-jar> Следуя выработанным нами принципам, определим фасадный5 объект для класса Category. Этот объект предназначен для того, чтобы упростить интерфейс для реализации общих задач бизнес-сущности. Для этого часто необходима координация методов, принадлежащих нескольким объектам. Шаблон Session Facade (Фасад сеанса) предоставляет простой интерфейс для поиска, создания, модификации и удаления сущностей. К счастью, наша интегрированная среда разработки обеспечивает автоматическое создание фасадных объектов для компонентов-сущностей. Результат называется CategoryFacade (Фасад категории) и, как и представление компонента-сущности, определяет функциональные свойства как на дистанционном, так и на локальном уровнях, а также на уровнях экземпляра и фабрики. В нашей модели стереотипированная зависимость << facade» означает семантическую связь между фасадным объектом и представлением сущности в модели. Фасадный класс обеспечивает множество методов для создания, поиска, обновления и удаления сущностей класса Category. По существу, он действует как менеджер отдельного источника экземпляров данного класса. Этот фасадный объект представлен на рис. 12.21. Сервисные объекты данных Другой характеристикой данной реализации фасада является использование относительно нового стандарта — SDO (Service Data Objects). Проще говоря, SDO — это механизм для доступа и манипулирования данных, отделенный от их 5 См. шаблон Session Facade, описанный в книге Core J2EE Patterns [4].
562 Часть III. Приложения OiCategoryFacade U CategoryFaeadeLocalHome Φ» create () €f CategoryFaeadeHome •H create () CP CategoryFacadeRernote • R getAHCategoryOb)ects () • RgetCategoryByKey() • R createCategory () • RupdateCategory() • RdeteteCategory (} • ■ applyCategoryRootChangee () • RgetCategoryRoot() С CategoryFacadeLocal •l getAICategoryObJects () • LgetCategoryByKey() •L createCategory () • LupdateCategory() • LdeieteCategory() •L apptyCategoryRootChanges () • LgetCategoryRoot() «facade» Й Category о^id: Integer о ® name : String о ® description : String U1 CategoryLocalHorne • ■"CTeateO • •flndByPrimaryKey () • ■"created G CategoryLocai • LgetName() • LsetName() • LgetOeicrlption() • LsetDescriptton() • getGrant () • letGrant () Рис. 12.21. Фасадный объект, управляющий доступом к компонентам-сущностям источника. Он предоставляет удобные средства для распределения данных в системе. Механизм SDO использует несвязные графы данных и позволяет пользователям получать эти графы из источника, манипулировать ими, а затем возвращать в исходный источник. Использование механизма SDO позволяет повысить согласованность интерфейса с компонентами данных в рамках всего приложения. При генерации фасадных классов создается соответствующее множество объектов SDO. Каждый созданный объект SDO определяет два интерфейса: корневой объект (для графа данных) и интерфейс сущности. Корневой объект представляет собой концептуальную вершину графа данных (рис. 12.22). О CtteooryfaudeLocaj ·* getAfcategoryODjects (): Category [·] • l getCategoryByKey (plmaryKey: Integer): Category • l oeateCategory (data: Category ): void • L updateCategory (data : Category }: void • l deleteCategory (data: Category ): void •L applyCategoryRootCnangei (root: CategoryRoot): void • l getCategoryRoot (): CategoryRoot О CXegoryRoot • getCategory (}: Let • getCategoryAsArray (): Category [*] • createCategory (): Category О Category • getld (): Integer • ntld (value : Integer): void • getName (): String • aetName (value : String ): void • getOBKrlptlon (): String • wtOerelptlon (value: String }: void Рис. 12.22. Объекты SDO, используемые классом CategoryFacadeLocal
Глава 12. Web-приложение: система планирования отпусков 563 Фасадный объект использует объект SDO как основной параметр, обращаясь к его методам создания, обновления и удаления (CRUD). Кроме того, он предусматривает метод для внесения любых изменений графа данных, принадлежащих объекту SDO. Как правило, этот фасадный объект используется другой сессией в качестве контроллера бизнес-логики, например, для запроса на заполнение Web-страницы. Рассмотрим простой сценарий, в рамках которого требуется обновить и создать категории запросов на отпуск. Ответственность за выполнение этой функции лежит на сотруднике отдела кадров. Для вывода на Web-странице такой контроллер бизнес-функции должен иметь доступ ко всем категориям (как правило, не менее десяти)6. Кроме того, пользователь должен иметь возможность выбирать категории для удаления или редактирования. Контроллер бизнес- логики может легко удалять категорию с помощью ссылки на компонент SDO или первичное ключевое значение. Изменение значений категории производится аналогично. Для этого достаточно изменить значения в компоненте SDO, а затем сообщить их фасадному объекту, чтобы он использовал свое локальное значение для обновления персистентной сущности в базе данных. Генерация первичного ключа Все реляционные объектные базы данных сталкиваются с проблемами, связанными с генерированием первичных ключей для компонентов-сущностей. Возможность использования естественных первичных ключевых значений, например, номеров карточек социального страхования или универсальных номеров продуктов (Universal Product Codes — UPC), сильно зависит от предметной области и не всегда существует. Это значит, что приложение должно определить и реализовать стратегию создания первичных ключей для новых сущностей, не имеющих естественных ключевых атрибутов. В нашей системе сущности класса Grant (Разрешение), Restriction (Ограничение) и Request (Запрос) представляют собой экземпляры бизнес-объектов, имеющих однозначные атрибуты, которые можно безопасно использовать в качестве первичных ключевых значений. В традиционных базах данных ключи можно создавать из нескольких компонентов и внешних ключевых значений. Однако большинство EBJ-проектов умеют более эффективно генерировать первичные ключевые значения элементарного типа, например, целые или строки. Это значит, что мы должны разработать стратегию создания первичных ключей для наших сущностей. В идеале, ту же самую стратегию и механизм можно использовать для всех типов сущностей, которые должны иметь ключи. произвольное использование методов get All Objects () в фасадных классах может привести к непредвиденным и серьезным проблемам, связанным с производительностью системы при ее тестировании в реальной ситуации. Достаточно представить себе стоимость записи в массив набора адресов всех клиентов средней по размеру компании.
564 Часть III. Приложения Для генерирования первичных ключей в нашем приложении мы выбрали стратегию Sequence Blocks, описанную в работе Маринеску (Marinescu) [5]. Эта стратегия реализует очень простой подход к созданию новых типов СМР-сущностей, ответственных за выбор следующего целого числа, которое можно использовать в качестве первичного ключа. Основным недостатком этого подхода является низкая производительность, особенно в системах, в которых сущности создаются часто. Эти проблемы разрешаются с помощью управляемого доступа к сущностям с помощью компонента сеанса, резервирующего за собой блок потенциальных ключевых значений. Таким образом, доступ к СМР-сущности, владеющей ключом, слегка ограничен, и степень этих ограничений зависит от размера зарезервированных ключей. Воплощение этой стратегии в системе приводит к созданию новой сущности и компонента сеанса, имеющего локальный доступ к другой сущности, представленной фасадным объектом (рис. 12.23). Компонент SequenceEntity имеет только два атрибута: имя последовательности (т.е. имя типа сущности, необходимое для генерирования первичного ключа) и следующее целочисленное значение, которое можно использовать в качестве первичного ключа. Поскольку эта стратегия резервирует блоки ключевых значений, вполне вероятно, что в последовательности целых чисел могут возникать пробелы. Таким образом, ни одно приложение, использующее эту стратегию, не должно использовать какие-либо предположения о порядке распределения первичных ключевых значений. «Session Bean» [£ SequenceSesston ©F SequenceSesston О SequenceSessionLocal • L getNextSequenceNumber () | CsequenceSessionLocalHome • 'create () CP SequenceSessionHome •H create () «EJB Local Reference» "ejb/SepuenceEntfcy" ~ ~ 5И «Entity Bean» @| SequenceEntity о ^SsequenceName: String о ® currentValue : int О SequenceEntityLocal • LgetCurrentValue() • LsetCurrentValue() • L get Value Aft etlncrementingBy () СГ SequenceEntityLocaHome • ■"createO • vfindByPrimaryKey () Cr SequenceEntity • RgetCurrentValue() • RsetCurrentValue() Cr SequenceEntityHome •H create () •H findByPrlmaryKey () Рис. 12.23. Компоненты сущности и сеанса, необходимые для генерирования первичных ключей При необходимости создать совершенно новый экземпляр сущности генератор ключей может использоваться другими фасадными объектами. Для этого необходимо модифицировать метод createCategory () для фасадного объекта, чтобы проверять входящий компонент SDO класса Category с нулевым полем id. Если поле id содержит нуль, то фасадный объект генерирует новый ключ для этой ка-
Глава 12. Web-приложение: система планирования отпусков 565 тегории. Невозможность сгенерировать новый ключ приводит к исключительной ситуации. Получить новый первичный ключ точно так же легко, как получить доступ к компоненту Sequence Session, а затем вызвать метод getNextSequen- се () с именем сущности в качестве параметра. Код метода createCategory приведен в листинге 12.2. Метод doAppl у Changes () является методом реализации компонентов SDO, а его код, вообще говоря, недоступен. Листинг 12.2. Код метода createCategory public void createCategory(Vategory data) throws CreateException { try { if ( data.getldO == null ) { InitialContext ctx = new InitialContext(); SequenceSessionLocalHome home = (SequenceSessionLocalHome) ctx. lookup (" java:comp/env/ejb/SequenceSessionfl) ; SequenceSessionLocal sequence = home.create(); int id = sequence.getNextSequenceNumber("Category"); data.setld( new Integer(id) ); } doApplyChanges(data) ; } catch (Exception ex) { throw new CreateException( "System error while creating \"Category\".", ex); } } Внеся такие изменения во все методы create фасадного объекта и используя компоненты SequenceSession и SequenceEntity, можно создать новые экземпляры сущностей, не прибегая к извлечению или вычислению требуемых первичных ключей каждого экземпляра (рис. 12.24). Методы поиска Еще одним важным вопросом, связанным с проектированием EJB-сущностей, является идентификация методов поиска. Эти методы предназначены для поиска конкретных экземпляров, соответствующих заданному набору критериев. Критерии могут быть простыми, и в таком случае им будут соответствовать все экземпляры запросов (обычно их список не превышает 12 пунктов). Кроме того, метод поиска может реализовать более сложные алгоритмы поиска, например, искать всех сотрудников, чьи запросы были отклонены за период с 1 марта по 23 июня предыдущего года. Независимо от деталей важно помнить, что фильтрация сущностей происходит на сервере, в идеале — на сервере базы данных.
566 Часть III. Приложения «Session Bean» Щ CategoryFacade V CategoryFacadeLocaNome • •create () С CategoryFacadeHome • Hcreate() Q CategoryFacadeRemote • " getAKategoryObjects () • RgetCategoryByKey() • R aeateCategory () • "updateCategoryO • "deleteCategory () • R applyCategoryRootChanges () • * getCategoryRoot () О CategoryFacadeLocal •L getAlCategoryObjectt () • lgetCategoryByKey() • L createCategory () • l updateCategoryO • ldeleteCategory О • L applyCategoryRootChanges () • l getCategoryRoot О Рис. 12.24. Компонент сессии CategoryFacade, использующий компонент SequenceSession для создания новых категорий Как правило, такой подход к поиску данных в крупной коллекции наиболее эффективен. Единственной альтернативой является получение всех сущностей из коллекции, их загрузка по линии связи и запуск другого процесса, перебирающего и сравнивающего загруженные сущности на компьютере клиента. Этот метод крайне неэффективен при поиске сущностей в больших коллекциях. Идея, лежащая в основе методов поиска, связана с оператором языка SQL SELECT. Методы поиска в компонентах EJB выражаются на другом языке — EJB Query Language (EJB QL), очень похожем на язык SQL, но не совпадающем с ним. Например, ниже приведена инструкция языка EJB QL, возвращающая все экземпляры сущности Grant, не связанные с какими-либо ограничениями. select object(о) from Grant о where о.restrictions is not empty Методы поиска могут иметь параметры. В следующем примере метод поиска запроса возвращает все экземпляры класса DateExclusionRestriction, за исключением запросов, поданных в конкретный день. Параметры в запросе отмечаются знаком вопроса, за которым следует индекс параметра в списке аргументов. select object(о) from Dare ExclusionRestriction o where о.date is ?1 Эти запросы указываются в основном конфигурационном файле компонента ЕЮ ejb-jar.xml и связанном с языком Java методом, который объявлен в домашнем интерфейсе. «EJB Local Reference» ejb/SequenceSesston Щ SequenceSession 0 SequenceSession G SequenceSesstonLocal • L oetNextSequenceNumber () CfSequenceSessionLocalHome • 'create () © SequenceSesstonHome • H create ()
Глава 12. Web-приложение: система планирования отпусков 567 Контроллеры Даже в Web-приложениях существует множество разных подходов к управлению бизнес-логикой. Многие Web-приложения используют подход "вид-представление-контроллер" (MVC). В настоящее время наиболее популярной рабочей средой для реализации этого подхода в J2EE Web-приложениях является программа Apache Struck. Эта среда содержит небольшой динамический компонент и набор библиотек JSP-дескрипторов для реализации пользовательского интерфейса и облегчения управления. В настоящее время широко используется шаблон проектирования MVC. Существует бесчисленное количество реализаций этого основного шаблона проектирования в контексте Web-приложений. Проектирование и реализация в среде Struts, по-видимому, является первой общепринятой реализацией этого шаблона в Web-приложениях, основанных на языке Java. Несмотря на то что применение парадигмы MVC для реализации яруса презентации вполне обоснованно, даже более внимательное изучение сценариев использования системы не позволяет ясно указать, в каком именно месте необходим контроль. В подавляющем большинстве сценариев использования от системы не требуется ничего больше, кроме операций CRUD (create (создать), read (прочитать), update (обновить), delete (удалить)), выполняемых над сущностями. Управление и координация сложных деловых операций (для некоторых из них хорошо подходит парадигма MVC) не входят в наше приложение. По этой причине архитектор системы решил не применять такую явную парадигму MVC, которая реализована в программе Struts. Вместо этого мы решили положиться на средства координации и управления, являющиеся частью Web-страниц. Некоторых архитекторов решение не использовать парадигму MVC и/или среду управления Struts может удивить, поскольку многие считают, что парадигма MVC неразрывно связана с разработкой Web-приложений. Однако мы рассматриваем использование промежуточного программного обеспечения, компонентов и даже стратегий, которые не являются необходимыми для успеха системы, не перечислены в документации и даже не планируются7. В соответствии с этим решением все управляющие конструкции должны содержаться либо в сессионных объектах EJB, в компонентах серверного яруса или должны быть встроены в дескрипторы на Web-страницах. Web-страницы и пользовательский интерфейс Проблемы, связанные с проектированием Web-страниц, разделяются на две основные части: 1) вопросы, касающиеся страниц как таковых, их гиперссылок, 7По той же причине некоторые читатели могут заинтересоваться, почему было принято решение адаптировать компоненты EJB для хранения персистентных сущностей, в то время как существуют намного более простые и эффективные стратегии. Это решение, как и многие решения в реальных проектах, в равной степени зависит от технических соображений и опыта проектировщиков.
568 Часть III. Приложения а также полей форм, и 2) структурные аспекты страниц. В первом случае архитекторы системы и информационной структуры сотрудничают друг с другом, чтобы точно определить, какие страницы необходимы, что на них должно быть показано, как осуществляется переход с одной страницы на другую и как все это способствует достижению основной цели, стоящей перед системой. Web-страницы, как правило, реализуются как JSP-страницы, содержащие смешанные данные и отношения с компонентами, реализующими бизнес-функции. В то же время вторая часть проблемы связана с эстетическими запросами пользователей и удобством работы. Схема Web-страницы определяет, где именно должна размещаться информация, а не какая информация должна появляться в этом месте. Основное внимание при разработке схемы уделяется организации страницы таким образом, чтобы ее содержание было понятным для конечного пользователя. Оставшаяся часть главы посвящена первой группе проблем, поскольку вторая часть связана скорее с искусством и визуальным творчеством, а не с анализом и проектированием. Проектирование Web-страницы начинается с создания UX-модели. Эта модель не просто описывает первичные варианты для выбора имени, содержания и связей Web-страницы. Вообще говоря, если страница не содержит динамических элементов, то UX-классы «screen» могут быть частью Web-приложения. Однако и в этих ситуациях более предпочтительными являются JSP-страницы, поскольку некоторые программы на клиентской стороне приложения требуют динамического обновления гиперссылок URL, которые способны осуществить только динамические страницы (см. врезку "Управление состоянием клиента"). В зависимости от инструментов, использованных при создании Web-страницы, UX-модель легко трансформировать в схему сайта или модель проектируемой системы (рис. 12.25), в которой элементы «screen» отображаются в JSP- страницы, а карта ассоциаций — в навигационные ссылки, представляющие собой либо простые гиперссылки, либо формы, в которые пользователь вводит дополнительные данные. Request Editor + %&& reqed.jsp(/VTSW... VTS Home Page vtshome.jsp(/VT... Cancel Confirmation cancelConfirm.jsp... Withdraw Confirm... ♦ *>&& withdrawConfirm.... Рис. 12.25. Схема сайта Проектируя ярус презентации, необходимо иметь в виду следующее: 1) как заполняется динамическое содержание страницы и 2) как вызываются бизнес- функции при переходе между страницами. В нашем случае в качестве архитек-
Глава 12. Web-приложение: система планирования отпусков 569 туры приложения выбрана платформа J2EE, и архитектор решил использовать компоненты JSF, позволяющие легко решить поставленные задачи. Компоненты JSF упрощают создание динамических Web-страниц. Они определяют количество пользовательских дескрипторов HTML, встроенных в JSP-страницу и используемых для вызова функций из объектов, реализующих бизнес-логику, а также для извлечения данных с последующим отображением на экране клиента. Кроме дескрипторов JSF библиотека JSTL (Java Server Pages Standard Template Library) предоставляет в распоряжение проектировщиков большое количество полезных дескрипторов, позволяющих обрабатывать данные на JSP-страницах. Заполнение динамического содержания Заполнение Web-страниц с динамическим содержанием требует наличия связи между Java-компонентом сессии на ярусе презентации и компонентом сессии на деловом ярусе. Эта связь должна быть определена как дистанционная ссылка, чтобы существовала потенциальная возможность разделить ярусы по разным узлам. Для того чтобы заполнить домашнюю страницу системы VTS, помимо прочей информации, необходимо знать текущие данные о запросах сотрудника. Эти данные приходят от СМР-компонента Employee и связанных с ним СМР-компонентов Request. Поскольку доступ к СМР-компонентам управляется сгенерированными фасадными объектами, компонент сессии на ярусе презентации должен иметь дистанционную ссылку на фасадный объект. Этот объект вернет объекты SDO компоненту сессии на ярусе презентации, который, в свою очередь, обработает их и создаст простой Java-объект, который можно будет непосредственно использовать в компоненте JSP. Как показано на рис. 12.26, класс EmployeeSummarySession представляет собой сессионный компонент, работающий на ярусе презентации. Его основная задача — обеспечивать связь с объектами EmployeeFacade и создавать резюме запросов объектов Employee. Этот сессионный компонент будет также собирать и предоставлять другим информацию о сотруднике, которая используется на домашней странице системы VTS. Класс EmployeeSummary и его открытый внутренний класс RequestSummary являются классами РОЮ, используемыми на страницах JSP с помощью дескрипторов JSTL и JSF. Фрагмент кода JSP для домашней страницы системы VTS показан на листинге 12.3. Домашняя страница VTS, как и все JSP-страницы в нашем приложении, использует большое количество специальных дескрипторов из разных библиотек дескрипторов. Основными являются JSF-дескрипторы, JSF HTML-дескрипторы и JSTL-дескрипторы. Они импортируются и связываются с префиксными идентификаторами в начале источника JSP.
570 Часть III. Приложения «Jav.i Class» Θ VtsHomeAction f · YteHomeActionT) • getErnptoyeeSummary () • action () • submit () __ «Session Bean» tfi EmployeeSummarySession ~CF BmployeeSurrrnarysWonHome • H create () 0 EmpbyeeSumrnarySesslon • я oetSummary () «EJB Remote Reference» eJb/EmployeeFacade «Javattass» Θ EmpbyeeSumrnay 'o~tofaFibursTlnt requertSummary: RequestSumrnary • getTotaNourTnn • getRequestSummary () _ ^'^:,«^Ша%»1* ' "**' ORequestSummay о title: String о date : String a type: String a etatue: String • getDate () • getStatuB () • get Title () • getType () «Session Bean» Oi EmployeeFacade IS EmployeeFacadeLocal • L getAIEmployeeObjects [) • LgetEmployeeByKey() •l createEmptoyee () •l updateEmployee () • LdeleteEmpbyee() • L applyErnptoyeeRootChanges (} • L getEmployeeRoot () 0 EmployeeFacadeRemote • " getAHEmployeeObJects () • "getEmpbyeeByKeyO • R createEmptoyee () • R updateEmployee () • "deleteEmployeeO • R applyEmployeeRootChanges () • R getEmployeeRoot () CF EmployeeFacadeLocalHome • •create () C9 EmployeeFacadeHome • H create () 1 ^titySean» * ©Employee j^iPTdTinteger ° ®ii?Tie-:^r!n0 Cf EmployeeLocal • lgetName() • lsetName() • lgetRequest() • LsetRequest() • LgetGrant () • lsetGrant() • lgetLocation() • Lsetl_ocation() СГ EmpbyeeLocalHome • 'createO • "•flndByPrimaiyKey () + request н employee "*щ «entity Bean» ©Request o^FTTnteger о ® title : String о ® comments : String о ® hours: mt date: Date Cf RequeetLocalHome • ""create () • *findByPrimaryKey () О RequestLocal • lgetTltle() • ••setTltleO •l getComments () •l setComments () • LgetHours() • LsetHouts() • l getDate () • LsetDate() • LgetEmployee() • L6etEmployee( ) • lgetGrant() • lsetGranti) Рис. 12.26. Элементы проекта на ярусе презентации и деловом ярусе Листинг 12.3. Код JSP для домашней страницы системы VTS <HTML> <HEAD> <%@ taglib uri="http://Java.sun.com/jsp/jstl/core" prefix= ,c"%> <%@ taglib uri="http://Java.sun.com/jsf/core" prefix="f"%> <%@ taglib uri="http://Java.sun.com/jsf/html" prefix="h"%> <%@ page language="java" contentType="text/html; charset=ISO-8859-l" pageEncoding="ISO-8859-l"%> <jsp:useBean id="vtsHome" class="vtsweb.actions.VtsHomeAction"/> <TITLE>VTS Home Page</TITLE> </HEAD> <f:view> <BODY> <P>Request Summary</P>
Глава 12. Web-приложение: система планирования отпусков 571 <с:forEach items="${vtsHome.employeeSummary}"> <c:url var="delUrl" value="faces/reqedf,> <c:param name="id" value="${leaveRequest.id}" /> <c:param name="action" value="delete" /> </c:url> <c:url var="edUrl" value="faces/reqed"> <c:param name="id" value="${leaveRequest.id}" /> <c:param name="actionM value="edit" /> </c:url> <tr> <td>${leaveRequest.date}</td> <td>${leaveRequest.type}</td> <td>${leaveRequest.status}</td> <td><a href=M${delUrl}">delete</a></td> <td><a href="${edUrl}">edit</a></td> </tr> </c:forEach> <PXBR>Outstanding Grants</P> </BODY> </f:view> </HTML> Дескриптор JSP используется для ссылки на компонент яруса презентации, который, в свою очередь, открывает доступ к бизнес-функциям и действует как локальный контроллер, управляющий действиями на данной странице. Этот компонент реализуется как объекты POJO. Доступ к нему обеспечивается в контексте JSP с помощью локальной ссылки vtsHome. <jsp:useBean id="vtsHome" class= "vtsweb.actions.VtsHomeAction"/> Этот компонент можно использовать в специальных дескрипторах JSF и JSTL, чтобы извлекать деловые данные и вызывать бизнес-методы. В нашем примере дескриптор JSTL f orEach перебирает коллекцию компонентов employeeSummary, содержащую экземпляры объектов RequestSummary, каждый из которых представляет собой конкретный запрос на отпуск. В целом, было бы правильно изолировать код JSP и логику от реальных компонентов EJB с помощью простого объекта компонента, который можно было бы связать с конкретной страницей. Этот объект отвечает за организацию и доступ ко всем дискретным значениям, размещенным в компоненте JSP. Благодаря этому, можно относительно легко разработать окончательную схему страницы,
572 Часть III. Приложения поскольку в этом случае проектировщики могут не беспокоиться о технических подробностях управления компонентами EJB. Вызов бизнес-функций В Web-приложениях основная работа выполняется путем перехода со страницы на страницу. Просматривая следующую страницу, пользователь выбирает ветки логической схемы приложения. Следующая страница может оказаться именно той страницей, которую желал видеть пользователь, или другой. В зависимости от бизнес-логики желательная страница переключается на другую страницу в зависимости от текущего состояния клиента. Например, если пользователь подал запрос на отпуск, но забыл заполнить требуемые поля, система не вернет его на домашнюю страницу, как можно было бы ожидать, а вернет его на страницу редактирования и, скорее всего, выдаст предупреждение, требуя ввести правильную информацию. В приложении JSF пути переходов определяются конфигурационным файлом, который называется f aces-conf ig. xml. Этот файл, помимо всех прочих, определяет управляемый компонент, на который можно ссылаться на JSP-странице (например, VtsHomeAction). Навигационное правило определяет допустимые переходы с одной страницы на другую в зависимости от результирующего значения. Это значение вычисляется в одном из управляемых компонентов, а после возвращения среда faces будет использовать его для определения загружаемой страницы. Правило навигации, указанное в файле f aces-conf ig. xml, приведено на листинге 12.4. Листинг 12.4. Правило навигации в файле f aces-conf ig. xml <navigation-rule> <from-view-id>/reqed.j sp</from-view-id> <navigation-case> <from-outcome>failure</from-outcome> <to-view-id>/reqed.jsp</to-view-id> </navigation-case> <navigation-case> <from-outcome>success</from-outcome> <to-view-id>/vtshome.j sp</to-view-id> </navigation-case> </navigation-rule> Правило, сформулированное в листинге 12.4, утверждает, что когда активизируется компонент кнопки или гиперссылки на reqed. j sp, приложение перейдет со страницы reqed. j sp на страницу vtshome. j sp, если с дескриптором кнопки или гиперссылки связан результат success. В противном случае приложение возвращает страницу reqed. j sp.
Глава 12. Web-приложение: система планирования отпусков 573 Гиперссылки или кнопки форм размещаются на исходной странице вместе с дескрипторами JSF HTML. В следующем примере, описывающем работу кнопки, щелчок на кнопке приводит к вызову метода submit (), принадлежащего экземпляру vtsHomeAction, поскольку атрибут action ссылается на метод submit, принадлежащий возвращаемому компоненту VtsHomeAction. Метод submit () выполняет определенную работу и возвращает логическое значение, которое передается обработчику навигации, заданному по умолчанию. Этот обработчик сравнивает результат с набором навигационных правил, определенных в конфигурационном файле. <h:commandButton value="Submit Changes" action>"#{vtsHome.submit}"/> В результате вся логика яруса презентации выражается в управляемых или возвращаемых компонентах, которые выполняются на Web-сервере. Эти компоненты выполняют свои задачи, создавая обычные дистанционные EJB-ссылки на компоненты EJB, находящиеся на деловом ярусе. Это может привести к запуску другого узла системы. 12.4 Внедрение и эксплуатация Помимо обычных проблем, связанных с функциональностью и производительностью, Web-ориентированные архитектуры, особенно использующие Интернет, порождают множество специфических проблем, касающихся их реализации и тестирования. По своей природе Web-приложения существуют в неоднородной среде, которая постоянно изменяется. Точную конфигурацию клиентского аппаратного и программного обеспечения определить невозможно. Для того чтобы облегчить решение этих проблем, при проектировании системы VTS специальные технологии, использующие браузеры, были сознательно отклонены. Реализация Web-приложения по существу представляет собой разработку серверного программного обеспечения. Практически все программное обеспечение в типичном Web-приложении выполняется на серверной стороне. Разработчик должен интересоваться конфигурацией клиентского аппаратного и программного обеспечения, только если на клиентском компьютере допускается выполнение сценариев JavaScript или специализированных аплетов. Даже если вы решили применить технологии, официально поддерживающие последние версии наиболее популярных браузеров, нет никакой гарантии, что они будут одинаково эффективно работать на любых конфигурациях клиента. Эти технологии перечислены в следующем списке. • Java Script. Все браузеры по-разному реализуют сценарии на клиентской стороне. Одни браузеры дополняют язык сценариев собственными свой-
574 Часть III. Приложения ствами, другие интерпретируют спецификации не совсем точно и допускают необычные побочные эффекты, не указанные в официальных спецификациях. • Style Sheets. Таблицы стилей (style sheets) и другие функциональные свойства, касающиеся схем страницы, зависят от доступности шрифтов и размера экрана. Использование таблиц стилей не гарантирует, что страницы правильно отразятся на компьютерах клиента любой конфигурации. • Фреймы. Реализация фреймов с самого начала оказалась проблематичной. Прокрутка экрана, изменение его размера и выделение объектов постоянно создает проблемы при использовании фреймов. Если в приложении используются фреймы, то их следует тестировать в полной мере: не только для конкретных клиентских конфигураций, но и в рамках сценариев, выходящих за пределы обычного использования системы. • Широта пропускания. По мере усложнения инструментов проектирования и Web-страниц возрастает вероятность того, что некоторые конечные пользователи столкнутся с чрезвычайно медленными переходами со страницы на страницу из-за большого объема HTML-кода и/или объема сценария, который должен быть выполнен на клиентском компьютере. Если разрабатываемое приложение должно быть развернуто на анонимной платформе в сети Интернет, необходимо уделить особенное внимание тестированию и проектированию страниц для компьютеров, имеющих низкую пропускную способность и слабую конфигурацию. По мере совершенствования технологий этот список проблем постоянно уве-
ПРИЛОЖЕНИЕ А ОБЪЕКТНО-ОРИЕНТИРОВАННЫЕ ЯЗЫКИ ПРОГРАММИРОВАНИЯ Использование объектно-ориентированной технологии не ограничивается каким-то конкретным языком программирования. Она реализуется во многих объектных и объектно-ориентированных языках. Однако программирование является не менее важным аспектом, чем анализ и проектирование. Нельзя пренебрегать деталями кодирования, поскольку в конце концов архитектурные особенности систем должны быть выражены с помощью какого-то конкретного языка программирования. Как полагает Вульф (Wulf) [1], язык программирования служит трем целям. • Это инструмент проектирования. • Это средство выражения идей программиста. • Это инструмент для записи команд, управляющих компьютером. Приложение предназначено для читателей, возможно, не знакомых с объектно- ориентированными языками программирования, упоминавшимися в книге. Оно содержит краткое описание наиболее важных и популярных из них. Кроме того, в нем описаны примеры, позволяющие сравнить синтаксис, семантику и идиомы наиболее распространенных объектно-ориентированных языков программирования — Smalltalk, C++ и Java. Эволюция языков программирования В настоящее время существуют более 2 500 разных языков программирования высокого уровня [2]. Это разнообразие объясняется тем, что каждый из этих языков разрабатывался для использования в определенных предметных областях. Более того, появление очередного нового языка программирования позволяет раз-
576 Приложение А. Объектно-ориентированные языки программирования работникам приступить к решению все более и более сложных задач. Исследуя ранее не изученные области применения, разработчики языков получили возможность уточнить свои представления о том, что важно для языка программирования, а что нет. Кроме того, на эволюцию языков программирования значительное влияние оказали достижения теории вычислений, которые позволили формализовать семантику операторов, модулей, абстрактных типов данных и процессов. Как указано в главе 2, языки программирования реализуют разные абстракции: математические, алгоритмические, информационно-ориентированные и объектно-ориентированные. Самые последние достижения в области разработки языков программирования связаны с объектной моделью. Кроме того, как отмечалось в главе 2, объектными считаются языки программирования, непосредственно обеспечивающие абстракцию данных и создание классов, а объектно-ориентированные — это объектные языки, поддерживающие наследование и полиморфизм. Общим предком почти всех современных объектных и объектно-ориентированных языков является язык Simula, разработанный в 1960-х годах Даалем (Dahl), Мирхургом (Myrhurg) и Нигардом (Nygard) [3]. Язык Simula развил идеи языка ALGOL, дополнив их концепцией инкапсуляции и наследования. Вероятно, наиболее важным обстоятельством является то, что язык Simula, предназначенный для моделирования и описания систем, заложил правила написания программ, отражающие словарь изучаемой предметной области. Генеалогия наиболее важных и распространенных объектных и объектно-ориентированных языков программирования продемонстрирована на рис. АЛ, заимствованном с Web-сайта Эрика Левенеца (Eric Levenez), посвященного истории языков программирования [4]. Величина прямоугольника отражает интенсивность разработки или использования языков в общей предметной области, а стрелочки изображают влияние, которое языки оказывали на разработку других языков. Определение распространенности того или иного языка программирования или даже семейства языков программирования представляет собой трудную задачу, которая в одинаковой степени должна учитывать эмоциональные оценки своих приверженцев и рутинные статистические данные. Сама по себе популярность того или иного языка программирования ничего не говорит о его качестве. Она лишь является свидетельством его эффективности и доступности. Одним из новаторских способов оценки популярности языков программирования является индекс программистского сообщества ТЮВЕ (TCP-Index) [5]. Он основан на сканировании Web-страниц и групп новостей в сети Интернет. Используя простые запросы, касающиеся исследуемого языка программирования, можно определить процентную долю Web-страниц, представляющих интерес, и сравнить эти результаты с данными, полученными ранее, по месяцам и годам. В табл. АЛ приведены наиболее свежие результаты исследования, полученные к моменту написания книги. Как видим, в первом десятке языков доминируют объектно-ориентированные языки, хотя ведущее место занимает процедурный язык С.
Приложение А. Объектно-ориентированные языки программирования 577 4 РНР Perl 4 Python С with Classes Й Δ Pascal Simula Δ C++ Δ <Δ Oak 4 Δ c# Java Objective С Smalltalk Δ Δ Δ Delphi Turbo Pascal ObjectPascal Ada ALGOL ts Basic VisualBasic Рис. АЛ. Генеалогия наиболее важных языков программирования В следующих разделах мы кратко опишем наиболее важные объектно-ориентированные языки программирования. Приведенные фрагменты программ предназначены для решения простой задачи: описания формы окна. В этих программах классы описывают разные типы фигур, которые могут быть выведены на дисплей. Обобщенная UML-модель этих классов приведена на рис. А.2.
578 Приложение А. Объектно-ориентированные языки программирования Таблица АЛ. Результаты определения популярности современных языков программирования Место Ϊ 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 Язык ~С Java Perl C++ PHP (Visual) Basic Delphy/Kylix Python C# SQL JavaScript COBOL IDL SAS Lisp Fortran MATLAB Ada Pascal AWK Рейтинг, % 19^37 18,57 10,37 9,72 7,97 6,78 2,89 2,80 2,78 2,65 1,39 1,38 1,23 1,09 0,86 0,82 0,78 0,68 0,49 0,48 Язык программирования Smalltalk Язык Smalltalk был разработан членами исследовательской группы Xerox Palo Alto Research Center Learning Research Group как элемент утопического проекта Dynabook, предложенного Аланом Кэем (Alan Kay). Основное влияние на этот проект оказали идеи языка программирования Simula, хотя в определенной степени в нем использовались принципы языка FLEX, а также результаты работ Сеймура Пэперта (Seymore Papert) и Уаллеса Фойрзайга (Wallace Feurzeig). Smalltalk представляет собой и язык программирования, и среду разработки программ. Он является чисто объектно-ориентированным языком программирования, в котором абсолютно все сущности считаются объектами. Даже целые числа в языке Smalltalk представляют собой классы. Наряду с языком Simula язык Smalltalk является, вероятно, важнейшим объектно-ориентированным языком программирования, поскольку его идеи оказали влияние не только на практически все после-
Приложение А. Объектно-ориентированные языки программирования 579 Point | г • Г + + Г + к: int I у: int PointQ I getxo setXQ 9®tY0 setYQ Ж SolidRectangle + drawQ Рис. А.2. Обобщенная UML-диаграмма класса для каждого примера дующие языки программирования (хотя сам Smalltalk теперь используется редко), но и легли в основу современных графических интерфейсов пользователя, таких как Macintosh, Windows, Motif, KDE и Gnome, получивших общее признание. Работа над языком Smalltalk продолжалась почти десять лет. Большую часть этого времени главным архитектором проекта был Дэн Ингалс (Dan Ingalls), но наряду с ним полезный вклад внесли также Питер Дейч (Peter Deutsh), Гленн Краснер (Glenn Krasner) и Ким МакКолл (Kim McCall). Параллельная группа, состоявшая из Джеймса Альтхофа (James Althoff), Роберта Флегала (Robert Flegal), Неда Келера (Ned Kaehler), Дианы Мерри (Diana Merry) и Стива Паца (Steve Putz), разрабатывала среду программирования Smalltalk. Наряду с остальными важными обязанностями, Адель Голдберг (Adele Goldberg) и Дэвид Робсон (David Robson) вели летопись проекта. Существуют пять версий этого языка: Smalltalk-72, 74, 76, 78, 80. Версии Smalltalk-72 и 74 не поддерживали наследование, но реализовывали большинство Shape center: Point + getCenterQ + setCenterQ Circle radius: int drawQ 1+ getRadiusO I + setRadiusQ Rectangle - height: int - width: int + dravyQ + getHelghtQ + eetHeightO + getWidthft + setWidth|
580 Приложение А. Объектно-ориентированные языки программирования основных концепций, в частности, механизм передачи сообщений и полиморфизм. В последующих версиях на первый план вышли классы. Это свидетельствовало о победе точки зрения, что все сущности в среде программирования должны рассматриваться как объекты. В настоящее время существует около 20 разных реализаций языка Smalltalk [6], большинство из которых представляют собой вариант языка Simula-80 для конкретной платформы (аппаратного и программного обеспечения). Несмотря на то что пользовательский интерфейс в этих реализациях, как правило, отличается от других, библиотеки классов и общие функциональные свойства во всех версиях практически совпадают. Обзор Ингалс (Ingalls) утверждает следующее: "Цель проекта Smalltalk — поддержать детей любого возраста в мире информации. Основная проблема заключается в том, чтобы найти и применить достаточно простые и яркие метафоры, позволяющие человеку получить доступ к информации и свободно оперировать ею, причем эта информация может быть самой разнообразной — от чисел и текста до звуковых файлов и картинок" [7]. В основе языка лежат две простые идеи: 1) все сущности считаются объектами, и 2) объекты взаимодействуют с помощью обмена сообщениями. Характеристики языка Smalltalk с точки зрения семи основных элементов объектной модели приведены в табл. А.2. Несмотря на то что в таблице это не указано, множественное наследование может быть реализовано с помощью переопределения некоторых элементарных методов [8]. Пример Рассмотрим пример, в котором существует список разных фигур, каждая из которых может быть окружностью, прямоугольником или закрашенным прямоугольником. В языке Smalltalk предусмотрена большая библиотека классов для окружностей и прямоугольников, поэтому решение поставленной задачи является весьма простым. Оно демонстрирует важность повторного использования кода. Однако для сравнения предположим, что имеются только классы-примитивы для рисования линий и дуг. Определим класс AShape следующим образом. Object subclass: #AShape instanceVariableNames: 'theCenter' classVariableNames: '' poolDictionaries: '' category: 'Appendix' initialize "Initialize the shape" thisCenter := Point new
Приложение А. Объектно-ориентированные языки программирования 581 Таблица А.2. Объектно-ориентированные свойства языка Smalltalk Элементы Свойство Включено? объектной модели Абстракция Переменные экземпляра Да Методы экземпляра Да Переменные класса Да Методы класса Да Инкапсуляция Модульность Иерархия Типизация Параллельность Персистентность Переменных Методов Виды моделей Наследование Шаблоны Метаклассы Строгая типизация Полиморфизм Многозадачность Персистентные объекты Закрытая Открытая Нет Одиночное Нет Да Нет Да (одиночный) Косвенная (с помощью классов) Нет setCenter: aPoint "Set the center of the shape" theCenter := aPoint center "Return the center of the shape" AtheCenter draw "Draw the shape" self subclassResponsibility Теперь определим подкласс ACircle. AShape subclass #ACircle instanceVariableNames: 'theRadius' classVariableNames: '' poolDictionaries: '' category: 'Appendix' setRadius: anlnteger
582 Приложение А. Объектно-ориентированные языки программирован "Set the radius of the circle" theRadius := anlnteger radius "Return the radius of the circle" AtheRadius draw "Draw the circle" I anArc index | anArc := Arc new. Index := 1. [index <= 4] whileTrue: [anArc center: theCenter radius: theRadius quadrant : index. anArc display. Index := index + 1] Далее, определим подкласс Arectangle. AShape subclass: #ARectangle instanceVariableNames: 'theHeight theWidth' classVariableNames: '' poolDictionaries: '' category: 'Appendix' draw "Draw the rectangle" I aLine upperLeftCorner | aLine := Line new. upperLeftCorner := theCenter χ — (theWidth /2) @ (theCenter у — (theHeight /2)). aLine beginPoint: upperLeftCorner aLine endPoint: upperLeftCorner χ + theWidth @ upperLeftCorner y. aLine display. aLine beginPoint: aLine endpoint. aLine endpoint: upperLeftCorner χ + theWidth @ (upperLeftCorner у + theHeight). aLine display. aLine beginPoint: aLine endPoint.
Приложение А. Объектно-ориентированные языки программирования 583 aLine endPoint: upperLeftCorner χ @ (upperLeftCorner у + theHeight). aLine display. aLine beginPoint: aLine endPoint. aLine endPoint: upperLeftCorner. aLine display. setHeight: anlnteger "Set the height of the rectangle" theHeight := anlnteger setWidth: anlnteger "Set the width of the rectangle" theWidth := anlnteger height "Return the height of the rectangle" AtheHeight width "Return the width of the rectangle" AtheWidth И наконец, определим подкласс ASolidRectangle. ARectangle subclass #ASolidRectangle instanceVariableNames: '' classVariableNames: '' poolDictionaries: '' category: 'Appendix' draw "Draw the rectangle" I upperLeftCorner lowerRightCorner | super draw. upperLeftCorner := theCenter χ - (theWidth quo: 2) + 1 @ (theCenter у - (theHeight quo: 2) + 1). lowerRightCorner := upperLeftCorner χ + theWidth - 1@ (upperLeftCorner у + theHeight - 1). Display fill: (upperLeftCorner corner: lowerRightCorner) mask: Form gray
584 Приложение А. Объектно-ориентированные языки программирования Ссылки В настоящее время основным руководством по языку Smalltalk является стандарт ANSI: Programming Language Smalltalk [20]. К другим источникам информации, заслуживающим внимания, относятся следующие книги: Гольдберг (Goldberg), Робсон (Robson), Smalltalk-80: Language [9], Гольдберг, Smalltalk-80: The Interactive Programming Environment [10], Краснер (Krasner) Smalltalk-80: Bits of History, Words of Advice [11]. Глубокое исследование языка Smalltalk-80, включая библиотеки классов и приложения, приведено также в работе Лалонде (LaLonde) и Пуга (Pugh) [12]. Язык программирования C++ Язык программирования C++ разработал сотрудник компании AT&T Bell Laboratories Бьерн Страуструп (Bjarne Stroustrup). Непосредственным предшественником C++ является язык С with Classes, созданный Страуструпом в 1980 году. В свою очередь, язык С with Classes испытывал сильное влияние языков С и Simula. В значительной степени язык C++ представляет собой расширение языка С. Однако в некотором смысле язык C++ лучше языка С. В частности, он обеспечивает контроль типов, перегрузку функций и ряд других усовершенствований. И все же самое главное — это то, что язык C++ добавляет к языку С объектно- ориентированные свойства. Ранние технологии трансляции программ, написанных на языке C++, использовали препроцессор cfront языка С. Поскольку в качестве промежуточного кода препроцессор cfront генерировал программы на языке С, он позволил достаточно быстро перенести язык C++ практически на все UNIX-системы. В настоящее время почти на всех платформах существуют коммерческие трансляторы и интерпретаторы языка C++, которые могут настраиваться практически на любую архитектуру компьютеров. Существовало несколько основных версий C++. Версия 1.0 дополнила язык С механизмами объектно-ориентированного программирования, например, одиночным наследованием и полиморфизмом, а также проверкой типов и перегрузкой функций. Версия 2.0, выпущенная в 1989 году, представляла собой улучшенную версию своей предшественницы (в частности, в этой версии было реализовало множественное наследование). Она возникла в результате обобщения опыта широкого применения языка C++ довольно крупным сообществом пользователей. В версии 3.0, появившейся в 1990 году, были предусмотрены шаблоны (параметризованные классы) и обработка исключений. Комитет ANSI X3J16 C++ одобрил предложения по управлению пространствами имен (согласованные с нашим понятием категории классов), а также идентификации типов во время выполнения программ. Кроме того, язык C++ был стандартизован Британским институтом стандартов (BTI — British Standards Institute), Организацией национальных
Приложение А. Объектно-ориентированные языки программирования 585 стандартов Германии (German national standards organization — DIN) и Организацией международных стандартов (International Standards Organization — IOS). Окончательный вариант стандарта ISO был принят в 1997 году и ратифицирован в августе 1998 года. В настоящее время основным институтом, отвечающим за поддержку стандарта языка C++, является организация ISO. Обзор Страуструп утверждает: "Язык C++ создавался в основном для того, чтобы избавить автора и его друзей от необходимости программировать на ассемблере, языке С или других современных языках высокого уровня. Его главное предназначение — облегчать создание хороших программ и приносить программисту большее удовольствие. Бумажной версии языка C++ никогда не существовало. Его проектирование, документирование и реализация осуществлялись одновременно" [13]. Язык C++ исправил многие недостатки языка С. В нем предусмотрены описания классов, проверка типов, перегрузка, управление динамической памятью, постоянные типы, ссылки, встраиваемые функции, производные классы и виртуальные функции [14]. Характеристики языка C++ с точки зрения семи основных элементов объектного подхода приведены в табл. А.З. Таблица А.З. Объектно-ориентированные свойства языка C++ Элементы объектной модели Абстракция Инкапсуляция Модульность Иерархия Типизация Параллельность Свойство Переменные экземпляра Методы экземпляра Переменные класса Методы класса Переменных Методов Виды моделей Наследование Шаблоны Метаклассы Строгая типизация Полиморфизм Многозадачность Включено? Да Да Да Да Закрытая, защищенная, закрытая Открытая, защищенная, закрытая Файл Множественное Да Нет Да Да (одиночный) Косвенная (с помощью классов) Персистентность Персистентные объекты Нет
586 Приложение А. Объектно-ориентированные языки программирования Пример Вернемся к задаче определения фигур. В C++ принято размещать интерфейсную часть классов в заголовочных файлах. Следуя этому правилу, мы можем написать следующий фрагмент программы. struct point { int x; int у; }; class Shape { public: Shape(); void setCenter(Point p); virtual void draw() =0; Point center() const; private: Point theCenter; }; class Circle : public Shape { public: Circle(); void setRadius(int r) ; virtual void draw(); int radius() const; private: int theRadius; }; class Rectangle : public Shape { public: Rectangle(); void setHeight(int h); void setWidth(int w); virtual void draw(); int height() conat; int width() const; private: int theHeigh; int theWidth; }; class SolidRectangle : public Rectangle { public: virtual void draw(); };
Приложение А. Объектно-ориентированные языки программирования 587 Определение C++ не содержит библиотеку классов. Для простоты предположим, что существует программный интерфейс с обобщенным графическим дисплеем (например, X Windows или Microsoft Windows), а также глобальные объекты Display, Window и GraphicsContext. Теперь можно завершить разработку, написав в отдельном файле реализацию методов, перечисленных выше. Shape::Shape() { theCenter.x = 0; theCenter.y = 0; }/ void Shape:rgetCenter(Point p) { theCenter = p; }; Point Shape::center() const { return theCenter; }; Circle::Circle() : theRadius(O) { }; void Circle: :setRadius( int r) { theRadius = r; }; void Circle::draw() { int χ = (center().x - theRadius); int у = (center().y - theRadius); XDrawArc(Display, Window, GraphicsContext, x, y, (theRadius 2), (theRadius * 2), 0, (360 64)); }; int Circle::radius() const { return theRadius; }; Rectangle::Rectangle() : theHeight(0), theWidth(O) { }; void Rectangle::setHeight( int h) {
588 Приложение А. Объектно-ориентированные языки программирования theHeight = h; }; void Rectangle::setWidth( int w) { theWidth = w; }; void Rectangle::draw() { int χ = (center().x - (theWidth / 2)); int у = (center().у - (theHeight / 2)); XDrawRectangle(Display, Window, GraphicsContext, x, y, thewidth, theHeight); }; int Rectangle::height() const { return theHeight; }; int Rectangle::width() const { return thewidth; }/ void SolidRectangle::draw() { Rectangle::draw(); int χ - (center().x - (width() / 2)); int у - (center().у - (height() / 2)); gc oldGraphicsContext = GraphicsContext; XSetForeground(Display, GraphicsContext, Gray); XDrawFilled(Display, Window, GraphicsContext, x, y, width(), height()); GraphicsContext = OldGraphicsContext; }; Ссылки Наиболее популярным источником информации по языку C++ является справочник Эллиса (Ellis) и Страуструпа Annotated C++ Reference Manual [15]. Наиболее свежее описание языка C++ можно найти в книге Страуструпа The C++ Standard: Incorporating Technical Corrigendum No. 1 [16]. Страуструп подробно описал язык и методы его использования в контексте объектно-ориентированного проектирования в книгах [17, 18].
Приложение А. Объектно-ориентированные языки программирования 589 Язык программирования Java Выяснив, что с помощью языка C++ очень трудно решить некоторые задачи, Джеймс Гослинг (James Gosling) и его немногочисленные коллеги, работавшие в компании Sim Microsystems, создали компактный язык программирования под названием Oak. Перед группой Джеймса Гослинга стояла задача разработать программное обеспечение для бытовых приборов с цифровым управлением, например, электронных игрушек и микроволновых печей. После того как попытки внедрить эту технологию на рынке цифрового кабельного телевидения провалились, разработчики поняли, что наилучшая сфера для приложения их усилий — сеть Интернет. Авторы переименовали язык Oak в язык Java и стали позиционировать его как язык программирования общего назначения, интерпретаторы которого легко загрузить через сеть Интернет и выполнить в контексте браузеров HTML. Решающий прорыв языка Java на рынок произошел в 1995 году, когда компании Sun Microsystems и Netscape сообщили, что они планируют инкорпорировать технологию Java в программу Netscape Navigator, наиболее популярный браузер того времени. Сообщение сразу привело к созданию огромного рынка потенциальных пользователей этой технологии. Ранние маркетинговые попытки были сосредоточены на применении технологии Java в сети Интернет, причем основной акцент делался на ее независимости от компьютерной платформы. Однако именно серверное использование вывело язык Java на роль одного из наиболее предпочтительных объектно-ориентированных языков. Поскольку графическая реализация языка Java всегда была предметом критики, в настоящее время большинство разработчиков приложений на языке Java используют его серверную часть (т.е. компоненты, не содержащие графики), стремясь обеспечить функциональность Web-страниц и оболочек для управления коммерцией. Несмотря на то что язык Java появился немногим более десятка лет назад, его успех является феноменальным со всех точек зрения. Рост его популярности объясняется не только совершенствованием самого языка, но и, что еще более важно, появлением тесно связанных с ним технологий: Enterprise Java Beans (EJB), Java Server Pages (JSP) и Java 2 Micro Edition (J2ME). В настоящее время технология Java и ее стандарты продолжают быстро развиваться. В 1998 году компания Sun организовала процесс Java Community Process (JCP). В рамках этого процесса компания управляет развитием языка, а также пересматривает спецификации технологии Java, содержание справочников и тестовые примеры. В рамках этого процесса компания пытается выяснить, как программистское сообщество оценивает документ Java Specification Request (JSR), регламентирующий правила создания следующих спецификаций и пересмотр существующих. В настоящее время рассматриваются более ста разных спецификаций языка Java.
590 Приложение А. Объектно-ориентированные языки программирования Компания Sun Microsystems продолжает управлять развитием языка Java и связанных с ним технологий. Обзор Технология Java — это не просто язык программирования. Как и язык Smalltalk, она одновременно является и средой программирования, и языком. Технология Java основана на использовании виртуальных машин и промежуточного двоичного кода. Как и язык Smalltalk, язык Java содержит большую библиотеку классов, которую можно расширять. Благодаря своей независимости от компьютерной платформы и богатому набору стандартных функций технология Java очень хорошо подходит для сети Интернет. Язык Java очень напоминает язык C++. Сначала команда компании Sim пыталась использовать язык C++, но, столкнувшись со слишком большим количеством сложных проблем, решила обойти их, создав новый более удобный язык программирования. Мы хотели построить систему, которую было бы легко программировать без длительной подготовки и которая учитывала бы современную стандартную практику. Сейчас большинство программистов используют язык С, а для объектно-ориентированного программирования применяют язык C++. По этой причине, несмотря на неудобность языка язык C++, мы решили сделать язык Java как можно более похожим на язык C++, чтобы система стала понятнее [19]. Язык Java не содержит многих свойств языка C++, таких как множественное наследование и перегрузку операторов. Одним из наиболее важных свойств языка Java является сборка "мусора" (garbage collection). Этот механизм освобождает разработчиков языка Java от необходимости реализовывать свою собственную систему управления памятью. Вместо этого они могут создавать новые экземпляры объектов и быть уверенными, что после удаления всех ссылок некоторая область памяти будет очищена. Несмотря на то что этот механизм сборки "мусора" не так эффективен, как механизм управления памятью в языке C++, он устраняет источники многих потенциальных ошибок. Язык Java стремится обеспечить максимально возможную с точки зрения практики безопасность типов. Однако, благодаря обширной библиотеке классов, такая строгая проверка типов, как в языке C++, не является практичной. Самая свежая спецификация языка Java 2 version 1.5 содержит некоторые новшества, которые называются Generics (JSR 14). Классы Java Generics, известные также как параметризованные типы, похожи на шаблоны из языка C++. Они позволяют программистам, работающим на языке C++, помимо всего прочего создавать наборы данных (collections), безопасные с точки зрения типов. Характеристики языка Java относительно семи основных элементов объектного подхода приведены в табл. А.4.
Приложение А. Объектно-ориентированные языки программирования 591 Таблица А.4. Объектно-ориентированные свойства языка Java Элементы объект- Свойство Включено? ной модели Абстракция Переменные экземпляра Да Методы экземпляра Да Переменные класса Да Методы класса Да Инкапсуляция Модульность Иерархия Типизация Параллельность Персистентность Переменных Методов Виды моделей Наследование Шаблоны Метаклассы Строгая типизация Полиморфизм Многозадачность Персистентные объекты Открытая, защищенная, закрытая, пакет Открытая, защищенная, закрытая, пакет Файл Одиночное Да Нет Нет Да (одиночный) Да Нет Пример Попытка решить поставленную выше задачу с помощью языка Java, приводит нас к созданию отдельного файла, содержащего описание класса, для каждого из определенных классов. Сначала создадим класс Point. package test; public class Point { private int χ = 0; private int у = 0/ public Point(int x, int y) { this.x = x; this.у = у; } public int getX() { return x; } public void setX(int x) { this.x = x; }
592 Приложение А. Объектно-ориентированные языки программирован public int getY() { return у; } public void setY(int y) { this.у = у; } } Теперь определим класс Shape. package test; public class Shape { private Point center; public Point getCenter() { return center; } public void setCenter(Point center) { this.center = center; } } Перейдем к описанию класса Circle. package test; import java.awt.Graphics; public class Circle extends Shape { private int radius = 0; public void draw(Graphics g) { int χ = (getCenter().getX() - radius); int у = (getCenter().getY() - radius); int d = radius * 2; g.drawOval(χ, y, d, d); } public int getRadius() { return radius; } public void setRadius(int radius) { this.radius = radius; }
Приложение А. Объектно-ориентированные языки программирования 593 Теперь создадим класс Rectangle. package test; import j ava.awt.Graphics; public class Rectangle extends Shape { private int height = 0; private int width =0; public void draw(Graphics g) { int χ = (getCenter().getX() - width/2); int у - (getCenter().getY() - height/2); g.drawRect(x, y, width, height); } public int getHeight() { return height; } public void setHeight(int height) { this.height = height; } public int getWidth() { return width; } public void setWidth(int width) { this.width = width; } } Завершим наш пример классом SolidRectangle. package test; import j ava.awt.Color; import Java.awt.Graphics; public class SolidRectangle extends Rectangle { public void draw(Graphics g) { super.draw(g); int width = getWidth()-l; int height = getHeight()-1; int χ = (getCenter () .getXO - width/2); int у = (getCenter () .getYO - height/2); g.setColor(Color.GRAY);
594 Приложение А. Объектно-ориентированные языки программирования g.fillRect(х, у, width, height); } } Ссылки Издательство Sim Microsystems Press (SMP) является совместным предприятием компаний Sim Microsystems, Prentice Hall и Addison-Wesley. Компания SMP издает превосходные и очень подробные книги по всем аспектам технологии Java. Поскольку язык Java развивался и распространялся через сеть Интернет, она, вероятно, является наилучшим и наиболее адекватным источником знаний по языку Java. Кроме того, Кен Арнольд (Ken Arnold), Джеймс Гослинг (James Gosling) и Дэвид Холмс (David Holmes) написали книгу The Java Programming Language, Third Edition, представляющую собой полное введение в язык Java.
ПРИЛОЖЕНИЕ Б РЕКОМЕНДАЦИИ ПО ДАЛЬНЕЙШЕМУ ЧТЕНИЮ В приложении содержатся ссылки на источники информации, перечисленные в разделе Библиография, по темам, рассмотренным в каждой главе. Ссылка на пункт библиографии имеет вид [<метка раздела><год>]. Например, ссылка Brooks [3 1975] относится к книге F.Brooks, The Mythical Man-Month, изданной в 1975 году, указанной в разделе 3. Глава 1 Проблемы, связанные с проектированием сложного программного обеспечения, подробно описаны в двух классических трудах Брукса (Brooks) [3 1975, 3 1987]. Кроме того, полезная информация о современной практике программирования содержится в работе Гласса (Glass) [3 1982], а также в отчетах Управления по закупкам Министерства обороны США о работе специальной комиссии по научным исследованиям (the Office of the Under Secretary of Defense for Acquisition (reporting on the Defense Science Board Task Force)) [3 1987] и Министерства обороны США (U.S. Department of Defence) [3 1982]. Результаты эмпирических исследований природы и источников сбоев программного обеспечения приведены в работах ван Генухтена (van Genuchten) [3 1991], Гуиндона и др. (Guindon et al.) [3 1987] и Джонса (Jones) [3 1992]. Среди работ, посвященных архитектуре сложных систем, следует выделить две замечательные работы Симона (Simon) [A 1962, А 1982], а также работу Кур- туа (Courtois) [A 1985], применившего идеи Симона к разработке программного обеспечения. Знаменитая работа Александера (Alexander) [И 1979] открыла новый этап изучения архитектуры физических структур, а Петер (Peter) [И 1986] и Петроски (Petroski) [И 1985] исследовали проблемы, связанные со сложностью социальных и физических систем соответственно. Аллен (Allen) и Старр (Starr) [А 1982] исследовали иерархические системы в многочисленных прикладных об-
596 Приложение Б. Рекомендации по дальнейшему чтению ластях. Флуд (Flood) и Карсон (Carson) [A 1988] провели формальное исследование сложности с помощью общей теории систем. Уолдроп (Waldrop) [A 1992] описал новую теорию сложности и с ее помощью стал изучать сложные адаптивные системы, поведение в необычных ситуациях, а также самоорганизующиеся системы. Отчет Миллера (Miller) [A 1956] содержит эмпирические свидетельства существования фундаментальных факторов, ограничивающих познавательные возможности человека. Существует большое количество замечательных работ, посвященных вопросам разработки программного обеспечения. Росс (Ross), Гудинаф (Goodenough) и Ирвин (Irvine) [3 1980], а также Зелковиц (Zelkowitz) [3 1978] написали две классические работы, в которых изложены основные принципы проектирования программного обеспечения. Эти идеи были развиты Йенсеном (Jensen) и Тонисом (Tonies) [3 1979], Соммервилем (Sommerville) [3 1989], Виком (Vick) и Рама- мурти (Ramamoorthy) [3 1984], Вегнером (Wegner) [3 1980], Прессманом (Pressman) [3 1992], Оманом (Oman) и Льюисом (Lewis) [3 1990], Берзинсом (Berzins) и Льюки (Luqi) [3 1991], а также Нг (Ng) и Йе (Yeh) [3 1990]. Среди других работ, посвященных проектированию программного обеспечения, следует отметить книги Йордона (Yourdon) [3 1979], Фримана (Freeman) и Вассермана (Wasserman) [3 1983]. Принципы объектно-ориентированного проектирования программного обеспечения изложены в книгах Грэхема (Graham) [E 1991] и Берарда (Berard) [3 1993]. Наиболее понятное введение в теорию хаоса можно найти в книге Глейка (Gleick) [И 1987]. Глава 2 Впервые концепция объектной модели была изложена в работах Джонса (Jones) [Ε 1979] и Уильямса [Е 1986]. В докторской диссертации Кэя (Kay) [E 1969] было открыто новое направление, по которому впоследствии стало развиваться объектно-ориентированное программирование. Прекрасное изложение принципов абстракции языка программирования высокого уровня содержится в работе Шоу (Shaw) [К 1984]. Теоретические основы абстракции можно найти также в работах Лискова (Liskov) и Гуттага (Guttag) [3 1986], Гуттага (Guttag) [К 1980] и Хилфингера (Hilfinger) [К 1982]. Книга Парнаса (Parnas) [E 1979] является превосходной работой, посвященной сокрытию информации. Смысл и важность иерархического принципа описаны в книге, редактором которой был Патти (Pattee) [К 1973]. Разнообразные применения объектно-ориентированного программирования описаны в книгах Тейлора (Taylor) [3 1990, В 1992], Берарда (Berard) [3 1993], Λ. Love) [В 1993], а также Пинсона (Pinson) и Вайнера (Weiner) [В 1990].
Приложение Б. Рекомендации по дальнейшему чтению 597 Вопросы, связанные с объектно-ориентированной технологией, изучены в книгах Петерсона (Peterson) [Ж 1987], Шрайвера (Schriver) и Вегнера (Wegner) [Ж 1987], а также Хошафяна (Khoshafian) и Абнуса (Abnous) [Д 1990]. Помимо этого, великолепными источниками информации по объектно-ориентированному программированию являются труды многочисленных научных конференций. К организациям, разрабатывающим стандарты объектной технологии, относятся группа Object Management Group и комитет ANSI X3J7. Основным источником сведений о языке C++ можно назвать книгу Эллиса (Ellis) и Струструпа (Stroustrup) [Ж 1990], а также учебники Страуструпа [Ж 2000], Липпмана (Lippman), Лажойе (LaJoie) и My (Moo) [Ж 2005], Коплиена (Coplien) [Ж 1992]. Хорошим введением в технологию .NET Framework является книга Конрада и др. (Conrad et al.) [Ж 2001] Introducing .NET. Глава 3 Различия между величинами и объектами рассматриваются в работе Мак- леннана (MacLennan) [Ж 1987]. В книге Мейера (Meyer) [К 1987] предложена идея рассматривать программирование как процесс заключения контракта. Много работ посвящено иерархии классов, в особенности наследованию и полиморфизму. Все основные понятия и концепции изложены в работах Альбано (Albano) [Ж 1983], Аллена (Allen) и Старра (Starr) [A 1982], Брахмана (Brachman) [К 1983], Гальперна (Hailpern) и Нгуена (Nguyen) [Ж 1987], а также Вегнера (Wegner) и Здо- ника (Zdonik) [К 1988]. Формальное описание семантики наследования приведено в статье Кука (Cook) и Палсберга (Palsberg) [К 1989], а также в книге Турецкого (Touretzky) [Ж 1986]. Вирт (Wirth) [К 1987] предложил новый подход к расширению типа записей, аналогичный тому, который использовался в языке Oberon. В статье Ингаллса (Ingalls) [Ж 1986] обсуждаются вопросы, связанные с полиморфизмом. Грогоно (Grogono) [Ж 1989] изучил взаимосвязь между полиморфизмом и проверкой типов, а Пондер (Ponder) и Бач (Buch) [Ж 1992] предупредили об опасностях, связанных с неограниченным полиморфизмом. Практическое руководство по эффективному использованию наследования было предложено Мейером (Meyer) [Ж 1988], а также Халбертом (Halbert) и О'Брайеном (O'Brien) [Ж 1988]. Проблемы, связанные с обучением эффективному использованию специализации и обобщению, изучены в работе Лалонде (LaLonde) и Паг (Pugh) [К 1985]. Природа и значение абстракции описаны в статьях Рубина (Rubin) и Голдберга (Goldberg) [Б 1992], а также Вирфс-Брока (Wirfs-Brock), Уилкерсона (Wilkerson) и Винера (Wiener) [E 1990]. Критерии качества проектирования классов рассмотрены также в статье Коада (Coad) [E 1991].
598 Приложение Б. Рекомендации по дальнейшему чтению Мейер (Meyer) [Ж 1986] исследовал зависимости между обобщением и наследованием с точки зрения языка Eiffel. Страуструп (Stroustrup) [Ж 1988а] предложил механизм реализации параметризованных типов в языке C++. Альтернативой иерархиям классов является делегирование с помощью экземпляров (delegation using exemplars). Этот подход подробно изучен в статье Штейна (Stein) [Ж 1987]. Глава 4 Проблема классификации существовала всегда. В работе Политик Платон (Plato) ввел классический подход к категоризации на основе группировки объектов, обладающих похожими свойствами. Аристотель (Aristotle) развил эту тему в работе Категории и проанализировал разницу между классами и объектами. Через несколько столетий Фома Аквинский (Aquinas) в своей работе Summa Theologica, а затем Декарт (Descartes) в книге Rules for the Direction of the Mind продолжили размышления по поводу классификации. Взгляды современных объективистов на эту проблему изложены в книге Рэнда (Rand) [И 1979]. Точка зрения, альтернативная объективизму, обсуждается в книгах Лакофф (Lakoff) и Джонсона (Johnson) [И 1980], а также Голдштейна (Goldstein) и Эл- джера (Alger) [В 1992]. Классификация относится к основным интеллектуальным способностям человека. Теория обучения классификации в раннем детстве была основана Пьяже (Piaget) и описана в книге Майера (Maier) [A 1969]. Доступное изложение методов обучения детей объектной концепции приведено в книге Лефрансуа (Lefrancois) [A 1977]. Ученые, разрабатывающие теорию познания, подробно изучили проблему классификации. Непревзойденным источником информации по этому вопросу является книга Невела (Newell) и Симона (Simon) [А 1972]. Сведения более общего характера можно найти в книге Симона (Simon) [А 1982], Хофштадтера (Hofstadter) [И 1979], Сиглера (Siegler) и Ричардса (Richards) [А 1982], а также Стиллинга и др. (Stillings et al.) [A 1987]. Лингвист Лакофф (Lakoff) [A 1987] изучил, каким образом проблема классификации нашла свое отражение в разных языках и что это дает для понимания принципов работы человеческого мозга. Минский (Minsky) [A 1986] предложил подойти к этой проблеме с противоположной стороны и начать разработку теории классификации с изучения структуры мозга. Концептуальная кластеризация (conceptual clustering), или подход к представлению знаний на основе классификации, подробно описана в книгах Михальского (Michalski) и Степпа (Stepp) [А 1983, А 1986], Пекхэма (Peckham) и Марьянски (Maryanski) [К 1988], а также Соува (Sowa) [A 1984]. Методы анализа предметной области (domain analysis) — поиска ключевых абстракций и механизмов на основе изучения лексикона предметной области — описаны в серии статей Прието-Ди- аза (Prieto-Diaz) и Аранго (Arango) [A 1991]. Важные достижения в этой области
Приложение Б. Рекомендации по дальнейшему чтению 599 принадлежат Иско (Iscoe) [Б 1988]. Дополнительную информацию можно найти в работах Иско (Iscoe), Броуна (Browne) и Верта (Werth) [Б 1989], Мура (Moore) и Бейлина (Bailin) [Б 1988], а также Аранго (Arango) [Б 1989]. Классификация часто вынуждает отказаться от стереотипов, причем этот навык можно выработать (по крайней мере, это желательно). Фон Оеч (VonOech) [И 1990] предложил несколько способов обучения навыкам креативности. Ко- ад (Coad) [A 1993] разработал настольную игру (Object Game), воспитывающую навыки классификации и идентификации объектов. Большая работа была проведена в области каталогизации программного обеспечения, в частности, в области классификации идиом, механизмов и принципов. С этой точки зрения большой интерес представляют работы Гамма и др. (Gamma et al.) [E 1995], Коплиена (Coplien) [Ж 1992], Коада (Coad) [A 1992], Джонсона (Johnson) [A 1992], Шо (Shaw) [A 1989, А 1990, А 1991] и Вирфс-Брокса (Wirfs-Brock) [В 1991]. В своей выдающейся работе Александер (Alexander) [И 1979] предложил шаблоны проектирования (patterns) в области строительной архитектуры и планирования города. Математики попытались изобрести эмпирические подходы к классификации, образовавшие так называемую теорию измерений (measurement theory). Выдающимися работами в этой области являются статьи Стивенса (Stevens) [A 1946], а также Кумбса (Coombs), Райффа (Raiffa) и Срэлла (Thrall) [A 1954]. Общество классификации Северной Америки (The Classification Society of North America) дважды в год выпускает научный журнал, в котором публикуются статьи, посвященные проблемам классификации. Глава 5 Группа Object Management Group разработала систему UML Superstructure Specification, version 2.0, на основе которой создана эта книга. Эту систему можно загрузить с Web-страницы UML Resource Page, расположенной по адресу www. uml. org [M 2004]. Как уже отмечалось, система UML 2.0 весьма содержательна и хорошо продумана. Однако в повседневной работе она используется только частично. Читателям, интересующимся "темными углами" системы UML, мы рекомендуем прочитать книги Рамбо (Rumbaugh), Якобсона (Jacobson) и Буча (Booch) [3 2005], а также Буча, Рамбо, Якобсона [3 2005]. Блаха (Blaha) и Рамбо (Rumbaugh) [3 2005] обновили свой классический текст 1991-го года по объектно-ориентированному моделированию и проектированию, используя систему обозначений UML 2.O. Беннет (Bennett), Скелтон (Skelton) и Ланн (Lunn) [3 2005] изложили в своей книге практическое введение в систему обозначений UML 2.0, включая примеры, упражнения и задачи. Эта книга представляет собой переработанное издание пуб-
600 Приложение Б. Рекомендации по дальнейшему чтению ликации 2001 года и рекомендуется тем, кто впервые изучает систему обозначений UML. Книга Фоулера (Fowler) [3 2003] представляет собой краткое представление типичных примеров использования системы UML 2.O. Глава 6 Первое описание процесса проектирования, рассмотренного в главе, содержится в работе Буча (Booch) [E 1982]. Позднее Берард (Berard) [E 1986] усовершенствовал этот процесс. К числу смежных подходов к решению этой задачи относятся метод GOOD (общее объектно-ориентированное проектирование — General Object-Oriented Design), описанный в работе Зайдвица (Seidewitz) и Старка (Stark) [Ε 1986а, Ε 1986b, Ε 1987, Ε 1988], метод MOOD (многостороннее объектно-ориентированное проектирование — Multiple-view Object-Oriented Design), изложенный в книге Керта (Kerth) [Ε 1988], а также метод HOOD (иерархическое объектно-ориентированное проектирование — Hierarchical Object-Oriented Design), предложенное компаниями CRI, CISI Ingenierie и Matra for the European Space Station [E 1987]. Кроме того, мы рекомендуем читателям книгу Страуструпа (Stroustrup) [Ж 1991], в которой описан аналогичный процесс проектирования. Кроме книг, процитированных в главе 2, существует множество других работ, посвященных объектно-ориентированному проектированию. Наиболее интересными из них являются следующие: Кручтен (Kruchten) [E 2003], Алабиос (А1- abios) [Ε 1988], Бойд (Boyd) [Ε 1987], Бур (Buhr) [Ε 1984], Черри (Cherry) [E 1987, Ε 1990], Дешамп (deChampeaux), Бальзер (Balzer) и др. [Ε 1992], Дешамп (deCham- peaux), Ли (Lea) и Форе (Faure) [Ε 1992], Фельзингер (Felsinger) [E 1987a, E 1987b], Файерсмит (Firesmith) [Ε 1986, Ε 1993], Хайнс (Hines) и Унгер (Unger) [Ж 1986], Якобсон (Jacobson) [Ε 1985], Ямса (Jamsa) [Ε 1984], Кади (Kadie) [E 1986], Масье- ρο (Masiero) и Германо (Germano) [Ε 1988], Нильсен (Nielsen) [E 1988], Нис (Nies) [Ε 1986], Райлих (Rajlich) и Сильва (Silva) [E 1987], а также Шумейт (Shumate) [Ε 1987]. Сравнение различных объектно-ориентированных процессов проектирования можно найти в следующих работах: Арнольд и др. (Arnold et al.) [E 1991], Боем- Дэвис (Boehm-Davis) и Росс (Ross) [3 1984], Дешамп [Б 1991а, Б 1991b], Криббс (Cribbs), Мун (Moon) и Ро (Roe) [Ε 1992], Фоулер (Fowler) [E 1992], Келли (Kelly) [Ε 1986], Маннино (Mannino) [Ε 1987], Сонг (Song) [E 1992] и Вебстер (Webster) [Ε 1988]. Результаты сравнения структурных и объектно-ориентированных методов приведены в статьях Брукмана (Brookman) [Ε 1991], а также Фишмана (Fichman) и Кемерера (Kemerer) [E 1992]. Эмпирическим исследованиям процесса разработки программного обеспечения посвящена статья Куртиса (Curtis), Келлнера (Kellner) и Овера (Over) [3 1992], а также труды семинара Software Process Workshop [3 1988]. Помимо них, инте-
Приложение Б. Рекомендации по дальнейшему чтению 601 рее представляет книга Гуиндона (Guindon), Краснера (Krasner) и Куртиса (Curtis) [3 1987], в которой описываются процессы исследования, осуществляемые разработчиками на ранних стадиях проектирования. Прагматические принципы, которых должен придерживаться архитектор, разрабатывающий программное обеспечение, были предложены в статье Речтин (Rechtin) [3 1992]. Классическим справочным руководством по фальсификации процессов проектирования является статья Парнас (Parnas) и Клементе (Clements) [3 1986]. Глава 7 Общие риски, которым подвергается программное обеспечение, проанализированы в работах ван Генухтена (van Genuchten) [3 1991] и Джонса (Jones) [3 1992]. Динамика развития проектных групп изучена в книге Абдель-Хамида (Abdel-Hamid) и Мэдника (Madnick) [3 1991]. Полезные сведения о практике управления процессами проектирования программного обеспечения содержатся в книгах Гилба (Gilb) [3 1988] и Чаретт (Charette) [3 1989]. Реальные проблемы, с которыми сталкиваются разработчики программного обеспечения, когда требования практики начинают доминировать над теорией, описаны в книгах Гласса (Glass) [3 1982], Ламмерса (Lammers) [3 1986] и Хамфри (Humphrey) [3 1989]. Большое количество рекомендаций, необходимых менеджеру, управляющему процессом разработки программного обеспечения, содержится в книге Демарко (DeMarco) и Листера (Lister) [3 1987], а также в статьях Йордона (Yourdon) [3 1989b], Реттига (Rettig) [3 1990] и Томсетта (Thom- sett) [3 1990]. Книга Шульмейера (Schulmeyer) и Маккмануса (McManus) [3 1992] представляет собой превосходный справочник по методам обеспечения качества ПО. Обеспечение качества объектно-ориентированных систем и методы его оценки изложены в статье Чидамбер (Chidamber) и Кемерер (Kemerer) [3 1991], а также Уолш (Walsh) [3 1992, 1993]. Кемерер (Kemerer) и Дарси (Darcy) [3 2005] описали примеры применения комплекса для измерения качества программного обеспечения Chidamber Kemerer (CK). Книга Кана (Кап) [3 2002] является полным справочником по методам обеспечения качества ПО и его оценки. Кроме того, она содержит выводы, которые извлекли авторы в ходе разработки объектно-ориентированных проектов. Лоренц (Lorenz) и Кидд (Kidd) [3 1994], а также Хендерсон-Селлерс (Henderson-Sellers) [3 1996] написали великолепные книги по методам оценки качества объектно- ориентированных проектов. Предложения, позволяющие отдельным программистам и организациям перейти к объектному моделированию, изложены в книге Гольдберг (Goldberg) [В 1978], Гольдберг (Goldberg) и Кэй (Кау) [Ж 1977], а также Кэмпф (Kempf) [Ж 1987].
602 Приложение Б. Рекомендации по дальнейшему чтению Новаторский подход к оценке рисков, связанных с объектно-ориентированным проектированием, путем отображения информации, извлеченной из работы Боем (Boehm) [3 1989, 3 2002], в объектно-ориентированные понятия, предложенные Мейером (Meyer) [3 1995], описан в книге Хантос (Hantos) [3 2005]. Глава 8 Справочник GPS Primer—A Student Guide to the Global Positioning System, опубликованный компанией Aerospace Corporation, представляет собой введение в глобальное позиционирование (Global Positioning) [В 2003]. Департамент энергии и транспорта Европейской комиссии (The European Commission, Directorate-General for Energy and Transportation) разработал Web-сайт, посвященный проекту Galileo, представляющему собой европейскую спутниковую систему навигации (European Satellite Navigation System) [В 2006]. Комиссия ΙΕΕΕ-Std-1471-2000 разработала принципы архитектурного создания систем, связанных с интенсивным использованием программного обеспечения [Г 2000]. В статье ANSI/IEEE 1471 and Systems Engineering Майер (Maier), Эмери (Emery) и Хиллард (Hilliard) [Г 2004] изложили принципы использования спецификации для описания системной архитектуры. Кручтен (Kruchten) [Г 1995] предложил архитектурную модель 4+1 для описания программного обеспечения с пяти точек зрения: логика, процесс, физическая сущность, проектирование и использование. В статье Introduction to Object-Oriented Systems Engineering (части1 и 2), Кри- корян (Krikorian) [Г 2003] предложил применить подход Кричтена 4+1 к проектированию систем и подробно аргументировал свою точку зрения. Документ IEEE-Std-12207 состоит из трех частей: 12207.0, 12207J и 12207.2. IEEE-Std-12207.0-1996 [3 1996]. В нем изложены основы проектирования программного обеспечения как в национальных, так и в международных компаниях. Он содержит уточнения, модификации и дополнения стандарта ISO/IEC 12207: 1995. Стандарт IEEE-Std-12207.1-1997 [3 1997а] представляет собой руководство по записи данных о жизненном цикле программного обеспечения. Стандарт IEEE- Std-12207.2-1997 [3 1997b] представляет собой руководство по реализации процессов проектирования, описанных в документе IEEE-Std-12207.0-1996. Стандарт IEEE-Std-1220-2005 [3 2005] содержит описание подхода к решению междисциплинарных задач, возникающих при проектировании программного обеспечения. Международный комитет по проектированию систем (The International Council on Systems Engineering (INCOSE)) разработал полное руководство по проектированию систем [И 2006].
Приложение Б. Рекомендации по дальнейшему чтению 603 Глава 9 Некоторые задачи, связанные с проектированием системы управления железнодорожным движением (Train Traffic Management System), решены с помощью методов, примененных при разработке усовершенствованной системы управления железнодорожным движением, описанных в книге Мэрфи (Murphy) [В 1988]. Проблемы, связанные с переводом сообщений и верификацией, возникают практически во всех системах управления. Плинта (Plinta), Ли (Lee) и Риссман (Rissman) [В 1989] создали превосходное описание этих задач и предложили механизм для передачи сообщений, безопасных с точки зрения типа, между процессорами, образующими распределенную систему. Глава 10 В контексте архитектурных шаблонов проектирования Шоу (Shaw) [A 1991], наряду с другими принципами, рассмотрел принцип "классной доски". Энглемор (Englemore) и Морган (Morgan) [В 1988] опубликовали полное описание систем, основанных на принципе "классной доски", включая ее эволюцию, теорию, проектирование и приложение. Помимо прочего, эта книга содержит описание двух объектно-ориентированных систем, основанных на методе "классной доски": ВВ1, разработанная в Стэнфорде (Stanford), и BLOB, разработанная Министерством обороны Великобритании. Другие полезные источники информации о системах, основанных на методу "классной доски", - работы Хайес-Рот (Hayes-Roth) [К 1985] и Нии (Nii) [К 1986]. Подробное описание методов прямого и обратного логического вывода (forward- and backward-chaining) в системах, основанных на логических правилах (rules-based systems), можно найти в книгах Барр (Вагг) и Фейгенбаума (Feigen- baum) [К 1981], Брахман (Brachman) и Левеск (Levesque) [К 1985], Хайес-Рот (Hayes-Roth), Уотермен (Waterman) и Ленат (Lenat) [К 1983], Уинстон (Winston) иХорн(Ногп)[Ж1989]. Мейер (Meyer) и Матьяс (Matyas) [И 1982] описали сильные и слабые стороны разных шифров, а также алгоритмические подходы к их взлому. Проблемы, преимущества и недостатки подхода, основанного на методе "классной доски", описаны в книгах Коркилла (Corkill) [Г 1991] и Ханта (Hunt) [Г 2002]. Глава 11 Вопросы, связанные с проблемами синхронизации (synchronization), тупика (deadlock), активного тупика (livelock) и конкуренции (race), подробно описаны в книге Хансен (Hansen) [3 1977], Бен-Ари (Ben-Ari) [3 1982], Холта и др. (Holt et al.) [3 1978]. Общие проблемы, связанные с приложениями в реальном времени, описаны в работах Мелликамп (Mellichamp) [3 1983], Гласе (Glass) [3 1983]
604 Приложение Б. Рекомендации по дальнейшему чтению и Фостер (Foster) [3 1981]. В работе Лорин (Lorin) [3 1972] параллельность рассматривается как взаимодействие аппаратного и программного обеспечения. Глава 12 В книге Гаррет (Garrett) [H 2002] обсуждаются вопросы, связанные с пользовательским проектированием высокого уровня. Константин (Constantine) и Локвуд (Lockwood) [H 1999] рассматривают проблемы пользовательского проектирования с точки зрения использования и моделирования. Книга Монсон-Хаефель (Monson-Haefel) [H 2001] представляет собой введение в проектирование и программирование с помощью системы EJB. Книга Гери (Geary) и Хорстманн (Horstmann) [H 2004] посвящена проблемам проектирования пользовательского интерфейса в контексте реализации повторно используемых компонентов Web-приложений. Каванесс (Cavaness) [H 2004] описывает принципы Штрутца (Struts) и шаблон проектирования модель-вид-контроллер (model-view-controller).
ПРИМЕЧАНИЯ Предисловие Mills, Η. 1985. DPMA and Human Productivity. Houston, TX: Data Processing Management Association. Часть 1. Понятия Wagner, J. 1986. The Search for Signs of Intelligent Life in the Universe. New York, NY: Harper and Row, p. 202. By permission of ICM, Inc. Глава 1. Сложность [1] Brooks, F. April 1987. No Silver Bullet: Essence and Accidents of Software Engineering. IEEE Computer vol. 20(4), p. 12. [2] Peters, L. 1981. Software Design. New York, NY: Yourdon Press, p. 22. [3] Brooks. No Silver Bullet, p. 11. [4] Parnas, D. July 1985. Software Aspects of Strategic Defense Systems. Victoria, Canada: University of Victoria, Report DCS-47-IR. [5] Peter, L. 1986. The Peter Pyramid. New York, NY: William Morrow, p. 153. [6] Waldrop, M. 1992. Complexity: The Emerging Science at the Edge of Order and Chaos. New York, NY: Simon and Schuster. [7] Courtois, P. June 1985. On Time and Space Decomposition of Complex Structures. Communications of the ACM vol. 28(6), p. 596. [8] Simon, H. 1982. The Sciences of the Artificial. Cambridge, MA: The MIT Press, p. 218. [9] Rechtin, E. October 1992. The Art of Systems Architecting. IEEE Spectrum vol. 29(10), p. 66. [10] Simon. Sciences, p. 217.
606 Примечания Там же, р. 221. Там же, р. 209. Gall, J. 1986. Systemantics: How Systems Really Work and How They Fail Second Edition. Ann Arbor, MI: The General Systemantics Press, p. 65. Miller, G. March 1956. The Magical Number Seven, Plus or Minus Two: Some Limits on Our Capacity for Processing Information. The Psychological Review vol. 63(2), p. 86. Simon. Sciences, p. 81. Dijkstra, E. 1979. Programming Considered as a Human Activity. In: Classics in Software Engineering. New York, NY: Yourdon Press, p. 5. Parnas, D. December 1985. Software Aspects of Strategic Defense Systems. Communications of the ACM vol. 28(12), p. 1328. Tsai, J., and Ridge, J. November 1988. Intelligent Support for Specifications Transformation. IEEE Software vol. 5(6), p. 34. Stein, J. March 1988. Object-Oriented Programming and Database Design. Dr. Dobb's Journal of Software Tools for the Professional Programmer no. 137, p. 18. Peters. Software Design. Yau, S., and Tsai, J. June 1986. A Survey of Software Design Techniques. IEEE Transactions on Software Engineering vol. SE-12(6). Teledyne Brown Engineering. October 1987. Software Methodology Catalog, Report MC87-COMM/ADP-0036. Tinton Falls, NJ. Sommerville, 1.1985. Software Engineering. Second Edition. Wokingham, England: Addison-Wesley, p. 68. Yourdon, E., and Constantine, L. 1979. Structured Design. Englewood Cliffs, NJ: Prentice-Hall. Myers, G. 1978. Composite/Structured Design. New York, NY: Van Nostrand Reinhold. Page-Jones, M. 1988. The Practical Guide to Structured Systems Design. Englewood Cliffs, NJ: Yourdon Press. Wirth, N. January 1983. Program Development by Stepwise Refinement. Communications of the ACM vol. 26(1). Wirth, N. 1986. Algorithms and Data Structures. Englewood Cliffs, NJ: Prentice-Hall. Dahl, O., Dijkstra, E., and Hoare, C. A. R. 1972. Structured Programming. London, England: Academic Press.
Примечания 607 [30] Mills, H., Linger, R., and Hevner, A. 1986. Principles of Information System Design and Analysis. Orlando, FL: Academic Press. [31] Jackson, M. 1975. Principles of Program Design. Orlando, FL: Academic Press. [32] Jackson, M. 1983. System Development. Englewood Cliffs, NJ: Prentice-Hall. [33] Orr, K. 1971. Structured Systems Development. New York, NY: Yourdon Press. [34] Langdon, G. 1982. Computer Design. San Jose, CA: Computeach Press, p. 6. [35] Miller. Magical Number, p. 95. [36] Shaw, M. (ed.). 1981. ALPHARD: Form and Content. New York, NY: Springer- Verlag, p. 6. [37] Goldberg, A. 1984. Smalltalk-80: The Interactive Programming Environment. Reading, MA: Addison-Wesley, p. 80. [38] Petroski, H. 1985. To Engineer Is Human. New York, NY: St. Martin's Press, p. 40. [39] Dijkstra, E. January 1993. American Programmer vol. 6(1). [40] Mostow, J. Spring 1985. Toward Better Models of the Design Process. AI Magazine vol. 6(1), p. 44. [41 ] Stroustrup, B. 1991. The C+ Programming Language. Second Edition. Reading, MA: Addison-Wesley, p. 366. [42] Eastman, N. 1984. Software Engineering and Technology. Technical Directions vol. 10(1), p. 5. [43] Brooks. No Silver Bullet, p. 10. Глава 2. Объектная модель [1] Wegner, P. June 1981. The Ada Programming Language and Environment. Unpublished draft. [2] Abbott, R. August 1987. Knowledge Abstraction. Communications of the ACM vol. 30(8), p. 664. [3] Там же, р. 664. [4] Shankar, K. 1984. Data Design: Types, Structures, and Abstractions. Handbook of Software Engineering. New York, NY: Van Nostrand Reinhold, p. 253. [5] Macintosh MacApp 1.1.1 Programmer's Reference. 1986. Cupertino, CA: Apple Computer, p. 2. [6] Bhaskar, K. October 1983. How Object-Oriented Is Your System? SIGPLAN Notices vol. 18(10), p. 8.
608 Примечания [7] Stefik, M., and Bobrow, D. Winter 1986. Object-Oriented Programming: Themes and Variations. AI Magazine vol. 6(4), p. 41. [8] Yonezawa, Α., and Tokoro, M. 1987. Object-Oriented Concurrent Programming: An Introduction. In Object-Oriented Concurrent Programming. Cambridge, MA: The MIT Press, p. 2. [9] Levy, H. 1984. Capability-Based Computer Systems. Bedford, MA: Digital Press, p. 13. [10] Ramamoorthy, C, and Sheu, P. Fall 1988. Object-Oriented Systems. IEEE Expert vol. 3(3), p. 14. [11] Myers, G. 1982. Advances in Computer Architecture. Second Edition. New York, NY: John Wiley and Sons, p. 58. [12] Dijkstra, E. May 1968. The Structure of the "THE" Multiprogramming System. Communications of the ACM vol. 11(5). [13] Pashtan, A. 1982. Object-Oriented Operating Systems: An Emerging Design Methodology. Proceedings of the ACM '82 Conference. ACM. [14] Parnas, D. 1979. On the Criteria to Be Used in Decomposing Systems into Modules. In Classics in Software Engineering. New York, NY: Yourdon Press. [15] Liskov, В., and Zilles, S. 1977. An Introduction to Formal Specifications of Data Abstractions. In Current Trends in Programming Methodology: Software Specification and Design vol. 1. Englewood Cliffs, NJ: Prentice-Hall. [16] Guttag, J. 1980. Abstract Data Types and the Development of Data Structures. In Programming Language Design. New York, NY: Computer Society Press. [17] Shaw, M. October 1984. Abstraction Techniques in Modern Programming Languages. IEEE Software vol. 1(4), p. 10. [18] Nygaard, K., and Dahl, O-J. 1981. The Development of the Simula Languages. In History of Programming Languages. New York, NY: Academic Press, p. 460. [19] Atkinson, M., and Buneman, P. June 1987. Types and Persistence in Database Programming Languages. ACM Computing Surveys vol. 19(2), p. 105. [20] Rumbaugh, J. April 1988. Relational Database Design Using an Object-Oriented Methodology. Communications of the ACM vol. 31(4), p. 415. [21] Chen, P. March 1976. The Entity-Relationship Model-Toward a Unified View of Data. ACM Transactions on Database Systems vol. 1(1). [22] Barr, Α., and Feigenbaum, E. 1981. The Handbook of Artificia Intelligence. Vol. 1. Los Altos, CA: William Kaufmann, p. 216. [23] Stillings, N., Feinstein, M., Garfield, J., Rissland, E., Rosenbaum, D., Weisler, S., and Baker-Ward, L. 1987. Cognitive Science: An Introduction. Cambridge, MA: The MIT Press, p. 305.
Примечания 609 [24] Rand, Ayn. 1979. Introduction to Objectivist Epistemology. New York, NY: New American Library. Minsky, M. 1986. The Society of Mind. New York, NY: Simon and Schuster. Jones, A. 1979. The Object Model: A Conceptual Tool for Structuring Software. In Operating Systems. New York, NY: Springer-Verlag, p. 8. Stroustrup, B. May 1988. What Is Object-Oriented Programming? IEEE Software vol. 5(3), p. 10. Cardelli, L., and Wegner, P. December 1985. On Understanding Types, Data Abstraction, and Polymorphism. ACM Computing Surveys vol. 17(4), p. 481. DeMarco, T. 1979. Structured Analysis and System Specification. Englewood Cliffs, NJ: Prentice-Hall. Yourdon, E. 1989. Modern Structured Analysis. Englewood Cliffs, NJ: Prentice- Hall. Gane, C, and Sarson, T. 1979. Structured Systems Analysis. Englewood Cliffs, NJ: Prentice-Hall. Ward, P., and Mellor, S. 1985. Structured Development for Real-Time Systems. Englewood Cliffs, NJ: Yourdon Press. Hatley, D., and Pirbhai, I. 1988. Strategies for Real-Time System Specification. New York, NY: Dorset House. Jenkins, M., and Glasgow, J. January 1986. Programming Styles in Nial. IEEE Software vol. 3(1), p. 48. Bobrow, D., and Stefik, M. February 1986. Perspectives on Artificial Intelligence Programming. Science vol. 231, p. 951. Dahl, O., Dijkstra, E., and Hoare, С A. R. 1972. Structured Programming. London, England: Academic Press, p. 83. Shaw. Abstraction Techniques. Berzins, V., Gray, M., and Naumann, D. May 1986. Abstraction-Based Software Development. Communications of the ACM vol. 29(5), p. 403. Abelson, H., and Sussman, G. 1985. Structure and Interpretation of Computer Programs. Cambridge, MA: The MIT Press, p. 126. Там же, р. 132. Seidewitz, E., and Stark, M. 1986. Towards a General Object-Oriented Software Development Methodology. Proceedings of the First International Conference on Ada Programming Language Applications for the NASA Space Station. NASA Lyndon B. Johnson Space Center, TX: NASA, p. D.4.6.4.
610 Примечания [42] Meyer, В. 1988. Object-Oriented Software Construction. New York, NY: Prentice Hall. [43] Wirfs-Brock, R., and Wilkerson, B. October 1989. Object-Oriented Design: A Responsibility-Driven Approach. SIGPLAN Notices vol. 24(10). [44] Ingalls, D. The Smalltalk-76 Programming System Design and Implementation. Proceedings of the Fifth Annual ACM Symposium on Principles of Programming Languages. ACM, p. 9. [45] Gannon, J., Hamlet, R., and Mills, H. July 1987. Theory of Modules. IEEE Transactions on Software Engineering vol. SE-13(7), p. 820. [46] Date, С 1986. Relational Database: Selected Writings. Reading, MA: Addison- Wesley,p. 180. [47] Liskov, B. May 1988. Data Abstraction and Hierarchy. SIGPLAN Notices, vol. 23(5), p. 19. [48] Britton, K., and Parnas, D. December 8, 1981. A-7E Software Module Guide. Washington, DC: Naval Research Laboratory, Report 4702, p. 24. [49] Stroustrup, B. 1988. Private communication. [50] Myers, G. 1978. Composite/Structured Design. New York, NY: Van Nostrand Reinhold, p. 21. [51] Liskov, B. 1980. A Design Methodology for Reliable Software Systems. In: Tutorial on Software Design Techniques. Third Edition. New York, NY: IEEE Computer Society, p. 66. [52] Zelkowitz, M. June 1978. Perspectives on Software Engineering. ACM Computing Surveys vol. 10(2), p. 20. [53] Parnas, D., Clements, P., and Weiss, D. March 1985. The Modular Structure of Complex Systems. IEEE Transactions on Software Engineering vol. SE-11(3), p. 260. [54] Britton and Parnas. A-7E Software, p. 2. [55] Parnas, D., Clements, P., and Weiss, D. 1983. Enhancing Reusability with Information Hiding. Proceedings of the Workshop on Reusability in Programming, Stratford, CT: ITT Programming, p. 241. [56] Meyer. Object-Oriented Software Construction, p. 47. [57] Cox, B. 1986. Object-Oriented Programming: An Evolutionary Approach. Reading, MA: Addison-Wesley, p. 69. [58] Danforth, S., and Tomlinson, С March 1988. Type Theories and Object- Oriented Programming. ACM Computing Surveys vol. 20(1), p. 34. [59] Liskov. Data Abstraction and Hierarchy, p. 23.
Примечания 611 [60] As quoted in Liskov. Design Methodology, p. 67. [61] Zilles, S. 1984. Types, Algebras, and Modeling. In: On Conceptual Model· ing: Perspectives from Artificial Intelligence, Databases, and Programming Languages. New York, NY: Springer-Verlag, p. 442. [62] Borning, Α., and Ingalls, D. 1982. A Type Declaration and Inference System for Smalltalk. Palo Alto, CA: Xerox Palo Alto Research Center, p. 134. [63] Stroustrup, B. 1992. Private communication. [64] Tesler, L. August 1981. The Smalltalk Environment. Byte vol. 6(8), p. 142. [65] Borning and Ingalls. Type Declaration, p. 133. [66] Thomas, D. March 1989. What's in an Object? Byte vol. 14(3), p. 232. [67] Lim, J., and Johnson, R. April 1989. The Heart of Object-Oriented Concurrent Programming. SIGPLAN Notices vol. 24(4), p. 165. [68] Black, Α., Hutchinson, N., Jul, E., Levy, H., and Carter, L. July 1986. Distribution and Abstract Types in Emerald. Report 86-02-04. Seattle, WA: University of Washington, p. 3. [69] Proceedings of the ACM SIGPLAN Workshop on Object-Based Concurrent Programming. April 1989. SIGPLAN Notices vol. 24(4), p. 1. [70] Atkinson, M., Bailey, P., Chisholm, K., Cockshott, P., and Morrison, R. [71] Khoshafian, S., and Copeland, G. November 1986. Object Identity. SIGPLAN Notices vol. 21(11), p. 409. [72] Vbase Technical Overview. September 1987. Billerica, MA: Ontologic, p. 4. [73] Stroustrup, B. November 1987. Possible Directions for C++. Proceedings of the USENIX C++ Workshop. Santa Fe, NM, p. 14. [74] Meyer. Object-Oriented Software Construction, pp. 30-31. [75] Robson, D. August 1981. Object-Oriented Software Systems. Byte vol. 6(8), p. 74. [76] See www.hibernate.org for more information and downloads. Глава 3. Классы и объекты [1] Lefrancois, G. 1977. Of Children: An Introduction to Child Development. Second Edition. Belmont, CA: Wadsworth, p. 244-246. [2] Nygaard, K., and Dahl, O-J. 1981. The Development of the Simula Languages. In History of Programming Languages. New York, NY: Academic Press, p. 462. [3] Halbert, D., and O'Brien, R September 1988. Using Types and Inheritance in Object-Oriented Programming. IEEE Software vol. 4(5), p. 73.
612 Примечания Smith, M., and Tockey, S. 1988. An Integrated Approach to Software Requirements Definition Using Objects. Seattle, WA: Boeing Commercial Airplane Support Division, p. 132. MacLennan, B. December 1982. Values and Objects in Programming Languages. SIGPLAN Notices vol. 17(12), p. 78. [6] Lippman, S. 1989. C++ Primer. Reading, MA: Addison-Wesley, p. 185. [7] Adams, S. 1993. Private communication. Wirfs-Brock, R., Wilkerson, В., and Wiener, L. 1990. Designing Object-Oriented Software. Englewood Cliffs, NJ: Prentice Hall, p. 61. [9] Rubin, K. 1993. Private communication. 10] Macintosh MacApp 1.1.1 Programmer s Reference. 1986. Cupertino, CA: Apple Computer, p. 4. Khoshafian, S., and Copeland, G. November 1986. Object Identity. SIGPLAN Notices vol. 21(11), p. 406. 12] Ingalls, D. 1981. Design Principles Behind Smalltalk. Byte vol. 6(8), p. 290. 13] Gall, J. 1986. Systemantics: How Systems Really Work and How They Fail. Second Edition. Ann Arbor, MI: The General Systemantics Press, p. 158. Rumbaugh, J., Blaha, M., Premerlani, W., Eddy, R, and Lorensen, W. 1991. Object-Oriented Modeling and Design. Englewood Cliffs, NJ: Prentice-Hall, p. 459. 15] Webster's Third New International Dictionary of the English Language, unabridged. 1986. Chicago, IL: Merriam-Webster. 16] Stroustrup, B. 1991. The C+ Programming Language. Second Edition. Reading, MA: Addison-Wesley, p. 422. 17] Meyer, B. 1987. Programming as Contracting. Report TR-EI-12/CO. Goleta, CA: Interactive Software Engineering. 18] Snyder, A. November 1986. Encapsulation and Inheritance in Object-Oriented Programming Languages. SIGPLAN Notices vol. 21(11). 19] LaLonde, W. April 1989. Designing Families of Data Types Using Exemplars. ACM Transactions on Programming Languages and Systems, vol. 11(2), p. 214. [20] Rumbaugh, J. April 1988. Relational Database Design Using an Object-Oriented Methodology. Communications of the ACM vol. 31(4), p. 417. [21] Brachman, R. October 1983. What IS-A Is and Isn't: An Analysis of Taxonomic Links in Semantic Networks. IEEE Computer vol. 16(10), p. 30. [22] As quoted in Harland, D., Szyplewski, M., and Wainwright, J. October 1985. An Alternative View of Polymorphism. SIGPLAN Notices, vol. 20(10).
Примечания 613 [23] Kaplan, S., and Johnson, R. July 21, 1986. Designing and Implementing for Reuse. Urbana, IL: University of Illinois, Department of Computer Science, p. 8. [24] Deutsch, P. 1983. Efficient Implementation of the Smalltalk-80 System. In: Proceedings of the 11th Annual ACM Symposium on the Principles of Programming Languages, p. 300. [25] Там же, р. 299. [26] Duff, С August 1986. Designing an Efficient Language. Byte vol. 11(8), p. 216. [27] Stroustrup, B. 1988. Private communication. [28] Vlissides, J., and Linton, M. 1988. Applying Object-Oriented Design to Structured Graphics. Proceedings of USENIX C++ Conference. Berkeley, CA: USENIX Association, p. 93. [29] Meyer, B. 1988. Object-Oriented Software Construction. New York, NY: Prentice Hall, p. 274. [30] Hendler, J. October 1986. Enhancement for Multiple Inheritance. SIGPLAN Notices vol. 21(10), p. 100. [31] Object Management Group's Web site: www. omg. org. [32] Ingalls, D. August 1981. Design Principles Behind Smalltalk. Byte, vol. 6(8), p. 286. [33] Stevens, W., Myers, G., and Constantine, L. 1979. Structured Design. In: Classics in Software Engineering. New York, NY: Yourdon Press, p. 209. [34] Page-Jones, M. 1988. The Practical Guide to Structured Systems Design. En- glewood Cliffs, NJ: Yourdon Press, p. 59. [35] Meyer. Programming as Contracting, p. 4. [36] Halbert, D., and O'Brien, P. September 1988. Using Types and Inheritance in Object-Oriented Programming. IEEE Software vol. 4(5), p. 74. [37] Sakkinen, M. December 1988. Comments on "the Law of Demeter" and C++. SIGPLAN Notices vol. 23(12), p. 38. [38] Lea, D. August 12,1988. User's Guide to GNU C++ Library. Cambridge, MA: Free Software Foundation, p. 12. [39] Там же. [40] Meyer. Object-Oriented Software Construction, p. 332. [41] Wirth, N. 1986. Algorithms and Data Structures. Englewood Cliffs, NJ: Prentice-Hall, p. 37. [42] Keene, S. 1989. Object-Oriented Programming in Common Lisp. Reading, MA: Addison-Wesley, p. 68.
614 Примечания [43] Jacobson, I., Christerson, Μ., Jonsson, P., and Overgaard, G. 1992. Object- Oriented Software Engineering: A Use Case Driven Approach, Reading, MA: Addison-Wesley, p. 186. [44] Parnas, D., Clements, P., and Weiss, D. 1989. Enhancing Reusability with Information Hiding. In: Software Reusability. New York, NY: ACM Press, p. 143. Глава 4. Классификация [1] Michalski, R., and Stepp, R. 1983. Learning from Observation: Conceptual Clustering. In Machine Learning: An Artificial Intelligence Approach. Palo Alto, CA: Tioga, p. 332. [2] Alexander, С 1979. The Timeless Way of Building. New York, NY: Oxford University Press, p. 203. [3] Darwin, C. 1984. The Origin of Species. Vol. 49 ofGreat Books of the Western World. Chicago, IL: Encyclopedia Britannica, p. 207. [4] The New Encyclopedia Britannica. 1985. Chicago, IL: Encyclopedia Britannica, vol. 3, p. 356. [5] As quoted in Lewin, R. November 4, 1988. Family Relationships Are a Biological Conundrum. Science vol. 242, p. 671. [6] The New Encyclopedia Britannica vol. 3, p. 156. [7] Descartes, R. 1984. Rules for the Direction of the Mind. Vol. 31 of Great Books of the Western World. Chicago, IL: Encyclopedia Britannica, p. 32. [8] Shaw, M. May 1989. Larger Scale Systems Require Higher-Level Abstractions. SIGSOFTEngineering Notes vol. 14(3), p. 143. [9] Goldstein, T. May 1989. The Object-Oriented Programmer. The C++ Report vol. 1(5). [10] Coombs, C, Raiffa, H., and Thrall, R. 1954. Some Views on Mathematical Models and Measurement Theory. Psychological Review vol. 61(2), p. 132. [11] Birtwistle, G., Dahl, O-J., Myhrhaug, В., and Nygard, K. 1979. Simula begin. Lund, Sweden: Studentlitteratur, p. 23. [12] Heinlein, R. 1966. The Moon Is a Harsh Mistress. New York, NY: The Berkeley Publishing Group, p. 11. [13] Sowa, J. 1984. Conceptual Structures: Information Processing in Mind and Machine. Reading, MA: Addison-Wesley, p. 16. [14] Lakoff, G. 1987. Women, Fire, and Dangerous Things: What Categories Reveal About the Mind. Chicago, IL: The University of Chicago Press, p. 161.
Примечания 615 Stepp, R., and Michalski, R. February 1986. Conceptual Clustering of Structured Objects: A Goal-Oriented Approach. Artificial Intelligence, vol. 28(1), p. 53. Wegner, P. 1987. The Object-Oriented Classification Paradigm. In: Research Directions in Object-Oriented Programming. Cambridge, MA: The MIT Press, p. 480. Aquinas, T. 1984. Summa Theologica. Vol. 19 of Great Books of the Western World. Chicago, IL: Encyclopedia Britannica, p. 71. Maier, H. 1969. Three Theories of Child Development: The Contributions of Erik H. Erichon, Jean Piaget, and Robert R. Sears, and Their Applications. New York, NY: Harper and Row, p. 111. Lakoff. Women, Fire, and Dangerous Things, p. 32. Minsky, M. 1986. The Society of Mind. New York, NY: Simon and Schuster, p. 199. The Great Ideas: A Syntopicon ofGreat Books of the Western World. 1984. Vol. 1 of Great Books of the Western World. Chicago, IL: Encyclopedia Britannica, p. 293. Kosko, B. 1992. Neural Networks and Fuzzy Systems. Englewood Cliffs, NJ: Prentice-Hall. Stepp and Michalski. Conceptual Clustering, p. 44. Lakoff. Women, Fire, and Dangerous Things, p. 7. Там же, р. 16. Lakoff, G., and Johnson, M. 1980. Metaphors We Live By. Chicago, IL: The University of Chicago Press, p. 122. Meyer, B. 1988. Private communication. Shlaer, S., and Mellor, S. 1988. Object-Oriented Systems Analysis: Modeling the World in Data. Englewood Cliffs, NJ: Yourdon Press, p. 15. Ross, R. 1987. Entity Modeling: Techniques and Application. Boston, MA: Database Research Group, p. 9. Coad, P., and Yourdon, E. 1990. Object-Oriented Analysis. Englewood Cliffs, NJ: Prentice-Hall, p. 62. Shlaer, S., and Mellor, S. 1992. Object Lifecycles: Modeling the World in States. Englewood Cliffs, NJ: Yourdon Press. Wirfs-Brock, R., Wilkerson, В., and Wiener, L. 1990. Designing Object-Oriented Software. Englewood Cliffs, NJ: Prentice Hall, p. 61.
616 Примечания [33] Rubin, К., and Goldberg, A. September 1992. Object Behavior Analysis. Communications of the ACM vol. 35(9), p. 48. [34] Dreger, B. 1989. Function Point Analysis. Englewood Cliffs, NJ: Prentice Hall, p. 4. [35] Arango, G. May 1989. Domain Analysis: From Art Form to Engineering Discipline. SIGSOFT Engineering Notes vol. 14(3), p. 153. [36] Moore, J., and Bailin, S. 1988. Position Paper on Domain Analysis. Laurel, MD: СТА, р. 2. [37] Jacobson, I., Ericsson, M., and Jacobson, A. 1994. The Object Advantage: Business Process Reengineering with Object Technology. Wokingham, England: Addison-Wesley. [38] Zahniseer, R. July/August 1990. Building Software in Groups. American Programmer vol. 3(7-8). [39] Beck, K., and Cunningham, W. October 1989. A Laboratory for Teaching Object-Oriented Thinking. SIGPLAN Notices vol. 24(10). [40] Abbott, R. November 1983. Program Design by Informal English Descriptions. Communications of the ACM vol. 26(11). [41] McMenamin, S., and Palmer, J. 1984. Essential Systems Analysis. New York, NY: Yourdon Press, p. 267. [42] Ward, P., and Mellor, S. 1985. Structured Development for Real-Time Systems. Englewood Cliffs, NJ: Yourdon Press. [43] Seidewitz, E., and Stark, M. August 1986. General Object-Oriented Software Development. Report SEL-86-002. Greenbelt, MD: NASA Goddard Space Flight Center, p. 5-2. [44] Seidewitz, E. 1990. Private communication. [45] Goldberg, A. 1984. Smalltalk-80: The Interactive Programming Environment. Reading, MA: Addison-Wesley, p. 77. [46] Thomas, D. May/June 1989. In Search of an Object-Oriented Development Process. Journal of Object-Oriented Programming vol. 2(1), p. 61. [47] Stroustrup, B. 1986. The C++ Programming Language. Reading, MA: Addison- Wesley, p. 7. [48] Halbert, D., and O'Brien, P. September 1988. Using Types and Inheritance in Object-Oriented Programming. IEEE Software vol. 4(5), p. 75. [49] Stefik, M., and Bobrow, D. Winter 1986. Object-Oriented Programming: Themes and Variations. AI Magazine vol. 6(4), p. 60. [50] Stroustrup, B. 1991. The C+ Programming Language. Second Edition. Reading, MA: Addison-Wesley, p. 377.
Примечания 617 [51] Stefik and Bobrow. Object-Oriented Programming, p. 58. [52] Lins, C. 1989. A First Look at Literate Programming. In: Structured Programming. [53] Gabriel, R. 1990. Private communication. [54] Coplien, J. 1992. Advanced C++ Programming Styles and Idioms. Reading, MA: Addison-Wesley. [55] Adams, S. July 1986. MetaMethods: The MVC Paradigm, hi HOOPLA: Hooray for Object-Oriented Programming Languages. Everette, WA: Object-Oriented Programming for Smalltalk Applications Developers Association vol. 1(4), p. 6. [56] Englemore, R., and Morgan, T. 1988. Blackboard Systems. Wokingham, England: Addison-Wesley, p. v. [57] Coad, P. September 1992. Object-Oriented Patterns. Communications of the ACM vol. 35(9). [58] World Resources Institute Web site. Accessed Jan. 2006. How Many Species Are There? http: //pubs . wri . org/pubs__content_text. cfm? ContentID=535. Часть II. Метод Petroski, Η. 1985. To Engineer Is Human. New York, NY: St. Martin's Press, p. 73. Глава 5. Система обозначений [1] Shear, D. December 8,1988. CASE Shows Promise, but Confusion Still Exists. EDN, vol. 33(25), p. 168. [2] Whitehead, A. 1958. An Introduction to Mathematics. New York, NY: Oxford University Press. [3] Defense Science Board. September 1987. Report of the Defense Science Board Task Force on Military Software. Washington, DC: Office of the Undersecretary of Defense for Acquisition, p. 8. [4] Kleyn, M., and Gingrich, P. September 1988. GraphTrace—Understanding Ob- jec-Oriented Systems Using Concurrently Animated Views. SIGPLAN Notices vol. 23(11), p. 192. [5] Weinberg, G. 1988. Rethinking Systems Analysis and Design. New York, NY: Dorset House, p. 157. [6] Jacobson, I., Christerson, M., Jonsson, P., and Overgaard, G. 1992. Object- Oriented Software Engineering: A Use Case Driven Approach. Reading, MA: Addison-Wesley.
618 Примечания Maksimchuk, R., and Naiburg, E. 2005. UML for Mere Mortals. Boston, MA: Addison-Wesley. Blaha, M., and Rumbaugh, J. 2005. Object-Oriented Modeling and Design with UML· Second Edition. Upper Saddle River, NJ: Prentice Hall, pp. 116-118. Rumbaugh, J., Jacobson, I., and Booch, G. 2005. The Unified Modeling Language Reference Manual Second Edition. Boston, MA: Addison-Wesley, pp. 248-253. Там же, pp. 40, 109, 171. Object Management Group. 2004. UML 2.0 Superstructure Specification. Need- ham, MA: Object Management Group, pp. 206-208. Rumbaugh, Jacobson, and Booch. The Unified Modeling Language Reference Manual, pp. 40, 171-172. Там же, pp. 109, 479. Object Management Group. UML 2.0 Superstructure Specification, p. 222. Rumbaugh, Jacobson, and Booch. The Unified Modeling Language Reference Manual, p. 312. Там же, р. 313. Object Management Group. UML 2.0 Superstructure Specification, p. 219. Там же, pp. 213-214. Rumbaugh, Jacobson, and Booch. The Unified Modeling Language Reference Manual, pp. 187,498. Там же, pp. 129-133. Там же, р. 285. Там же, pp. 285-288. Там же, pp. 285-287. Там же, pp. 374-375. Там же, р. 429. Там же, р. 623. Object Management Group. UML 2.0 Superstructure Specification, p. 174. Rumbaugh, Jacobson, and Booch. The Unified Modeling Language Reference Manual, pp. 523-525. Object Management Group. UML 2.0 Superstructure Specification, pp. 189— 190. Rumbaugh, Jacobson, and Booch. The Unified Modeling Language Reference Manual, pp. 282-283.
Примечания 619 [31 [32 Object Management Group. UML 2.0 Superstructure Specification, pp. 169, 176-181. Rumbaugh, Jacobson, and Booch. The Unified Modeling Language Reference Manual, pp. 42^3, 111-112, 504-507. [33] Там же, р. 679. [34] Там же, pp. 71-73, 227-231. [35] Там же, pp. 506-507. [36] Object Management Group. UML 2.0 Superstructure Specification, pp. 169, 111-112. [37] Там же, pp. 111-112. [38] Rumbaugh, Jacobson, and Booch. The Unified Modeling Language Reference Manual, pp. 506-507. [39] Там же, pp. 113, 505-506, 678-680. [40] Object Management Group. UML 2.0 Superstructure Specification, pp. 109- 111. [41] Там же, pp. 109-111. [42] Rumbaugh, Jacobson, and Booch. The Unified Modeling Language Reference Manual, pp. 113, 505-506, 678-680. [43] Там же, pp. 112-113, 384, 505-506. [44] Там же, pp. 112-113, 505-506. [45] Там же, pp. 42, 111-112, 507. [46] Там же, pp. 42, 111-112, 507. [47] Там же, pp. 42, 111-112, 507. [48] Там же, pp. 42, 383-384, 505. [49] Object Management Group. UML 2.0 Superstructure Specification, p. 111. [50] Там же, pp. 113-114. [51] Rumbaugh, Jacobson, and Booch. The Unified Modeling Language Reference Manual, pp. 383-387, 505. [52] Там же, р. 383-387, 505. [53] Object Management Group. UML 2.0 Superstructure Specification, p. 113-114. [54] Там же, p. 111. [55] Rumbaugh, Jacobson, and Booch. The Unified Modeling Language Reference Manual, pp. 384-385, 505. [56] Там же, pp. 383-387, 505.
620 Примечания [57] Object Management Group. UML 2.0 Superstructure Specification, pp. 1 ΠΙ 14. [58] Rumbaugh, Jacobson, and Booch. The Unified Modeling Language Reference Manual, Pp. 31, 73, 253, 255. [59] Object Management Group. UML 2.0 Superstructure Specification, pp. 147, 150, 153. [60] Там же, р. 153. [61] Rumbaugh, Jacobson, and Booch. The Unified Modeling Language Reference Manual, pp. 31, 74, 256. [62] Там же, pp. 74, 254, 257, 523-525. [63] Object Management Group. UML 2.0 Superstructure Specification, pp. 150— 151. [64] Там же, pp. 150-151, 154. [65] Rumbaugh, Jacobson, and Booch. The Unified Modeling Language Reference Manual, pp. 31, 74, 254, 256, 416. [66] Там же, pp. 254, 257. [67] Object Management Group. UML 2.0 Superstructure Specification, p. 162. [68] Там же, pp. 147, 150, 153. [69] Rumbaugh, Jacobson, and Booch. The Unified Modeling Language Reference Manual, pp. 73-74, 253-254. [70] Там же, pp. 31-33, 257-258, 282-283. [71] Object Management Group. UML 2.0 Superstructure Specification, pp. 150, 156, 160. [72] Там же, pp. 154-155. [73] Rumbaugh, Jacobson, and Booch. The Unified Modeling Language Reference Manual, pp. 256-257, 415-417. [74] Там же, pp. 256-257, 418. [75] Object Management Group. UML 2.0 Superstructure Specification, p. 155. [76] Там же, р. 155. [77] Rumbaugh, Jacobson, and Booch. The Unified Modeling Language Reference Manual, pp. 256-257, 418. [78] Object Management Group. UML 2.0 Superstructure Specification, pp. 155- 156. [79] Там же, p. 150.
Примечания 621 [80] Rumbaugh, Jacobson, and Booch. The Unified Modeling Language Reference Manual, p. 31. [81] Там же, pp. 258, 283. [82] Object Management Group. UML 2.0 Superstructure Specification, pp. 160- 162. [83] Там же, pp. 169, 176-181. [84] Rumbaugh, Jacobson, and Booch. The Unified Modeling Language Reference Manual, pp. 71-73, 227-231. [85] Там же [86] Object Management Group. UML 2.0 Superstructure Specification, pp. 169, 176-181. [87] Там же [88] Rumbaugh, Jacobson, and Booch. The Unified Modeling Language Reference Manual, pp. 71-73, 227-231. [89] Там же [90] Object Management Group. UML 2.0 Superstructure Specification, pp. 169, 176-181. [91] Rumbaugh, Jacobson, and Booch. The Unified Modeling Language Reference Manual, p. 98. Глава 6. Процесс [1] Brooks, F. 1975. The Mythical Man-Month. Reading, MA: Addison-Wesley, 42. [2] Stroustrup, B. 1991. The C+ Programming Language. Second Edition. Reading, MA: Addison-Wesley. [3] Jones, С September 1984. Reusability in Programming: A Survey of the State of the Art. IEEE Transactions on Software Engineering vol. SE-10(5). [4] Parnas, D., and Clements, P. 1986. A Rational Design Process: How and Why to Fake It. IEEE Transactions on Software Engineering vol. SE-12(2). [5] Stroustrup. The C+ Programming Language, p. 373. [6] Gilb, T. 1988. Principles of Software Engineering Management Reading, MA: Addison-Wesley, p. 92. [7] Mellor, S., Hecht, Α., Tryon, D., and Hywari, W. September 1988. Object- Oriented Analysis: Theory and Practice, Course Notes. In: Object-Oriented Programming Systems, Languages, and Applications. San Diego, CA: OOP- SLA'88,p. 1.3.
622 Примечания [8] Andert, G. 1992. Private communication. [9] Walsh, J. Preliminary Defect Data from the Iterative Development of a Large C++ Program. Vancouver, Canada: OOPSLA'92. [10] Chmura, L., Norcio, Α., and Wicinski, T. July 1990. Evaluating Software Design Processes by Analyzing Change Date Over Time. IEEE Transactions on Software Engineering vol. 16(7). [11] As quoted in Summerville, I. 1989. Software Engineering. Third Edition. Wokingham, England: Addison-Wesley, p. 546. [12] The Zachman Institute for Framework Advancement: www. zif a. com. [13] Department of Defense Architecture Framework Working Group. Februrary 9, 2004. DoD Architecture Framework, Version 1.0. Volume 1: Definitions and Guidelines. Accessed in January 2007 at www. dod.mil/cio-nii/docs/ DoDAF__vl__Volume__I .pdf. [14] For more information on the Federal Enterprise Architecture, visit www. whitehouse.gov/omb/egov/a-1-fea.html. [15] Agile Alliance Web site. Accessed in January 2007 at http://agilemanifesto.org/principles.html. [16] Boehm, B. W., and Turner, R. 2004. Balancing Agility and Discipline: A Guide for the Perplexed. Boston, MA: Addison-Wesley, 2004. [17] Booch, G., Rumbaugh, J., and Jacobson, I. 1999. The Unified Modeling Language User's Guide. Reading, MA: Addison-Wesley, 1999. [18] Booch, G., and Brown, A. W. October 28, 2002. Collaborative Development Environments. Rational Software Corporation. [19] Eeles, P. February 15, 2006. What Is a Software Architecture? Accessed in January 2007 at www-128 . ibm. com/developerworks/rational/ library/febO6/eeles/. [20] IEEE Computer Society. 2000. IEEE Recommended Practice for Architectural Description of Software Intensive Systems. IEEE Std. 1471-2000. [21] Kruchten, P. November 1995. The 4+1 View Model of Architecture. IEEE Software 12(6), pp. 42-50. [22] Kruchten, P. August 2001. Software Maintenance Cycles with the RUP. Rational Edge. Accessed in January 2007 at www.ibm.com/developerworks/ rational/library/content/RationalEdge/augOl/ SoftwareMaintenanceCycleswiththeRUPAug01.pdf. [23] Kroll, P., and Kruchten, P. 2003. The Rational Unified Process Made Easy. Boston, MA: Addison-Wesley.
Примечания 623 [24] Larman, С. 2004. Agile and Iterative Development. Boston, MA: Addison- Wesley. [25] Martin, R. C. 2002. Agile Software Development, Principles, Patterns, and Practices. Upper Saddle River, NJ: Prentice Hall. [26] For more information about MDA, see the Object Management Group's related Web site, www. omg. org/mda. [27] The Rational Unified Process product produced by IBM Rational, 2006. [28] Adams, J., Koushik, S., Vasudeva, G., and Galambos, G. 2001. Patterns for e-Business: A Strategy for Reuse. Double Oak, TX: IBM Press. [29] Buschmann, R, Meunier, R., Rohnert, H., Sommerlad, P., and Stal, M. 1996. Pattern-Oriented Software Architecture, Volume 1: A System of Patterns. New York, NY: John Wiley & Sons. [30] Cheesman, J., and Daniels, J. 2001. UML Components: A Simple Process for Specifying Component-Based Software. Boston, MA: Addison-Wesley. [31] Gamma, E., Helm, R., Johnson, R., and Vlissides, J. 1995. Design Patterns: Elements of Reusable Object-Oriented Software. Reading, MA: Addison-Wesley. [32] Herzum, P., and Sims, 0.2000. Business Component Factory: A Comprehensive Overview of Component-Based Development for the Enterprise. New York, NY: Wiley. Глава 7. Практические вопросы [1] Goldstein, Η. September 2005. Who Killed the Virtual Case File? IEEE Spectrum vol. 42, p. 24. [2] Miller, J. March 20, 2006. FBI Awards Lockheed $305 Million Sentinel Contract. Government Computer News. Accessed in January 2007 at www. gen. com/online/voll_nol/40145-1.html. [3] Charette, R. September 2005. Why Software Fails. IEEE Spectrum,vol. 42, p. 42. [4] Hawryszkiewycz, I. 1984. Database Analysis and Design. Chicago, IL: Science Research Associates, p. 115. [5] van Genuchten, M. June 1991. Why Is Software Late? An Empirical Study of Reasons for Delay in Software Development. IEEE Transactions on Software Engineering vol. 17(6), p. 589. [6] Gilb, T. 1988. Principles of Software Engineering Management. Reading, MA: Addison-Wesley, p. 73. [7] As quoted in Zelkowitz, M. June 1978. Perspectives on Software Engineering. ACM Computing Surveys vol. 10(2), p. 204.
624 Примечания [8] Showalter, J. 1989. Private communication. [9] Davis, Α., Bersoff, E., and Comer, E. October 1988. A Strategy for Comparing Alternative Software Development Life Cycle Models. IEEE Transactions on Software Engineering vol. 14(10), p. 1456. [10] Goldberg, A. 1993. Private communication. [11] Schulmeyer, G., and McManus, J. 1992. Handbook of Software Quality Assurance. Second Edition. New York, NY: Van Nostrand Reinhold, p. 7. [12] Schulmeyer and McManus. Handbook of Software Quality Assurance, p. 5. [13] Schulmeyer and McManus. Handbook of Software Quality Assurance, p. 184. [14] Schulmeyer and McManus. Handbook of Software Quality Assurance, p. 169. [15] Walsh, J. Preliminary Defect Data from the Iterative Development of a Large C++ Program. Vancouver, Canada: OOPSLA'92. [16] Lorenz, M., and Kidd, J. 1994. Object-Oriented Software Metrics. Upper Saddle River, NJ: Prentice Hall. [17] Chidamber, S., and Kemerer, C. 1993. A Metrics Suite for Object-Oriented Design. Cambridge, MA: MIT Sloan School of Management. [18] Kan, S. H. 2002. Metrics and Models in Software Quality Engineering. Second Edition. Boston, MA: Addison-Wesley. [19] Kemerer, C, and Darcy, D. November/December 2005. OO Metrics in Practice. IEEE Software^. 17. [20] Stix, Α., and Mosley, P. H. 2002. Cognitive Complexities Confronting Software Developers Utilizing Object Technology. The Proceedings ofISECON2002 vol. 19, §342a. [21] Maksimchuk, R. Α., and Naiburg, E. J. 2004. UML for Mere Mortals. Boston, MA: Addison-Wesley, p. 208. [22] Schmucker, K. 1986. Object-Oriented Programming for the Macintosh. Has- brouk Heights, NJ: Hayden, p. 11. [23] Taylor, D. 1992. Object-Oriented Information Systems. New York, NY: John Wiley and Sons. [24] Pinson,L., and Wiener, R. \990. Applications of Object-Oriented Programming. Reading, MA: Addison-Wesley. [25] Hantos, P. February 2005. Inherent Risks in Object-Oriented Development. CrossTalk, The Journal of Defense Software Engineering, p. 13-16; Fig. 2. Accessed in January 2007 at www. stsc.hill.af .mil. [26] Meyer, B. 1995. Object Success: A Manager's Guide to Object-Oriented Technology and Its Impact on the Corporation. Upper Saddle River, NJ: Prentice Hall.
Примечания 625 [27] Boehm, В. 1989. Software Risk Management (Tutorial). New York, NY: IEEE Computer Society Press. [28] Boehm, B. October 2002. Software Risk Management: Overview and Recent Developments. 17th International Forum on COCOMO and Software Cost Modeling. Los Angeles, CA: University of Southern California Center for Software Engineering. [29] Lyons, B. 2005. Private communication. [30] Там же Часть III. Приложения Minsky, Μ. April 1970. Form and Content in Computer Science. Journal of the Association for Computing Machinery vol. 17(2), p. 197. Глава 8. Архитектура системы: спутниковая навигация [1] International Council on Systems Engineering (INCOSE). June 2006. Systems Engineering Handbook. INCOSE-TP-2003-016-02, Version 3. Seattle, WA; INCOSE, app. 8. [2] INCOSE. June 2004. Systems Engineering Handbook. INCOSE-TP-2003-016- 02, Version 2a. Seattle, WA: INCOSE, p. 293. [3] The Aerospace Corporation. 2003. GPSPrimer-A Student Guide to the Global Positioning System, p. 2. Accessed in January 2007 at www.aero.org/ education/primers/gps/GPS-Primer.pdf. [4] Там же, pp. 2-3. [5] Там же, р. 4. [6] Там же, р. 5. [7] Там же, р. 6. [8] Rumbaugh, J., Jacobson, I., and Booch, G. 2005. The Unified Modeling Language Reference Manual Second Edition. Boston, MA: Addison-Wesley, p. 37. [9] Maier, M. W., Emery, D., and Hilliard, R. 2004. ANSI/IEEE 1471 and Systems Engineering. Systems Engineering vol. 7(3), p. 257. [10] Там же, р. 269. [11] Krikorian, H. F. March/April 2003. Introduction to Object-Oriented Systems Engineering, Part 1. IT Professional, p. 40. [12] Jacobson, I., Ericsson, M., and Jacobson, A. 1994. The Object Advantage: Business Process Reengineering with Object Technology. Wokingham, England: Addison-Wesley, pp. 319-337.
626 Примечания Глава 9. Система управления: контроль трафика [1] Murphy, Ε. December 1988. АН Aboard for Solid State. IEEE Spectrum vol. 25(13), p. 42. [2] Rockwell Advanced Railroad Electronic Systems. 1989. Cedar Rapids, LA: Rockwell International. [3] Tanenbaum, A. 1981. Computer Networks. Englewood Cliffs, NJ: Prentice-Hall. Глава 10· Искусственный интеллект: криптоанализ [1] Erman, L., Lark, J., and Hayes-Roth, F. December 1988. ABE: An Environment for Engineering Intelligent Systems. IEEE Transactions on Software Engineering vol. 14(12), p. 1758. [2] Shaw, M. 1991. Heterogeneous Design Idioms for Software Architecture. Pittsburgh, PA: Carnegie Mellon University. [3] Meyer, C, and Matyas, S. M. 1982. Cryptography. New York, NY: John Wiley and Sons, p. 1. [4] Nii, P. Summer 1986. Blackboard Systems: The Blackboard Model of Problem Solving and the Evolution of Blackboard Architectures. AI Magazine vol. 7(2), p. 46. [5] Englemore, R., and Morgan, T. 1988. Blackboard Systems. Wokingham, England: Addison-Wesley, p. 16. [6] Там же, р. 19. [7] Там же, р. 6. [8] Там же, р. 12. [9] Nii. Blackboard Systems, p. 43. [10] Englemore and Morgan. Blackboard Systems, p. 11. Глава 12: Web-приложение: планирование поездок [1] Conallen, J. 2003. Building Web Applications with UML. Second Edition. Boston, MA: Addison-Wesley. [2] Eeles, P., Houston, Κ. Α., and Kozaczynski, W. 2003. Building J2EE Applications with the Rational Unified Process. Boston, MA: Addison-Wesley. [3] Kruchten, P. November 1995. The 4+1 View Model of Architecture. IEEE Software 12(6), pp. 42-50. [4] Alur, D., Crupi, J., and Malks, D. 2003. Core J2EE Patterns: Best Practices and Design Strategies. Second Edition. Upper Saddle River, NJ: Prentice Hall. [5] Marinescu, F. 2002. EJB Design Patterns. New York, NY: John Wiley.
Примечания 627 Приложение 1. Объектно-ориентированные языки программирования [1] Wulf, W. January 1980. Trends in the Design and Implementation of Programming Languages. IEEE Computer vol. 13(1), p. 15. [2] The Language List, a compendium of programming languages, originating in the Usenet news group comp.lang.misc, currently maintained by Bill Kinners- ley. http://people.ku.edu/~nkinners/LangList/Extras/ langlist.htm. [3] Birtwistle, G., Dahl, O-J., Myhrhaug, В., and Nygard, K. 1979. Simula begin. Lund, Sweden: Studentlitteratur. [4] Eric Levenez's Web site on computer language history: www. levenez. com/ lang/. [5] The TIOBE Programming Community Index: www.tiobe.com/tiobe_ index/index.htm. [6] The Smalltalk Web site: www.smalltalk.org/smalltalk/history.html. [7] Ingalls, D. The Smalltalk-76 Programming System Design and Implementation. Proceedings of the Fifth Annual ACM Symposium on Principals of Programming Languages, ACM, p. 9. [8] Borning, Α., and Ingalls, D. 1982. Multiple Inheritance in Smalltalk-80. Proceedings of the National Conference on Artificial Intelligence. Menlo Park, CA: AAAI. [9] Goldberg, Α., and Robson, D. 1989. Smalltalk-80: The Language. Reading, MA: Addison-Wesley. [10] Goldberg, A. 1984. Smalltalk-80: The Interactive Programming Environment. Reading, MA: Addison-Wesley. [11] Krasner, G. 1983. Smalltalk-80: Bits of History, Words of Advice. Reading, MA: Addison-Wesley. [12] LaLonde, W., and Pugh, J. 1990. Inside Smalltalk, Volumes 1 and 2. Englewood Cliffs, NJ: Prentice Hall. [13] Stroustrup, B. 2000. The C+ Programming Language. Special Third Edition. Boston, MA: Addison-Wesley, p. 4. [14] Gorlen, K. 1989. An Introduction to C++. In Unix System V AT&T C++ Language System, Release 2.0 Selected Readings. Murray Hill, NJ: AT&T Bell Laboratories, p. 2-1. [15] Ellis, M., and Stroustrup, B. 1990. The Annotated C++ Reference Manual. Reading, MA: Addison-Wesley.
628 Примечания [16] Stroustrup, В. 2003. The C++ Standard: Incorporating Technical Corrigendum No. 1. Second Edition. New York, NY: John Wiley & Sons. [17] Stroustrup, B. 1991. The C++ Programming Language. Second Edition. Reading, MA: Addison-Wesley. [18] Stroustrup, B. 1994. The Design and Evolution of C++. Reading, MA: Addison- Wesley. [19] The Java Language: An Overview. Accessed in January 2007 at http:// Java.sun.com/docs/overviews/Java/Java-overview-1.html. [20] International Committee for Information Technology Standards. January 1998. Programming Language Smalltalk. Document Number ANSI/INCITS 319- 1998.
ГЛОССАРИЙ CRC-карточки (CRC cards). Класс/Обязанности/Сотрудниьси (Class/Responsibilities/Collaborators); простой инструмент анализа, позволяющий выявить ключевые абстракции и механизмы системы. Unified Modelling Language (UML). Язык (система обозначений), используемый при объектно-ориентированном анализе и проектировании для моделирования свойств создаваемой системы. Абстрактная операция (abstract operation). Объявленная, но не реализованная операция в абстрактном классе. Абстрактный класс (abstract class). Класс, не имеющий экземпляров. Абстрактный класс создается в предположении, что его структура и поведение будут уточнены конкретными подклассами, как правило, с помощью абстрактных операций. Абстракция (abstraction). Существенная характеристика объекта, отличающая его от всех других объектов и четко определяющая его концептуальные границы с точки зрения наблюдателя; процесс выявления основных свойств объекта. Один из основных элементов объектной модели. Агрегация (aggregation). Полное или частичное отношение, в котором один объект состоит из одного или нескольких других объектов, каждый из которых рассматривается как часть целого. Это отношение является слабой формой отношения включения (containment), в котором сроки жизни целого и его частей не зависят друг от друга. Активный объект (active object). Объект, имеющий собственный поток управления. Алгоритмическая декомпозиция (algorithmic decomposition). Процесс разделения системы на части, каждая из которых отражает этап более крупного процесса. Применение методов структурного проектирования приводит к алгоритмической декомпозиции, сосредоточенной на потоке управления внутри системы.
630 Глоссарий Архитектура (architecture). Логическая и физическая структура компонентов системы и взаимосвязей между ними, сформированная всеми стратегическими и тактическими проектными решениями. Архитектурный механизм (architectural mechanism). Представление общего потенциала системы, взаимосвязанное с основной функциональностью системы или поддерживающее ее. Ассоциация (association). Отношение, означающее некоторую семантическую связь между классами. Атрибут (attribute). Часть составного объекта (агрегата). Базовый класс (base class). Наиболее общий класс в какой-либо структуре классов. В большинстве приложений есть много таких корневых классов. В некоторых языках программирования определяется первичный базовый класс, являющийся исходным суперклассом для всех классов. Видимость (visibility). Способность одной абстракции видеть другую и ссылаться на ее ресурсы извне. Абстракции являются видимыми друг для друга, только если они находятся в одном пространстве видимости. Контроль экспорта переменных может еще более ограничить доступ к видимым абстракциям. Примерами разной степени видимости могут быть разделы public, private, protected и package. Виртуальная функция (virtual function). Некая операция над каким-то объектом. Обобщенная функция класса может быть переопределена в подклассах; таким образом, для конкретного объекта ее реализация определяется неким множеством методов, объявленных в разных классах, входящих в иерархию наследования. Термины обобщенная функция и виртуальная функция являются синонимами. Вызов (process). Активизация одного потока управления. Действующее лицо (actor). Сущность, определяющая роль, которую внешняя сущность играет во взаимодействии с системой. Делегирование (delegation). Действие объекта, поручающего выполнение операции другому объекту, вместо того, чтобы выполнить ее самому. Деструктор (destructor). Операция, освобождающая состояние объекта и/или уничтожающая сам объект. Деятельность (activity). Спецификация поведения, содержащая узлы операций, узлы управления и узлы объектов. Диаграмма классов (class diagram). Часть системы обозначений объектно-ориентированного проектирования; используется для демонстрации существования классов и их взаимоотношений в логической схеме. Диаграмма классов может представлять как всю структуру классов, так и ее часть.
Глоссарий 631 Диаграмма конечных автоматов (state machine diagram). Часть обозначений объектно-ориентированного проектирования; используется для демонстрации пространства состояний данного класса, событий, вызывающих переход из одного состояния в другое, и действий, являющихся результатом изменения состояния. Диаграмма объектов (object diagram). Часть системы обозначений объектно- ориентированного проектирования, используемая, чтобы продемонстрировать существование объектов и отношения между ними в логической схеме системы. Диаграмма объектов может полностью или частично представлять объектную структуру и главным образом иллюстрирует семантику механизмов в логической схеме. Отдельная диаграмма объектов представляет собой моментальный снимок событий или переменных конфигураций объектов, сделанный в конкретный момент времени. Динамическое связывание (dynamic binding). Связывание, при котором ассоциация между именем и классом не устанавливается, пока объект с заданным именем не будет создан в ходе выполнения программы. Друг (friend). Класс или операция, имеющие доступ к закрытым операциям или данным другого класса. Объявление дружественных классов или операций является исключительным правом класса, открывающего доступ к своему закрытому разделу. Закрытый раздел (private). Часть интерфейса какого-либо класса или объекта, недоступная для других классов или объектов. Защищенная часть (protected). Часть интерфейса какого-либо класса или объекта, недоступная для других классов или объектов, за исключением подклассов. Индивидуальность (identity). Природа объекта, отличающая его от всех остальных объектов. Иерархия (hierarchy). Ранжирование или упорядочение абстракций. Наиболее типичными иерархиями в сложной системе являются структура классов (включая иерархию "общее/частное" ("is а")) и структура объектов (включая иерархию "целое/часть" ("part of')). Кроме того, иерархии можно обнаружить в архитектурах сложных систем. Инвариант (invariant). Логическое выражение некоторого условия, истинность которого необходимо гарантировать. Инкапсуляция (encapsulation). Процесс разделения элементов абстракции, определяющих ее структуру и поведение. Инкапсуляция отделяет контрактный интерфейс абстракции от его реализации.
632 Глоссарий Интерфейс (interface). Внешний вид класса, объекта, компонента или сложной структуры, демонстрирующий их абстрактные свойства и скрывающий их внутреннее устройство и секреты поведения. Итератор (iterator). Операция, позволяющая получать доступ к частям объекта. Квалификатор (qualifier). Атрибут, однозначно идентифицирующий отдельный целевой объект. Класс (class). Множество объектов, имеющих общую структуру и одинаковое поведение. Термины класс и тип обычно (но не всегда) являются синонимами. Класс отличается от типа тем, что он концентрируется на классификации структуры и поведения. Клиент (client). Объект, пользующийся услугами другого объекта, либо выполняя операции над последним, либо ссылаясь на его состояние. Ключевая абстракция (key abstraction). Класс или объект, являющийся частью словаря предметной области. Композиция (composition). Полное или частичное отношение, в котором один объект состоит из одного или нескольких других объектов, каждый из которых рассматривается как часть целого. Это отношение является сильной формой агрегации, в которой время жизни целого и его частей зависят друг от друга. Компонент (component). Логическая совокупность классов, взаимодействующих вместе для обеспечения набора услуг, предлагаемых посредством интерфейса. Услуги, требуемые компонентом, запрашиваются с помощью соответствующих интерфейсов. Кроме того, компонент может состоять из других компонентов и быть вложенным в другой компонент. Конкретизация (instantiation). Процесс подстановки параметров шаблона обобщенного или параметризованного класса для создания класса, который может иметь экземпляры. (Часто переводится как инстанцирование. — Примеч. ред.). Конкретный класс (concrete class). Класс, реализация которого является завершенной и который, благодаря этому, может иметь экземпляры. Конструктор (constructor). Операция, создающая объект и/или инициализирующая его состояние. Контейнерный класс (container class). Класс, экземпляры которого содержат другие объекты. Контейнерный класс может описывать как однородные (когда все объекты, включенные в коллекцию, относятся к одному и тому же классу), так и неоднородные совокупности (когда объекты, включенные в коллекцию, могут относиться к разным классам, хотя все они обладают свойствами общего суперкласса). Контейнерные классы часто реализуются
Глоссарий 633 с помощью параметризованных классов, в которых класс объектов, содержащихся в контейнере, задается определенным параметром. Кооперация (collaboration). Процесс, в котором несколько элементов модели взаимодействуют, для того чтобы обеспечить определенное поведение верхнего уровня. Метакласс (metaclass). Класс классов; класс, экземпляры которого сами являются классами. Метод (method). Операция над объектом, определенная как часть объявления класса. Все методы являются операциями, но не все операции являются методами. Термины функция-член и метод — синонимы. В некоторых языках программирования методы представляют собой самостоятельные сущности и могут переопределяться в подклассах, в то время как в других языках программирования метод не может быть переопределен и является частью реализации обобщенных, или виртуальных функций, которые можно переопределять в подклассах. Механизм (mechanism). Структура, с помощью которой объекты взаимодействуют друг с другом, обеспечивая поведение, удовлетворяющее требованиям системы. Модульность (modularity). Свойство системы, которое состоит в разделении слабосвязанных (loosely coupled) между собой компонентов, образующих одно целое (cohesive). Мономорфизм (monomorphism). Концепция теории типов, согласно которой имена (например, объявления переменных) могут обозначать только объекты одного и того же класса. Мощность (cardinality). Количество экземпляров класса; количество экземпляров, участвующих в отношениях между классами. Наследование (inheritance). Отношение между классами, при котором класс использует структуру или поведение, определенное в другом классе (одиночное наследование) или нескольких других классах (множественное наследование). Наследование определяет иерархию классов "общее/частное", в которой подкласс наследует свойства одного или нескольких более общих суперклассов. Подкласс обычно конкретизирует суперкласс, дополняя или переопределяя его структуру и поведение. Обобщенная функция (generic function). Операция над каким-то объектом. Обобщенная функция класса может быть переопределена в подклассах; таким образом, для конкретного объекта ее реализация определяется неким множеством методов, объявленных в разных классах, входящих в иерархию наследования. Термины обобщенная функция и виртуальная функция (virtual function) являются синонимами.
634 Глоссарий Обратное проектирование (reverse-engineering). Воссоздание логической или физической модели системы по выполняемому коду. Объект (object). Сущность, которой можно оперировать. Объект имеет состояние, поведение и индивидуальность. Структура и поведение похожих объектов определяются в общем для них классе. Термины экземпляр (instance) и объект являются синонимами. Объектная модель (object model). Совокупность принципов, лежащих в основе объектно-ориентированного проектирования; парадигма программирования, основанная на абстракции, инкапсуляции, модульности, иерархичности, типизации, параллелизме и персистентности. Объектное программирование (object-based programming). Методология программирования, в которой программы представляют собой совокупности взаимодействующих объектов, каждый из которых является экземпляром определенного типа, входящего в иерархию типов, не связанных отношением наследования. В таких программах классы обычно считаются статичными сущностями, а объекты имеют более динамичную природу, ограниченную статическим связыванием и мономорфизмом. Объектно-ориентированное программирование (object-oriented programming). Методология программирования, в которой программы представляют собой совокупности взаимодействующих объектов, каждый из которых является экземпляром определенного класса, входящего в иерархию классов, связанных отношением наследования. В таких программах классы обычно считаются статичными сущностями, а объекты имеют более динамичную природу, поддерживаемую механизмами динамического связывания и полиморфизма. Объектно-ориентированная декомпозиция (object-oriented decomposition). Процесс разбиения системы на части, каждая из которых представляет собой некоторый класс или объект из предметной области. Практическое применение методов объектно-ориентированного проектирования приводит к объектно-ориентированной декомпозиции, позволяющей представить весь мир как совокупность объектов, взаимодействующих друг с другом для обеспечения требуемых функциональных свойств. Объектно-ориентированное проектирование (object-oriented design). Методология проектирования, объединяющая процесс объектно-ориентированной декомпозиции и систему обозначений для представления логической и физической, статической и динамической моделей проектируемых систем. В частности, система обозначений состоит из диаграмм классов, объектов, компонентов и процессов.
Глоссарий 635 Объектно-ориентированный анализ (object-oriented analysis). Метод анализа, в котором требования рассматриваются с точки зрения классов и объектов, включенных в словарь предметной области. Обязанность (responsibility). Поведение, которое обязан обеспечить объект. Ограничение (constraint). Выражение некоторого семантического условия, которое должно выполняться. Операция (operation). Действие, выполняемое одним объектом над другим с определенной целью. Все операции над конкретным объектом сосредоточены в свободных подпрограммах и функциях-членах, или методах. Термины сообщение, метод и операция, как правило, являются синонимами. Ориентирная структура (reference architecture). Заранее определенный архитектурный шаблон или набор шаблонов, полностью или частично конкретизированный, разработанный и испытанный на конкретных примерах, в сочетании с артефактами, облегчающими его использование. Открытая часть (public). Часть интерфейса какого-либо класса, объекта или модуля, доступная для всех классов, объектов и модулей. Параллелизм (concurrency). Свойство, отличающее активные объекты от неактивных. Параллельный объект (concurrent object). Активный объект, семантика которого обеспечивается многопоточной средой. Параметризованный класс (parameterized class). Класс, играющий роль шаблона для других классов. Параметрами шаблона могут быть классы, объекты и/или операции. Шаблонный класс должен быть конкретизирован (с помощью подстановки параметров) до того, как будут созданы объекты. Шаблонные классы, как правило, используются как контейнеры. Термины шаблонный класс и параметризованный класс являются синонимами. Пассивный объект (passive object). Объект, не имеющий собственного потока управления. Переменная экземпляра (instance variable). Место хранения части состояния объекта. Совокупность переменных экземпляра определяет структуру объекта. Термины поле (field), переменная экземпляра (instance variable), член объекта (member object) и слот (slot) являются синонимами. Переход (transition). Переход из одного состояния в другое. Персистентность (persistence). Способность объекта существовать во времени и пространстве дольше своего создателя, перемещаясь из одного диапазона адресов в другой. Поведение (behavior). Действия и реакции объекта, выраженные в терминах изменения состояния и передачи сообщений; видимая извне и воспроизводимая функция объекта.
636 Глоссарий Подкласс (subclass). Класс, наследующий свойства одного или нескольких классов (непосредственными суперклассами). Подсистема (subsystem). Совокупность компонентов, одна часть которых доступна для других подсистем, а друга часть — недоступна. Поле (field). Место хранения части состояния объекта; совокупность полей объекта определяет его структуру. Термины поле (field), переменная экземпляра (instance variable), член объекта (member object) и слот (slot) — синонимы. Полиморфизм (polymorphism). Концепция теории типов, согласно которой имена (например, объявления переменных) могут обозначать объекты разных классов, имеющих общий суперкласс. Следовательно, объекты, обозначаемые полиморфным именем, могут по-разному выполнять общий набор операций. Последовательный объект (sequential object). Пассивный объект, семантика которого гарантируется при наличии только одного потока управления. Постусловие (postcondition). Инвариант, обеспечиваемый операцией. Поток управления (thread of control). Отдельный процесс. Активизация потока управления приводит к возникновению независимого динамического действия в системе. Система может иметь несколько одновременно выполняемых потоков, некоторые из них могут динамически активизироваться и прекращаться. Истинная многопоточность возможна лишь в многопроцессорных системах, в то время как на однопроцессорных компьютерах возможна только иллюзия многопоточности. Предусловие (precondition). Инвариант, предполагаемый операцией. Пространство состояний (state space). Перечисление всех возможных состояний объекта. Пространство состояний объекта содержит неопределенное, но конечное число возможных состояний (не обязательно желаемых или ожидаемых). Протокол (protocol). Способы, с помощью которых объекты могут действовать и реагировать, образуя полное статическое и динамическое представление объекта. Протокол объекта определяет допустимое поведение объекта. Прототип поведения (behavioral prototype). Пример, позволяющий исследовать некоторый элемент системы, например, определенный аспект архитектуры, новый алгоритм, модель пользовательского интерфейса или схему базы данных. Его цель — обеспечить быстрое изучение альтернативных проектных решений, для того чтобы минимизировать риск, не подвергая риску систему. Процессор (processor). Часть аппаратного обеспечения, имеющая вычислительные ресурсы.
Глоссарий 637 Прямое проектирование (forward-engineering). Создание исполняемого кода по логической или физической модели. Раздел (partition). Компоненты или подсистемы, образующие часть определенного уровня абстракции. Кроме того, разделом называется структурная часть диаграммы процесса, или "дорожка " ("swimlane"). Реактивная система (reactive system). Система, управляемая событиями. Поведение реактивной системы не является простым отображением "вход-выход". Реализация (implementation). Внутреннее представление класса или объекта, включая секреты его поведения. Роль (role). Способность или цель взаимодействия класса или объекта с другими сущностями. Роль объекта определяет выбор точно определенных особенностей поведения объекта в конкретный момент времени. Роль — это грань объекта, которую он демонстрирует миру в данный момент. Свободная подпрограмма (free subprogram). Процедура или функция, представляющая собой непримитивную операцию над объектом или объектами одного и того же или разных классов. Свободная подпрограмма — это любая подпрограмма, не являющаяся методом какого-либо объекта. Связывание (binding). Установление соответствия между именем (например, объявлением переменной) и классом. Связь (link). Отношение между объектами; экземпляр ассоциации. Сервер (server). Объект, который никогда не воздействует на другие объекты, а является предметом воздействия других объектов; объект, предоставляющий определенные услуги. Сигнатура (signature). Полная спецификация формальных аргументов и возвращаемого значения операций. Сильная типизация (strongly typed). Свойство языка программирования, в соответствии с которым во всех выражениях гарантируется согласованность типов. Синхронизация (synchronization). Семантика параллельности операции. Существуют следующие виды операций: простая (simple), если задействован только один поток управления; синхронная (synchronous), если встречаются только два потока; задержка (balking), если встреча происходит только в том случае, когда одному из потоков приходится ждать; простой (timeout), если встреча происходит, когда один процесс ждет другого определенное время; и асинхронная (asynchronous), если два процесса протекают независимо друг от друга.
638 Глоссарий Система реального времени (real-time system). Система, в которой существенные процессы должны выполняться за определенное время. "Жесткая" система реального времени должна быть детерминированной, поскольку нарушение временных рамок в такой системе может привести к катастрофическим результатам. Словарь данных (data dictionary). Полный перечень всех классов в системе. Слот (slot). Место хранения части состояния объекта. Совокупность слотов образует структуру объекта. Термины поле (field), переменная экземпляра (instance variable), член объекта (member object) и слот (slot) являются синонимами. Событие (event). Некое явление, способное изменить состояние системы. Сокрытие информации (information hiding). Процесс сокрытия всех секретов объекта, которые не относятся к его существенным характеристикам. Обычно скрывается структура объекта и реализация его методов. Сообщение (message). Операция, которую один объект может выполнять над другим. Термины сообщение, метод и операция, как правило, являются синонимами. Состояние (state). Совокупный результат поведения объекта; одно из возможных условий, в которых объект может существовать, описанное с помощью количественных параметров, отличающихся от других. В любой конкретный момент времени состояние объекта включает в себя перечень всех (как правило, статических) свойств объекта и текущие (как правило, динамические) значения каждого из этих свойств. Среда (framework). Совокупность классов, предоставляющих набор услуг в определенной предметной области. Таким образом, среда экспортирует отдельные классы и механизмы, которые клиенты могут использовать или адаптировать. Статическое связывание (static binding). Установление соответствия между именем и классом на этапе компиляции, но до создания объекта. Сторожевое условие (guard). Логическое выражение, применяемое к событию. Если выражение является истинным, то событие приводит к изменению состояния системы. Стратегическое проектное решение (strategic design decision). Проектные решения, имеющие сильное влияние на архитектуру. Структура (structure). Конкретное представление состояния объекта. Каждый объект имеет свое собственное состояние, отличающееся от состояния других объектов. Тем не менее, все объекты одного и того же класса имеют одинаковое представление состояния.
Глоссарий 639 Структура классов (class structure). Граф, вершины которого соответствуют классам, а ребра — отношениям между ними. Структура классов системы представляется в виде совокупности диаграмм классов. Структура объекта (object structure). Граф, вершины которого соответствуют объектам, а ребра — отношениям между объектами. Объектная структура системы представляется в виде совокупности диаграмм объектов. Структурное проектирование (structured design). Метод проектирования, основанный на алгоритмической декомпозиции. Суперкласс (superclass). Класс, свойства которого наследуются другими классами (непосредственными подклассами). Сценарий (scenario). Набор событий, выявляющий определенный аспект поведения системы. Тактическое проектное решение (tactical design decision). Проектное решение, имеющее локальное влияние на архитектуру системы. Тип (type). Определение области допустимых значений, которые может принимать объект, и совокупности операций, которые могут выполняться над объектом. Термины класс и тип, как правило (но не всегда), являются синонимами. Концепция типа немного отличается от концепции класса тем, что в классе основное внимание сосредоточено на поддержке общего протокола. Типизация (typing). Механизм, препятствующий замене объектов одного типа на объекты другого типа или, в крайнем случае, сильно ограничивающий возможности такой замены. Узел объекта (object node). Один из трех типов узлов, являющихся составной частью процесса (activity). Узел объекта определяет потоки между действиями, образующими процесс. Узел операции (action node). Один из трех типов узлов, являющихся составной частью процесса (activity). В системе UML 2 определены допустимые типы действий, к которым относятся типы, ссылающиеся на поведение операции (operation) или функции (activity). Узел управления (control node). Один из трех типов узлов, являющихся составной частью процесса (activity). Он обеспечивает начало, остановку и функциональную последовательность действий, составляющих процесс. Управление доступом (access control). Механизм управления доступом к элементам модели, содержимому пакета, структуре или операциям класса. См. также Видимость. Уровень (layer). Совокупность компонентов, относящихся к одному и тому же уровню абстракции.
640 Глоссарий Уровень абстракции (level of abstraction). Относительное упорядочение абстракций в структурах классов, объектов, компонентов или процессов. В терминах иерархии "часть/целое" ("part of) абстракция более высокого уровня раскладывается на абстракции более низкого уровня; в терминах иерархии "общее/частное" ("is а") высокоуровневые абстракции являются обобщенными, а низкоуровневые — специализированными. Услуга (service). Поведение, обеспечиваемое определенной частью системы. Устройство (device). Часть аппаратуры, не имеющая собственных вычислительных ресурсов. Функциональная точка (function point). В контексте анализа требований к системе — отдельный процесс, видимый извне и поддающийся проверке. Функция (function). Преобразование входных данных в выходные, определяемое поведением объекта. Функция-член (member function). Операция над объектом, определенная как часть объявления класса. Все функции-члены являются операциями, но не все операции являются функциями-членами. Термины функция-член и метод (method) — синонимы. В некоторых языках программирования функции-члены представляют собой самостоятельные сущности и могут переопределяться в подклассах, в то время как в других языках программирования функция-член не может быть переопределена и является частью реализации обобщенных, или виртуальных функций, которые можно переопределять в подклассах. Член объекта (member object). Место хранения части состояния объекта. Члены объекта полностью определяют его структуру. Термины поле (field), переменная экземпляра (instance variable), член объекта (member object) и слот (slot) являются синонимами. Шаблонный класс (template class). Класс, играющий роль шаблона для других классов. Параметрами шаблона могут быть классы, объекты и/или операции. Шаблонный класс должен быть конкретизирован (с помощью подстановки параметров) до того, как будут созданы объекты. Шаблонные классы, как правило, используются как контейнеры. Термины шаблонный класс и параметризованный класс являются синонимами. Экземпляр (instance). Сущность, которой можно оперировать. Экземпляр имеет состояние, поведение и индивидуальность. Структура и поведение похожих экземпляров определяются в общем для них классе. Термины экземпляр (instance) и объект являются синонимами.
БИБЛИОГРАФИЯ Библиография состоит из разделов, обозначенных буквами. В приложении 2 ссылка на пункт библиографии имеет вид [<метка раздела><год>]. Например, ссылка Brooks [3 1975] относится к книге F.Brooks, The Mythical Man-Month, изданной в 1975 году, указанной в разделе "Разработка программного обеспечения". А. Классификация Allen, Т., and Starr, Т. 1982. Hierarchy: Perspectives for Ecological Complexity. Chicago, IL: The University of Chicago Press. Aquinas, T. Summa Theologica., vol. 19 of Great Books of the Western World. Chicago, IL: Encyclopedia Britannica. Aristotle. Categories., vol. 8 of Great Books of the Western World. Chicago, IL: Encyclopedia Britannica. Bateson, G. 1979. Mind and Nature: A Necessary Unity. New York, NY: Bantam Books. Brachman, R., McGuinness, D., Patel-Schneider, P., and Resnick, L. Living with Classic. Principles of Semantic Networks. San Mateo, CA: Morgan Kaufman Publishers. Bulman, D. January 1991. Refining Candidate Objects. Computer Language, vol. 8(1). Cant, S., Jeffery, D., and Henderson-Sellers, B. October 1991. ^4 Conceptual Model of Cognitive Complexity of Elements of the Programming Process. New South Wales, Australia: University of New South Wales. Classification Society of North America. Journal of Classification. New York, NY: Springer-Verlag. Coad, P. September 1992. Object-Oriented Patterns. Communications of the ACM, vol. 35(9). Coad, P. 1993. The Object Game. Austin, TX: Object International.
642 Библиография Coombs, С, Raiffa, H., and Thrall, R. 1954. Some Views on Mathematical Models and Measurement Theory. Psychological Review, vol. 61(2). Courtois, P. June 1985. On Time and Space Decomposition of Complex Structures. Communications of the ACM, vol. 28(6). Cunningham, W., and Beck, K. July/August 1989. Constructing Abstractions for Object-Oriented Abstractions. Journal of Object-Oriented Programming, vol. 2(2). Darwin, С The Origin of Species., vol. 49 of Great Books of the Western World. Chicago, IL: Encyclopedia Britannica. Descartes, R. Rules for the Direction of the Mind., vol. 31 of Great Books of the Western World. Chicago, IL: Encyclopedia Britannica. Flood, R., and Carson, E. 1988. Dealing with Complexity. New York, NY: Plenum Press. ι - Gould, S. June 1992. We Are All Monkey's Uncles. Natural History. Johnson, R. 1992. Documenting Frameworks Using Patterns. Vancouver, Canada: OOPSLA'92. Lakoff, G. 1987. Women, Fire, and Dangerous Things: What Categories Reveal about the Mind. Chicago, IL: The University of Chicago Press. Lefrancois, G. 1977. Of Children: An Introduction to Child Development. Second Edition. Belmont, CA: Wadsworth. Lewin, R. November 4, 1988. Family Relationships Are a Biological Conundrum. Science, vol. 242. Maccoby, M. December 1991. The Innovative Mind at Work. IEEE Spectrum, vol. 28(12). Maier, H. 1969. Three Theories of Child Development: The Contributions of Erik H. Erickson, Jean Piaget, and Robert R. Sears, and Their Applications. New York, NY: Harper and Row. May, R. September 16, 1988. How Many Species Are There on Earth. Science, vol. 241. Michalski, R., and Stepp, R. 1983. Learning from Observation: Conceptual Clustering. In Machine Learning: An Artificial Intelligence Approach, ed. R. Michalski, J. Carbonell, and T. Mitchell. Palo Alto, CA: Tioga. Miller, G. March 1956. The Magical Number Seven, Plus or Minus Two: Some Limits on Our Capacity for Processing Information. The Psychological Review, vol. 63(2). Minsky, M. April 1970. Form and Content in Computer Science. Journal of the ACM, vol. 17(2).
Библиография 643 Minsky, M. 1986. The Society of Mind. New York, NY: Simon and Schuster. Moldovan, D., and Wu, С December 1988. A Hierarchical Knowledge-Based System for Airplane Classification. IEEE Transactions on Software Engineering, vol. 14(12). Newell, A. 1990. Unified Theories of Cognition. Cambridge, MA: Harvard University Press. Newell, Α., and Simon, H. 1972. Human Problem Solving. Englewood Cliffs, NJ: Prentice Hall. Papert, S. 1980. Mindstorms: Children, Computers, and Powerful Ideas. New York, NY: Basic Books. Plato. Statesman., vol. 7 of Great Books of the Western World. Chicago, IL: Encyclopedia Britannica. Prieto-Diaz, R., and Arango, G. 1991. Domain Analysis and Software System: Mod- eling. Las Alamitos, CA: Computer Society Press of the IEEE. Shaw, M. 1989. Larger Scale Systems Require Higher-Level Abstractions. Proceedings of the Fifth International Workshop on Software Specification and Design. IEEE Computer Society. Shaw, M. 1990. Elements of a Design Language for Software Architecture. Pittsburgh, PA: Carnegie Mellon University. Shaw, M. 1991. Heterogeneous Design Idioms for Software Architecture. Pittsburgh, PA: Carnegie Mellon University. Siegler, R., and Richards, D. 1982. The Development of Intelligence. In: Handbook of Human Intelligence, ed. R. Sternberg. Cambridge, United Kingdom: Cambridge University Press. Simon, H. 1962. The Architecture of Complexity. Proceedings of the American Philosophical Society у vol. 106. Simon, H. 1982. The Sciences of the Artificial. Cambridge, MA: The MIT Press. Sowa, J. 1984. Conceptual Structures: Information Processing in Mind and Machine. Reading, MA: Addison-Wesley. Sowa, J. 1991. Principles of Semantic Networks. San Mateo, CA: Morgan Kaufman Publishers. Stepp, R., and Michalski, R. 1986. Conceptual Clustering of Structured Objects: A Goal-Oriented Approach. Artificial Intelligence, vol. 28(1). Stevens, S. June 1946. On the Theory of Scales of Measurement. Science, vol. 103 (2684).
644 Библиография Stillings, Ν., Feinstein, Μ., Garfield, J., Rissland, Ε., Rosenbaum, D., Weisler, S., and Baker-Ward, L. 1987. Cognitive Science: An Introduction. Cambridge, MA: The MIT Press. Waldrop, M. 1992. Complexity: The Emerging Science at the Edge of Order and Chaos. New York, NY: Simon and Schuster. Б. Объектно-ориентированный анализ Arango, G. May 1989. Domain Analysis: From Art Form to Engineering Discipline. SIGSOFT Engineering Notes, vol. 14(3). Bailin, S. 1988. Remarks on Object-Oriented Requirements Specification. Laurel, MD: Computer Technology Associates. Bailin, S., and Moore, J. 1987. An Object-Oriented Specification Method for Ada. Laurel, MD: Computer Technology Associates. Barbier, F. May 1992. Object-Oriented Analysis of Systems through Their Dynamical Aspects. Journal of Object-Oriented Programming, vol. 5(2). Borgida, Α., Mylogoulos, J., and Wong, H. 1984. Generalization/Specialization as a Basis for Software Specification. In: On Conceptual Modeling: Perspectives from Artificial Intelligence, Databases, and Programming Languages, ed. M. Brodie, J. Mylopoulos, and J. Schmidt. New York, NY: Springer-Verlag. Cernosek, G., Monterio, E., and Pribyl, W. 1987. An Entity-Relationship Approach to Software Requirements Analysis for Object-Based Development. Houston, TX: McDonnell Douglas Astronautics. Coad, P. Summer 1989. OOA: Object-Oriented Analysis. American Programmer, vol. 2(7-8). Coad, P. April 1990. New Advances in Object-Oriented Analysis. Austin, TX: Object International. Coad, P., and Yourdon, E. 1991. Object-Oriented Analysis. Second Edition. Englewood Cliffs, NJ: Yourdon Press. Dahl, O-J. 1987. Object-Oriented Specifications. In: Research Directions in Object- Oriented Programming, ed. B. Schriver and P. Wegner. Cambridge, MA: The MIT Press. deChampeaux, D. April 1991a. A Comparative Study of Object-Oriented Analysis Methods. Palo Alto, CA: Hewlett-Packard Laboratories. deChampeaux, D. April 1991b. Object-Oriented Analysis and Top-Down Software Development. Palo Alto, CA: Hewlett Packard Laboratories. DeMarco, T. 1979. Structured Analysis and System Specification. Englewood Cliffs, NJ: Prentice Hall.
Библиография 645 Embley, D., Kurtz, В., and Woodfield, S. 1992. Object-Oriented Systems Analysis: A Model-Driven Approach. Englewood Cliffs, NJ: Yourdon Press. EVB Software Engineering. 1989. Object-Oriented Requirements Analysis. Frederick, MD. Gane, C, and Sarson, T. 1979. Structured Systems Analysis. Englewood Cliffs, NJ: Prentice Hall. Hatley, D., and Pirbhai, I. 1988. Strategies for Real-Time System Specification. New York, NY: Dorset House. Ho, D., and Parry, T. July 1991. The Hewlett-Packard Method of Object-Oriented Analysis. Palo Alto, CA: Hewlett-Packard Laboratories. Iscoe, N. 1988. Domain Models for Program Specification and Generation. Austin, TX: University of Texas. Iscoe, N., Browne, J., and Werth, J. 1989. Modeling Domain Knowledge: An Object- Oriented Approach to Program Specification and Generation. Austin, TX: The University of Texas. Lang, N. January 1993. Shlaer-Mellor Object-Oriented Analysis Rules. Software Engineering Notes, vol. 18(1). Marca, D., and McGowan, С 1988. SADT™: Structured Analysis and Design Technique. New York, NY: McGraw-Hill. Martin, J., and Odell, J. 1992. Object-Oriented Analysis and Design. Englewood Cliffs, NJ: Prentice Hall. McMenamin, S., and Palmer, J. 1984. Essential Systems Analysis. New York, NY: Yourdon Press. Mellor, S., Hecht, Α., Tryon, D., and Hywari, W. September 1988. Object-Oriented Analysis: Theory and Practice, Course Notes. San Diego, CA: OOPSLA'88. Moore, J., and Bailin, S. 1988. Position Paper on Domain Analysis. Laurel, MD: Computer Technology Associates. Page-Jones, M., and Weiss, S. Summer 1989. Synthesis: An Object-Oriented Analysis and Design Method. American Programmer, vol. 2(7-8). Rubin, K., and Goldberg, A. September 1992. Object Behavior Analysis. Communications of the ACM, vol. 35(9). Saeki, M., Horai, H., and Enomoto, H. May 1989. Software Development Process from Natural Language Specification. Proceedings of the 11th International Conference on Software Engineering. New York, NY: Computer Society Press of the IEEE. Shemer, I. June 1987. Systems Analysis: A Systemic Analysis of a Conceptual Model. Communications of the ACM, vol. 30(6).
646 Библиография Shlaer, S., and Mellor, S. 1988. Object-Oriented Systems Analysis: Modeling the World in Data. Englewood Cliffs, NJ: Yourdon Press. Shlaer, S., and Mellor, S. July 1989. An Object-Oriented Approach to Domain Analysis. Software Engineering Notes, vol. 14(5). Shlaer, S., and Mellor, S. Summer 1989. Understanding Object-Oriented Analysis. American Programmer, vol. 2(7-8). Shlaer, S., and Mellor, S. 1992. Object Lifecycles: Modeling the World in States. Englewood Cliffs, NJ: Yourdon Press. Stoecklin, S., Adams, E., and Smith, S. 1987. Object-Oriented Analysis. Tallahassee, FL: East Tennessee State University. Sully, P. Summer 1989. Structured Analysis: Scaffolding for Object-Oriented Development. American Programmer, vol. 2(7-8). Tsai, J., and Ridge, J. November 1988. Intelligent Support for Specifications Transformation. IEEE Software, vol. 5(6). Veryard, R. 1984. Pragmatic Data Analysis. Oxford, England: Blackwell Scientific Publications. Ward, P. March 1989. How to Integrate Object Orientation with Structured Analysis and Design. IEEE Software, vol. 6(2). Weinberg, G. 1988. Rethinking Systems Analysis and Design. New York, NY: Dorset House. В. Объектно-ориентированные приложения Abdali, К., Cherry, G., and Soiffer, N. November 1986. A Smalltalk System for Algebraic Manipulation. SIGPLAN Notices, vol. 21(11). Abdel-Hamid, Т., and Madnick, S. December 1989. Lessons Learned from Modeling the Dynamics of Software Development. Communications of the ACM, vol. 32(12). The Aerospace Corporation. 2003. GPS Primer—A Student Guide to the Global Positioning System. www.aero.org/education/primers/gps/GPS-Primer.pdf. Almes, G., and Holman, С September 1987. Edmas: An Object-Oriented, Locally Distributed Mail System. IEEE Transactions on Software Engineering, vol. SE- 13(9). Anderson, D. November 1986. Experience with Flamingo: A Distributed, Object- Oriented User Interface System. SIGPLAN Notices, vol. 21(11). Archer, J., and Devlin, M. 1987. Rationale Experience Using Ada for Very Large Systems. Mountain View, CA: Rational.
Библиография 647 Bagrodia, R., Chandy, Μ., and Misra, J. June 1987. A Message-Based Approach to Discrete-Event Simulation. IEEE Transactions on Software Engineering, vol. SE-13(6). Barry, B. October 1989. Prototyping a Real-Time Embedded System in Smalltalk. SIGPLAN Notices, vol. 24(10). Barry, В., Altoft, J., Thomas, D., and Wilson, M. October 1987. Using Objects to Design and Build Radar ESM Systems. SIGPLAN Notices, vol. 22(12). Basili, V., Caldiera, G., and Cantone, G. January 1992. A Reference Architecture for the Component Factory. ACM Transactions on Software Engineering and Methodology, vol. 1(1). Batory, D., and O'Malley, S. October 1992. The Design and Implementation of Hierarchical Software Systems with Reusable Components. ACM Transactions on Software Engineering and Methodology, vol. 1(4). Bezivin, J. October 1987. Some Experiments in Object-Oriented Simulation. SIGPLAN Notices, vol. 22(12). Bhaskar, K., and Peckol, J. November 1986. Virtual Instruments: Object-Oriented Program Synthesis. SIGPLAN Notices, vol. 21(11). Bihair, Т., and Gopinath, P. December 1992. Object-Oriented Real-Time Systems: Concepts and Examples. IEEE Computer, vol. 25(12). Bjornerstedt, Α., and Britts, S. September 1988. AVANCE: An Object Management System. SIGPLAN Notices, vol. 23(11). Bobrow, D., and Stefik, M. February 1986. Perspectives on Artificial Intelligence Programming. Science, vol. 231. Boltuck-Pasquier, J., Grossman, E., and Collaud, G. August 1988. Prototyping an Interactive Electronic Book System Using an Object-Oriented Approach. Proceedings of ECOOP'88: European Conference on Object-Oriented Programming. New York, NY: Springer-Verlag. Bonar, J., Cunningham R., and Schultz, J. November 1986. An Object-Oriented Architecture of Intelligent Tutoring Systems. SIGPLAN Notices, vol. 21(11). Booch, G. 1987. Software Components with Ada: Structures, Tools, and Subsystems. Menlo Park, CA: Benjamin/Cummings. Borning, A. October 1981. The Programming Language Aspects of ThingLab, a Constraint-Oriented Simulation Laboratory. ACM Transactions on Programming Languages and Systems, vol. 3(4). Bowman, W., and Flegal, B. August 1981. ToolBox: A Smalltalk Illustration System. Byte, vol. 6(8).
648 Библиография Britcher, R., and Craig, J. May 1986. Using Modern Design Practices to Upgrade Aging Software Systems. IEEE Software, vol. 3(3). Britton, K., and Parnas, D. December 8, 1981. A-7E Software Module Guide. Report 4702. Washington, DC: Naval Research Laboratory. Brooks, R. 1987. A Hardware Retargetable Distributed Layered Architecture for Mo- bile Robot Control Cambridge, MA: MIT Artificial Intelligence Laboratory. Brooks, R., and Flynn, A. June 1989. Fast, Cheap, and Out of Control: A Robot Invasion of the Solar System. Cambridge, MA: MIT Artificial Intelligence Laboratory. Bruck, D. 1988. Modeling of Control Systems with C++ and PHIGS. Proceedings of USENIXC++ Conference. Berkeley, CA: USENIX Association. Budd, T. January 1989. The Design of an Object-Oriented Command Interpreter. Software—Practice and Experience, vol. 19(1). C++ Booch Components Class Catalog. 1992. Santa Clara, CA: Rational. Call, L., Cohrs, D., and Miller, B. October 1987. CLAM-An Open System for Graphical User Interfaces. SIGPLAN Notices, vol. 22(12). Campbell, R., Islam, N., and Madany, P. 1992. The Design of an Object-Oriented Operating System: A Case Study of Choices. Vancouver, Canada: OOPSLA'92. Caplinger, M. October 1987. An Information System Based on Distributed Objects. SIGPLAN Notices, vol. 22(12). Cargill, T. November 1986. Pi: A Case Study in Object-Oriented Programming. SIGPLAN Notices, vol. 21(11). Carroll, M. September 1990. Building Reusable C++ Components. Murray Hills, NJ: AT&T Bell Laboratories. Cmelik, R., and Genani, N. May 1988. Dimensional Analysis with C++. IEEE Software, vol. 5(3). Coggins, J. September 1990. Design and Management ofC+ Libraries. Chapel Hill, NC: University of North Carolina. Cointe, P., Briot, J., and Serpette, B. 1987. The Formes System: A Musical Application of Object-Oriented Concurrent Programming. In: Object-Oriented Concurrent Programming, ed. Yonezawa and M. Tokoro. Cambridge, MA: The MIT Press. Collins, D. 1990. What Is an Object-Oriented User Interface? Thornwood, NY: IBM Systems Research Education Center. Comeau, G. March 1991. C++ in the Real World: Interviews with C++ Application Developers. The C++ Report, vol. 3(3). Coplien, J. September 1991. Experience with CRC Cards in AT&T. The C++ Report, vol. 3(8).
Библиография 649 Coutaz, J. September 1985. Abstractions for User Interface Design. IEEE Computer, vol. 18(9). Custer, H. 1993. Inside Windows NT. Redmond, WA: Microsoft Press. Dasgupta, P. November 1986. A Probe-Based Monitoring Scheme for an Object- Oriented Operating System. SIGPLAN Notices, vol. 21(11). Davidson, C, and Moseley, R. 1987. An Object-Oriented Real-Time Knowledge-Based System. Albuquerque, NM: Applied Methods. Davis, J., and Morgan, T. January 1993. Object-Oriented Development at Brooklyn Union Gas. IEEE Software, vol. 10(1). deChampeaux, D., Anderson, Α., Lerman, D., Gasperina, M., Feldhousen, E., Glei, M., Fulton, R, Groh, C, Houston, D., Monroe, C, Raj, R., and Shultheis, D. October 1991. Case Study of Object-Oriented Software Development. Palo Alto, CA: Hewlett-Packard Laboratories. Dietrich, W., Nackman, L., and Gracer, F. October 1989. Saving a Legacy with Objects. SIGPLAN Notices, vol. 24(10). Dijkstra, E. May 1968. The Structure of the "THE" Multiprogramming System. Communications of the ACM, vol. 11(5). Durand, G., Benkiran, Α., Durel, C, Nga, H., and Tag, M. 1988. Distributed Mail Service in CSE System. Paris, France: Synergie Informatique et Development. Englemore, R., and Morgan, T. 1988. Blackboard Systems. Wokingham, England: Addison-Wesley. Epstein, D., and LaLonde, W. September 1988. A Smalltalk Window System Based on Constraints. SIGPLAN Notices, vol. 23(11). The European Commission, Directorate-General for Energy and Transportation. 2006. Galileo — The European Satellite Navigation System, http: //ec. europa. eu/dgs/energy_transport/galileo/index_en.htm. Ewing, J. November 1986. An Object-Oriented Operating System Interface. SIGPLAN Notices, vol. 21(11). Fenton, J., and Beck, K. October 1989. Playground: An Object-Oriented Simulation System with Agent Rules for Children of All Ages. SIGPLAN Notices, vol. 24(10). Fischer, G. 1987. An Object-Oriented Construction and Tool Kit for Human-Computer Communication. Boulder, CO: University of Colorado Department of Computer Science and Institute of Cognitive Science. Foley, J., and van Dam, A. 1982. Fundamentals of Interactive Computer Graphics. Reading, MA: Addison-Wesley.
650 Библиография Frankowski, E. 1986. Advantages of the Object Paradigm for Prototyping. Golden Valley, MN: Honeywell. Freburger, K. October 1987. RAPID: Prototyping Control Panel Interfaces. SIGPLAN Notices, vol. 22(12). Freitas, M., Moreira, Α., and Guerreiro, P. July/August 1990. Object-Oriented Requirements Analysis in an Ada Project. Ada Letters, vol. X(6). Funk, D. 1986. Applying Ada to Beech Starship Avionics. Proceedings of the First International Conference on Ada Programming Language Applications for the NASA Space Station. Houston, TX: NASA Lyndon B. Johnson Space Center. Garrett, N., and Smith, K. November 1986. Building a Timeline Editor from Prefab Parts: The Architecture of an Object-Oriented Application. SIGPLAN Notices, vol. 21(11). Goldberg, A. 1978. Smalltalk in the Classroom. Palo Alto, CA: Xerox Palo Alto Research Center. Goldberg, Α., and Rubin, K. October 1990. Taming Object-Oriented Technology. Computer Language, vol. 7(10). Goldstein, N., and Alger, J. 1992. Developing Object-Oriented Software for the Macintosh. Reading, MA: Addison-Wesley. Gorlen, K. December 1987. An Object-Oriented Class Library for C++ Programs. Software—Practice and Experience, vol. 17(12). Gray, L. 1987. Transferring Object-Oriented Design Techniques into Use: AWIS Experience. Fairfax, VA: TRW Federal Systems Group. Grimshaw, Α., and Liu, J. October 1987. Mentat: An Object-Oriented Macro Data Flow System. SIGPLAN Notices, vol. 22(12). Grossman, M., and Ege, R. October 1987. Logical Composition of Object-Oriented Interfaces. SIGPLAN Notices, vol. 22(12). Gutfreund, S. October 1987. Manipllcons in ThinkerToy. SIGPLAN Notices, vol. 22(12). Gwinn, J. February 1992. Object-Oriented Programs in Realtime. SIGPLAN Notices, vol. 27(2). Harrison, W., Shilling, J., and Sweeney, P. October 1989. Good News, Bad News: Experience Building a Software Development Environment Using the Object- Oriented Paradigm. SIGPLAN Notices, vol. 24(10). Hekmatpour, Α., Orailoglu, Α., and Chau, P. April 1991. Hierarchical Modeling of the VLSI Design Process. IEEE Expert, vol. 6(2).
Библиография 651 Hollowell, G. November 1991. Leading the U.S. Semiconductor Manufacturing Industry Toward an Object-Oriented Technology Standard. Hotline on Object- Oriented Technology, vol. 3(1). Ingalls, D., Wallace, S., Chow, Y., Ludolph, R, and Doyle, K. September 1988. Fabrik: A Visual Programming Environment. SIGPLAN Notices, vol. 23(11). Jacky, J., and Kalet, I. November 1986. An Object-Oriented Approach to a Large Scientific Application. SIGPLAN Notices, vol. 21(11). Jacobson, I. January 1993. Is Object Technology Software's Industrial Platform? IEEE Software, vol. 10(1). Jerrell, M. October 1989. Function Minimization and Automatic Differentiation Using C++. SIGPLAN Notices, vol. 24(10). Johnson, R., and Foote, B. June/July 1988. Designing Reusable Classes. Journal of Object-Oriented Programming, vol. 1(2). Jones, M., and Rashid, R. November 1986. Mach and Matchmaker: Kernel and Language Support for Object-Oriented Distributed Systems. SIGPLAN Notices, vol. 21(11). Jurgen, R. May 1991. Smart Cars and Highways Go Global. IEEE Spectrum vol. 28(5). Kamath, Y, and Smith, J. November/December 1992. Experiences in C++ and 0-0 Design. Journal of Object-Oriented Programming, vol. 5(7). Kay, Α., and Goldberg, A. March 1977. Personal Dynamic Media. IEEE Computer. Kerr, R., and Percival, D. October 1987. Use of Object-Oriented Programming in a Time Series Analysis System. SIGPLAN Notices, vol. 22(12). Kiyooka, G. December 1992. Object-Oriented DLLs. Byte, vol. 17(14). Kozaczynski, W., and Kuntzmann-Combelles, A. January 1993. What It Takes to Make 0-0 Work. IEEE Software, vol. 10(1). Krueger, С June 1992. Software Reuse. ACM Computing Surveys, vol. 24(2). Kuhl, F. 1988. Object-Oriented Design for a Workstation for Air Traffic Control. McLean, VA: The MITRE Corporation. LaPolla, M. 1988. On the Classification of Object-Oriented Design: The Object- Oriented Design of the AirLand Battle Management Menu System. Austin, TX: Lockheed Software Technology Center. Lea, D. 1988a. User's Guide to GNU C++ Library. Cambridge, MA: Free Software Foundation. Lea, D. 1988b. The GNU C++ Library. Proceedings of USENIX C++ Conference. Berkeley, CA: USENIX Association.
652 Библиография Leathers, В. July 1990. Cognos and Eiffel: A Cautionary Tale. Hotline on Object- Oriented Technology, vol. 1(9). Ledbetter, L., and Cox, B. June 1985. Software-ICs. Byte, vol. 10(6). Lee, K., and Rissman, M. February 1989. An Object-Oriented Solution Example: A Flight Simulator Electrical System. Pittsburgh, PA: Software Engineering Institute. Lee, K., Rissman, M., D'Ippolito, R., Plinta, C, and Van Scoy, R. December 1987. An OOD Paradigm for Flight Simulators. Report CMU/SEI-87-TR-43. Pittsburgh, PA: Software Engineering Institute. Levy, P. 1987. Implementing Systems Software in Ada. Mountain View, CA: Rational. Lewis, J., Henry, S., Kafura, D., and Shulman, R. July/August 1992. On the Relationship Between the Object-Oriented Paradigm and Software Reuse: An Empirical Investigation. Journal of Object-Oriented Programming, vol. 5(4). Linton, M., Vlissides, J., and Calder, P. February 1989. Composing User Interfaces with Interviews. IEEE Computer, vol. 22(2). Liu, L., and Horowitz, E. February 1989. Object Database Support for a Software Project Management Environment. SIGPLAN Notices, vol. 24(2). Locke, D., and Goodenough, J. 1988. A Practical Application of the Ceiling Protocol in a Real-Time System. Report CMU/SEI-88-SR-3. Pittsburgh, PA: Software Engineering Institute. Love, T. 1993. Object Lessons. New York, NY: SIGS Publications. Lu, Cary. December 1992. Objects for End Users. Byte, vol. 17(14). Madany, P., Leyens, D., Russo, V, and Campbell, R. 1988. A C++ Class Hierarchy for Building UNIX-like File Systems. Proceedings ofUSENIXC++ Conference. Berkeley, CA: USENIX Association. Madduri, H., Raeuchle, Т., and Silverman, J. 1987. Object-Oriented Programming for Fault-Tolerant Distributed Systems. Golden Valley, MN: Honeywell Computer Science Center. Maloney, J., Borning, Α., and Freeman-Benson, B. October 1989. Constraint Technology for User Interface Construction in ThingLab II. SIGPLAN Notices, vol. 24(10). McDonald, J. October 1989. Object-Oriented Programming for Linear Algebra. SIGPLAN Notices, vol. 24(10). Mentor's Lessons in the School of Hard Knocks. January 25, 1993. Business Week. Meyrowitz, N. November 1986. Intermedia: The Architecture and Construction of an Object-Oriented Hypermedia System and Applications Framework. SIGPLAN Notices, vol. 21(11).
Библиография 653 Miller, Μ., Cunningham, Η., Lee, С, and Vegdahl, S. November 1986. The Application Accelerator Illustration System. SIGPLAN Notices, vol. 21(11). Mohan, L., and Kashyap, R. May 1988. An Object-Oriented Knowledge Representation for Spatial Information. IEEE Transactions on Software Engineering, vol. 14(5). Morgan, Т., and Davis, J. March 1991. Large-Scale Object Systems Development. Hotline on Object-Oriented Technology, vol. 2(5). Mraz, R. December 1986. Performance Evaluation of Parallel Branch and Bound Search with the Intel iPSE Hypercube Computer. Wright-Patterson Air Force Base, OH: Air Force Institute of Technology. Muller, H., Rose, J., Kempf, J., and Stansbury, T. October 1989. The Use of Multimeth- ods and Method Combination in a CLOS-Based Window Interface. SIGPLAN Notices, vol. 24(10). Murphy, E. December 1988. All Aboard for Solid State. IEEE Spectrum vol. 25(13). Nerson, J. September 1992. Applying Object-Oriented Analysis and Design. Communications of the ACM, vol. 35(9). NeXT Embraces a New Way of Programming. November 25, 1988. Science vol. 242. Orden, E. 1987. Application Talk. HOOPLA: Hooray for Object-Oriented Programming Languages, vol. 1(1). Everette, WA: Object-Oriented Programming for Smalltalk Application Developers Association. Orfali, R., and Harkey, D. 1992. Client/Server Programming with OS/2. New York, NY: Van Nostrand Reinhold. Oshima, M., and Shirai, Y. July 1983. Object Recognition Using Three-Dimensional Information. IEEE Transactions on Pattern Analysis and Machine Intelligence, vol. 5(4). Page, Т., Berson, S., Cheng, W., and Muntz, R. October 1989. An Object-Oriented Modeling Environment. SIGPLAN Notices, vol. 24(10). Pashtan, A. 1982. Object-Oriented Operating Systems: An Emerging Design Methodology. Proceedings of the ACM '82 Conference. New York, NY: Association of Computing Machinery. Piersol, K. November 1986. Object-Oriented Spreadsheets: The Analytic Spreadsheet Package. SIGPLAN Notices, vol. 21(11). Pinson, L., and Wiener, R. 1990. Applications of Object-Oriented Programming. Reading, MA: Addison-Wesley. Pittman, M. January 1993. Lessons Learned in Managing Object-Oriented Development. IEEE Software, vol. 10(1).
654 Библиография Plinta, С, Lee, К., and Rissman, M. March 29,1989. A Model Solution for C3I: Message Translation and Validation. Pittsburgh, PA: Software Engineering Institute. Pope, S. April/May 1988. Building Smalltalk-80-Based Computer Music Tools. Journal of Object-Oriented Programming, vol. 1(1). Raghavan, R. 1990. Taming Windows 3.0 and DOS Using C++. Lake Oswego, OR: Wyatt Software. Rockwell International. 1989. Rockwell Advanced Railroad Electronic Systems. Cedar Rapids, LA. Rombach, D. March 1990. Design Measurement: Some Lessons Learned. IEEE Software, vol. 7(2). Rubin, K., Jones, P., Mitchell, C, and Goldstein, T. September 1988. A Smalltalk Implementation of an Intelligent Operator's Associate. SIGPLAN Notices vol. 23(11). Rubin, R., Walker, J., and Golin, E. October 1990. Early Experience with the Visual Programmer's WorkBench. IEEE Transactions on Software Engineering, vol. 16(10). Ruspini, E., and Fraley, R. 1983. ID: An Intelligent Information Dictionary System. In: Entity-Relationship Approach to Software Engineering, ed. С Davis et al. Amsterdam, The Netherlands: Elsevier Science. Russo, V, Johnston, G., and Campbell, R. September 1988. Process Management and Exception Handling in Multiprocessor Operating Systems Using Object- Oriented Design Techniques. SIGPLAN Notices, vol. 23(11). Sampson, J., and Womble, B. 1988. SEND: Simulation Environment for Network Design. Dallas, TX: Southern Methodist University. Santori, M. August 1990. An Instrument That Isn't Really. IEEE Spectrum, vol. 27(8). Scaletti, C, and Johnson, R. September 1988. An Interactive Environment for Object- Oriented Music Composition and Sound Synthesis. SIGPLAN Notices, vol. 23(11). Schindler, J., and Joy, S. February 1992. An Introduction to Object Technology at Liberty Mutual. Liberty Mutual Information Systems Research and Development. Schoen, E., Smith, R., and Buchanan, B. December 1988. Design of Knowledge-Based Systems with a Knowledge-Based Assistant. IEEE Transactions on Software Engineering, vol. 14(12). Schulert, Α., and Erf, K. 1988. Open Dialogue: Using an Extensible Retained Object Workspace to Support a UIMS. Proceedings ofUSENIXC++ Conference. Berkeley, CA: USENIX Association.
Библиография 655 Scott, R., Reddy, R, Edwards, R., and Campbell, D. 1988. GPIO: Extensible Objects for Electronic Design. Proceedings ofUSENIXC++ Conference. Berkeley, CA: USENIX Association. Smith, R., Barth, P., and Young, R. 1987. A Substrate for Object-Oriented Interface Design. Research Directions in Object-Oriented Programming. Cambridge, MA: The MIT Press. Smith, R., Dinitz, R., and Barth, P. November 1986. Impulse-86: A Substrate for Object-Oriented Interface Design. SIGPLAN Notices, vol. 21(11). Sneed, H., and Gawron, W. 1983. The Use of the Entity/Relationship Model as a Schema for Organizing the Data Processing Activities at the Bavarian Motor Works. In: Entity-Relationship Approach to Software Engineering, ed. C. Davis et al. Amsterdam, The Netherlands: Elsevier Science. Snodgrass, R. 1987. An Object-Oriented Command Language. In: Object-Oriented Computing: Implementations, vol. 2, ed. G. Peterson. New York, NY: Computer Society Press of the IEEE. Software Made Simple. September 30, 1991. Business Week. Sridhar, S. September 1988. Configuring Stand-Alone Smalltalk-80 Applications. SIGPLAN Notices, vol. 23(11). Stadel, M. January 1991. Object-Oriented Programming Techniques to Replace Software Components on the Fly in a Running Program. SIGPLAN Notices vol. 26(1). Stevens, A. 1992. C++ Database Development. New York, NY: MIS Press. Stokes, R. 1988. Prototyping Database Applications with a Hybrid of C++ and 4GL. Proceedings of USENIX C++ Conference. Berkeley, CA: USENIX Association. Szcur, M., and Miller, P. September 1988. Transportable Applications Environment (TAE) PLUS: Experiences in Objectively Modernizing a User Interface Environment. SIGPLAN Notices, vol. 23(11). Szekely, P., and Myers, B. September 1988. A User Interface Toolkit Based on Graphical Objects and Constraints. SIGPLAN Notices, vol. 23(11). Tanner, J. April 1, 1986. Fault Tree Analysis in an Object-Oriented Environment. Mountain View, CA: IntelliCorp. Taylor, D. 1992. Object-Oriented Information Systems. New York, NY: John Wiley and Sons. Temte, M. November/December 1984. Object-Oriented Design and Ballistics Software. Ada Letters, vol. 4(3). Tripathi, Α., and Aksit, M. November/December 1988. Communication, Scheduling, and Resource Management in SINA. Journal of Object-Oriented Programming, vol. 1(4).
656 Библиография Tripathi, Α., Ghonami, Α., and Schmitz, Т. 1987. Object Management in the NEXUS Distributed Operating System. Proceedings of the Thirty-second IEEE Computer Society International Conference. New York, NY: Computer Society Press of the IEEE. Ursprung, P., and Zehnder, С 1983. HIQUEL: An Interactive Query Language to Define and Use Hierarchies. In: Entity-Relationship Approach to Software Engineering, ed. С Davis et al. Amsterdam, The Netherlands: Elsevier Science. van der Meulen, P. October 1987. INSIST: Interactive Simulation in Smalltalk. SIGPLAN Notices, vol. 22(12). Vernon, V. September/October 1989. The Forest for the Trees. Programmer's Journal, vol. 7(5). Vilot, M. Fall 1990. Using Object-Oriented Design and C++. The C++ Journal vol. 1(1). Vines, D., and King, T. 1987. Experiences in Building a Prototype Object-Oriented Framework in Ada. Minneapolis, MN: Honeywell. Vlissides, J., and Linton, M. 1988. Applying Object-Oriented Design to Structured Graphics. Proceedings of USENIX C++ Conference. Berkeley, CA: USENIX Association. Volz, R., Mudge, Т., and Gal, D. 1987. Using Ada as a Programming Language for Robot-Based Manufacturing Cells. In: Object-Oriented Computing: Concepts, vol. 1, ed. G. Peterson. New York, NY: Computer Society Press of the IEEE. Walther, S., and Peskin, R. October 1989. Strategies for Scientific Prototyping in Smalltalk. SIGPLAN Notices, vol. 24(10). Wasserman, Α., and Pircher, P. January 1991. Object-Oriented Structured Design and C++. Computer Language, vol. 8(1). Weinand, Α., Gamma, E., and Marty, R. September 1988. ET++-An Object-Oriented Application Framework in C++. SIGPLAN Notices, vol. 23(11). Welch, B. July/August 1991. Securities Objects—The Complexity. Object Magazine, vol. 1(2). White, S. October 1986. Panel Problem: Software Controller for an Oil Hot Water Heating System. Proceedings ofCOMPSAC. New York, NY: Computer Society Press of the IEEE. Wirfs-Brock, R. September 1988. An Integrated Color Smalltalk-80 System. SIGPLAN Notices, vol. 23(11). Wirfs-Brock, R. October 1991. Object-Oriented Frameworks. American Programmer vol. 4(10).
Библиография 657 WOSA Extensions for Financial Services. December 1992. Banking Systems Vendor Council. Wu, P. January 1992. An Object-Oriented Specification for a Compiler. SIGPLAN Notices, vol. 27(1). Yoshida, N., and Hino, K. September 1988. An Object-Oriented Framework of Pattern Recognition. SIGPLAN Notices, vol. 23(11). Yoshida, Т., and Tokoro, M. March 31, 1986. Distributed Queueing Network Simulation: An Application of a Concurrent Object-Oriented Language. Yokohama, Japan: Keio University. Young, R. October 1987. An Object-Oriented Framework for Interactive Data Graphics. SIGPLAN Notices, vol. 22(12). Г. Объектно-ориентированная архитектура Athas, W., and Seitz, С August 1988. Multicomputers: Message-Passing Concurrent Computers. IEEE Computer, vol. 21(8). Corkill, D. D. September 1991. Blackboard Systems. AI Expert, vol. 6(9), pp. 40-47. Dahlby, S., Henry, G., Reynolds, D., and Taylor, P. 1982. The IBM System/38: A High Level Machine. In: Computer Structures: Principles and Examples, ed. G. Bell and A. Newell. New York, NY: McGraw-Hill. Dally, W., and Kajiya, J. March 1985. An Object-Oriented Architecture. SIGARCH Newsletter, vol. 13(3). Fabry, R. 1987. Capability-Based Addressing. In: Object-Oriented Computing: Implementations, vol. 2, ed. G. Peterson. New York, NY: Computer Society Press of the IEEE. Flynn, M. October 1980. Directions and Issues in Architecture and Language. IEEE Computer, vol. 13(10). Harland, D., and Beloff, B. December 1986. Microcoding an Object-Oriented Instruction Set. Computer Architecture News, vol. 14(5). Hillis, D. 1985. The Connection Machine. Cambridge, MA: The MIT Press. Hunt, J. May 2002. Blackboard Architectures. JayDee Technology Ltd 27. www.agent.ai/doc/upload/2004 02/hunt02_l.pdf. IEEE-Std-1471-2000. 2000. IEEE Recommended Practice for Architectural Description of Software-Intensive Systems. New York, NY: IEEE. Iliffe, J. 1982. Advanced Computer Design. London, England: Prentice Hall International. Intel. 1981. iAPX432 Object Primer. Santa Clara, CA.
658 Библиография Ishikawa, Y, and Tokoro, M. March 1984. The Design of an Object-Oriented Architecture. SIGARCH Newsletter, vol. 12(3). Kavi, K., and Chen, D. 1987. Architectural Support for Object-Oriented Languages. Proceedings of the Thirty-second IEEE Computer Society International Conference. New York, NY: Computer Society Press of the IEEE. Krikorian, H. F. March/April 2003. Introduction to Object-Oriented Systems Engineering, Part 1. IT Professional, p. 40. Kruchten, P. 1995. The 4+1 View Model of Architecture. IEEE Software 12(6), pp. 42-50. Lahtinen, P. September/October 1982. A Machine Architecture for Ada. Ada Letters, vol. 2(2). Lampson, В., and Pier, K. January 1981. A Processor for a High-Performance Personal Computer. In: The Dorado: A High Performance Personal Computer. Report CSL-81-1. Palo Alto, CA: Xerox Palo Alto Research Center. Langdon, G. 1982. Computer Design. San Jose, CA: Computeach Press. Levy, H. 1984. Capability-Based Computer Systems. Bedford, MA: Digital Press. Lewis, D., Galloway, D., Francis, R., and Thomson, B. November 1986. Swamp: A Fast Processor for Smalltalk-80. SIGPLAN Notices, vol. 21(11). Maier, M. W., Emery, D., and Hilliard, R. 2004. ANSI/IEEE 1471 and Systems Engineering. Systems Engineering, vol. 7(3), pp. 257-270. Mashburn, H. 1982. The C.mmp/Hydra Project: An Architectural Overview. In: Computer Structures: Principles and Examples, ed. G. Bell and A. Newell. New York, NY: McGraw-Hill. Myers, G. 1982. Advances in Computer Architecture. Second Edition. New York, NY: John Wiley and Sons. Rattner, J. 1982. Hardware/Software Cooperation in the iAPX-432. Proceedings of the Symposium on Architectural Support for Programming Languages and Operating Systems. New York, NY: Association of Computing Machinery. Rose, J. September 1988. Fast Dispatch Mechanisms for Stock Hardware. SIGPLAN Notices, vol. 23(11). Samples, D., Ungar, D., and Hilfinger, P. November 1986. SOAR: Smalltalk without Bytecodes. SIGPLAN Notices, vol. 21(11). Shaw, M., and Garlan, D. 1996. Software Architecture, Perspectives on an Emerging Discipline. Upper Saddle River, NJ: Prentice Hall. Soltis, R., and Hoffman, R. 1987. Design Considerations for the IBM System/38. In: Object-Oriented Computing: Implementations, vol. 2, ed. G. Peterson. New York, NY: Computer Society Press of the IEEE.
Библиография 659 Thacker, С, McCreight, E., Lampson, В., Sproull, R., and Boggs, D. August 1979. Alto: A Personal Computer, Report CSL-79-11. Palo Alto, CA: Xerox Palo Alto Research Center. Ungar, D. 1987. The Design and Evaluation of a High-Performance Smalltalk System. Cambridge, MA: The MIT Press. Ungar, D., and Patterson, D. January 1987. What Price Smalltalk? IEEE Computer, vol. 20(1). Ungar, D., Blau, R., Foley, P., Samples, D., and Patterson, D. March 1984. Architecture of SOAR: Smalltalk on a RISC. SIGARCH Newsletter vol. 12(3). Wah, В., and Li, G. April 1986. Survey on Special Purpose Computer Architectures for AI. SIGART Newsletter, no. 96. Wulf, W. January 1980. Trends in the Design and Implementation of Programming Languages. IEEE Computer, vol. 13(1). Wulf, W., Levin, R., and Harbison, S. 1981. HYDRA/Cmmp: An Experimental Computer System. New York, NY: McGraw-Hill. Д. Объектно-ориентированные базы данных Alford, Μ. 1983. Derivation of Element-Relation-Attribute Database Requirements by Decomposition of System Functions. In: Entity-Relationship Approach to Software Engineering, ed. С Davis et al. Amsterdam, The Netherlands: Elsevier Science. Andleigh, R, and Gretzinger, M. 1992. Distributed Object-Oriented Data-Systems Design. Englewood Cliffs, NJ: Prentice Hall. Atkinson, M., Bailey, R, Chisholm, K., Cockshott, R, and Morrison, R. 1983. An Approach to Persistent Programming. The Computer Journal, vol. 26(4). Atkinson, M., and Buneman, P. June 1987. Types and Persistence in Database Programming Languages. ACM Computing Surveys, vol. 19(2). Atkinson, M., and Morrison, R. October 1985. Procedures as Persistent Data Objects. ACM Transactions on Programming Languages and Systems vol. 7(4). Atwood, T. February 1991. Object-Oriented Databases. IEEE Spectrum, vol. 28(2). Bachman, C. 1983. The Structuring Capabilities of the Molecular Data Model. In: Entity-Relationship Approach to Software Engineering, ed. С Davis et al. Amsterdam, The Netherlands: Elsevier Science. Batini, C, and Lenzerini, M. 1983. A Methodology for Data Schema Integration in the Entity-Relationship Model. In: Entity-Relationship Approach to Software Engineering, ed. С Davis et al. Amsterdam, The Netherlands: Elsevier Science.
660 Библиография Beech, D. 1987. Groundwork for an Object Database Model. In: Research Directions in Object-Oriented Programming, ed. B. Schriver and P. Wegner. Cambridge, MA: The MIT Press. Beech, D. September 1988. Intensional Concepts in an Object Database Model. SIGPLAN Notices, vol. 23(11). Bertino, E. 1983. Distributed Database Design Using the Entity-Relationship Model. In: Entity-Relationship Approach to Software Engineering, ed. С Davis et al. Amsterdam, The Netherlands: Elsevier Science. Blackwell, P., Jajodia, S., and Ng, P. 1983. A View of Database Management Systems as Abstract Data Types. In: Entity-Relationship Approach to Software Engineering, ed. С Davis et al. Amsterdam, The Netherlands: Elsevier Science. Bloom, T. October 1987. Issues in the Design of Object-Oriented Database Programming Languages. SIGPLAN Notices, vol. 22(12). Bobrow, D., Fogelsong, D., and Miller, M. 1987. Definition Groups: Making Sources into First-Class Objects. In: Research Directions in Object-Oriented Programming, ed. B. Schriver and P. Wegner. Cambridge, MA: The MIT Press. Brathwaite, K. 1983. An Implementation of a Data Dictionary to Support Databases Designed Using the Entity-Relationship (E-R) Approach. In: Entity-Relationship Approach to Software Engineering, ed. С Davis et al. Amsterdam, The Netherlands: Elsevier Science. Breazeal, J., Blattner, M., and Burton, H. March 28, 1986. Data Standardization Through the Use of Data Abstraction. Livermore, CA: Lawrence Livermore National Laboratory. Brodie, M. 1984. On the Development of Data Models. In: On Conceptual Modeling: Perspectives from Artificial Intelligence, Databases, and Programming Languages, ed. M. Brodie, J. Mylopoulos, and J. Schmidt. New York, NY: Springer-Verlag. Brodie, M., and Ridjanovic, D. 1984. On the Design and Specification of Database Transactions. In: On Conceptual Modeling: Perspectives from Artificial Intelligence, Databases, and Programming Languages, ed. M. Brodie, J. Mylopoulos, and J. Schmidt. New York, NY: Springer-Verlag. Butterworth, P., Otis, Α., and Stein, J. October 1991. The GemStone Object Database Management System. Communications of the ACM, vol. 34(10). Carlson, C, and Arora, A. 1983. UPM: A Formal Tool for Expressing Database Update Semantics. In: Entity-Relationship Approach to Software Engineering, ed. С Davis et al. Amsterdam, The Netherlands: Elsevier Science.
Библиография 661 Casanova, M. 1983. Designing Entity-Relationship Schemes for Conventional Information Systems. In: Entity-Relationship Approach to Software Engineering, ed. С Davis et al. Amsterdam, The Netherlands: Elsevier Science. Cattell, R. May 1983. Design and Implementation of a Relationship-Entity-Datum Data Model, Report CSL-83-4. Palo Alto, CA: Xerox Palo Alto Research Center. Cattell, R. 1991. Object Data Management. Reading, MA: Addison-Wesley. Chen, P. March 1976. The Entity-Relationship Model-Toward a Unified View of Data. ACM Transactions on Database Systems, vol. 1(1). Chen, P. 1983. ER—A Historical Perspective and Future Directions. In: Entity-Relationship Approach to Software Engineering, ed. С Davis et al. Amsterdam, The Netherlands: Elsevier Science. Claybrook, В., Claybrook, Α., and Williams, J. January 1985. Defining Database Views as Data Abstractions. IEEE Transactions on Software Engineering, vol. SE-ll(l). D'Cunha, Α., and Radhakrishnan, T. 1983. Applications of E-R Concepts to Data Administration. In: Entity-Relationship Approach to Software Engineering, ed. С Davis et al. Amsterdam, The Netherlands: Elsevier Science. Date, C. 1981, 1983. An Introduction to Database Systems. Reading, MA: Addison- Wesley. Date, С 1986. Relational Database: Selected Writings. Reading, MA: Addison- Wesley. Date, C. 1987. The Guide to the SQL Standard. Reading, MA: Addison-Wesley. Duhl, J., and Damon, С September 1988. A Performance Comparison of Object and Relational Databases Using the Sun Benchmark. SIGPLAN Notices vol. 23(11). Harland, D., and BelofF, B. April 1987. OBJEKT-A Persistent Object Store with an Integrated Garbage Collector. SIGPLAN Notices, vol. 22(4). Hawryszkiewycz, I. 1984. Database Analysis and Design. Chicago, IL: Science Research Associates. Higa, K., Morrison, M., Morrison, J., and Sheng, O. June 1992. An Object-Oriented Methodology for Knowledge Base/Database Coupling. Communications of the ACM, vol. 35(6). Hull, R., and King, R. September 1987. Semantic Database Modeling: Survey, Applications, and Research Issues. ACM Computing Surveys, vol. 19(3). Jajodia, S., Ng, P., and Springsteel, F. 1983. On Universal and Representative Instances for Inconsistent Databases. In: Entity-Relationship Approach to Software Engineering, ed. C. Davis et al. Amsterdam, The Netherlands: Elsevier Science.
662 Библиография Ketabchi, M., and Berzins, V. January 1988. Mathematical Model of Composite Objects and Its Application for Organizing Engineering Databases. IEEE Transactions on Software Engineering, vol. 14(1). Ketabchi, M., and Wiens, R. 1987. Implementation of Persistent Multi-User Object- Oriented Systems. Proceedings of the Thirty-second IEEE Computer Society International Conference. New York, NY: Computer Society Press of the IEEE. Khoshafian, S., and Abnous, R. 1990. Object-Orientation: Concepts, Languages, Databases, User Interfaces. New York, NY: John Wiley and Sons. Kim, W., and Lochovsky, K. 1989. Object-Oriented Concepts, Databases, and Applications. Reading, MA: Addison-Wesley. Kim, W., Ballou, N., Chou, H., Garze, J., Woelk, D., and Banerjee, J. September 1988. Integrating an Object-Oriented Programming System with a Database System. SIGPLAN Notices, vol. 23(11). Kim, W., Banerjee, J., Chou, H., Garza, J., and Woelk, D. October 1987. Composite Object Support in an Object-Oriented Database System. SIGPLAN Notices, vol. 22(12). Kung, С Object Subclass Hierarchy in SQL: A Simple Approach. Communications of the ACM, vol. 33(7). Laenens, E., and Vermeir, D. August 1988. An Overview of OOPS+, an Object- Oriented Database Programming Language. Proceedings ofECOOPf88: European Conference on Object-Oriented Programming. New York, NY: Springer- Verlag. Lamb, C, Landis, G., Orenstein, J., and Weinreb, D. October 1991. The ObjectStore Database System. Communications of the ACM, vol. 34(10). Larson, J., and Dwyer, P. 1983. Defining External Schemas for an Entity-Relationship Database. In: Entity-Relationship Approach to Software Engineering, ed. С Davis et al. Amsterdam, The Netherlands: Elsevier Science. Maier, D., and Stein, J. 1987. Development and Implementation of an Object-Oriented DBMS. In: Research Directions in Object-Oriented Programming, ed. B. Schri- ver and P. Wegner. Cambridge, MA: The MIT Press. Margrave, G., Lusk, E., and Overbeek, R. 1983. Tools for the Creation of IMS Database Designs from Entity-Relationship Diagrams. In: Entity-Relationship Approach to Software Engineering, ed. С Davis et al. Amsterdam, The Netherlands: Elsevier Science. Mark, L., and Poussopoulos, N. 1983. Integration of Data, Schema, and Meta-Schema in the Context of Self-Documenting Data Models. In: Entity-Relationship Approach to Software Engineering, ed. С Davis et al. Amsterdam, The Netherlands: Elsevier Science.
Библиография 663 Markowitz, V., and Makowsky, J. August 1990. Identifying Extended Entity-Relationship Object Structures in Relational Schemas. IEEE Transactions on Software Engineering, vol. 16(8). Marti, R. 1983. Integrating Database and Program Descriptions Using an ER Data Dictionary. In: Entity-Relationship Approach to Software Engineering, ed. С Davis et al. Amsterdam, The Netherlands: Elsevier Science. Merrow, Т., and Laursen, J. October 1987. A Pragmatic System for Shared Persistent Objects. SIGPLAN Notices, vol. 22(12). Mitchell, J., and Wegbreit, B. 1977. Schemes: A High-Level Data Structuring Concept. In: Current Trends in Programming Methodology: Data Structuring, vol. 4, ed. R. Yeh. Englewood Cliffs, NJ: Prentice Hall. Morrison, R., Atkinson, M., Brown, Α., and Dearie, A. April 1988. Bindings in Persistent Programming Languages. SIGPLAN Notices, vol. 23(4). Moss, E., Herlihy, M., and Zdonik, S. September 1988. Object-Oriented Databases, Course Notes. San Diego, CA: OOPSLA'88. Moss, J. August 1992. Working with Persistent Objects: To Swizzle or Not to Swizzle. IEEE Transactions on Software Engineering, vol. 18(8). Nastos, M. January 1988. Databases, Etc. HOOPLA: Hooray for Object-Oriented Programming Languages, vol. 1(2). Everette, WA: Object Oriented Programming for Smalltalk Application Developers Association. Navathe, S., and Cheng, A. 1983. A Methodology for Database Schema Mapping from Extended Entity Relationship Models into the Hierarchical Model. In: Entity- Relationship Approach to Software Engineering, ed. C. Davis et al. Amsterdam, The Netherlands: Elsevier Science. Ontologic. 1987. Vbase Technical Overview. Billerica, MA. Oracle. 1989. Oracle for Macintosh: References, Version 1.1. Belmont, CA. Penny, J., and Stein, J. October 1987. Class Modification in the GemStone Object- Oriented DBMS. SIGPLAN Notices, vol. 22(12). Peterson, R. 1987. Object-Oriented Database Design. In: Object-Oriented Computing: Implementations, vol. 2, ed. G. Peterson. New York, NY: Computer Society Press of the IEEE. Premerlani, W., Blaha, M., Rumbaugh, J., and Varwig, T. November 1990. An Object- Oriented Relational Database. Communications of the ACM vol. 33(11). Sakai, H. 1983. Entity-Relationship Approach to Logical Database Design. In: Entity- Relationship Approach to Software Engineering, ed. С Davis et al. Amsterdam, The Netherlands: Elsevier Science.
664 Библиография Skarra, Α., and Zdonik, S. 1987. Type Evolution in an Object-Oriented Database. In: Research Directions in Object-Oriented Programming, ed. B. Schriver and P. Wegner. Cambridge, MA: The MIT Press. Skarra, Α., and Zdonik, S. November 1986. The Management of Changing Types in an Object-Oriented Database. SIGPLAN Notices, vol. 21(11). Smith, D., and Smith, J. 1980. Conceptual Database Design. In: Tutorial on Software Design Techniques, Third Edition, ed. P. Freeman and A. Wasserman. New York, NY: Computer Society Press of the IEEE. Smith, J., and Smith, D. Database Abstractions: Aggregation and Generalization. ACM Transactions on Database Systems, vol. 2(2). Smith, K., and Zdonik, S. October 1987. Intermedia: A Case Study of the Differences Between Relational and Object-Oriented Database Systems. SIGPLAN Notices, vol. 22(12). Stein, J. March 1988. Object-Oriented Programming and Database Design. Dr. Dobb 's Journal, vol. 13(3). Teorey, Т., Yang, D., and Fry, J. June 1986. A Logical Design Methodology for Relational Databases Using the Extended Entity-Relationship Model. ACM Computing Surveys, vol. 18(2). Thuraisingham, M. October 1989. Mandatory Security in Object-Oriented Database Systems. SIGPLAN Notices, vol. 24(10). Veloso, P., and Furtado, A. 1983. View Constructs for the Specification and Design of External Schemas. In: Entity-Relationship Approach to Software Engineering, ed. С Davis et al. Amsterdam, The Netherlands: Elsevier Science. Wiebe, D. November 1986. A Distributed Repository for Immutable Persistent Objects. SIGPLAN Notices, vol. 21(11). Wiederhold, G. December 1986. Views, Objects, and Databases. IEEE Computer vol. 19(12). Wile, D., and Allard, D. May 1982. Worlds: An Organizing Structure for Object-Bases. SIGPLAN Notices, vol 19(5). Zdonik, S., and Maier, D. 1990. Readings in Object-Oriented Database Systems. San Mateo, CA: Morgan Kaufmann. Zhang, Z., and Mendelzon, A. 1983. A Graphical Query Language for Entity-Relationship Databases. In: Entity-Relationship Approach to Software Engineering, ed. C. Davis et al. Amsterdam, The Netherlands: Elsevier Science. E. Объектно-ориентированное проектирование Abbott, R. November 1983. Program Design by Informal English Descriptions. Communications of the ACM, vol. 26(11).
Библиография 665 Abbott, R. August 1987. Knowledge Abstraction. Communications of the ACM vol. 30(8). Ackroyd, M., and Daum, D. 1991. Graphical Notation for Object-Oriented Design and Programming. Journal of Object-Oriented Programming, vol. 3(5). Alabios, B. September 1988. Transformation of Data Flow Analysis Models to Object- Oriented Design. SIGPLAN Notices, vol. 23(11). Arnold, P., Bodoff, S., Coleman, D., Gilchrist, H., and Hayes, F. June 1991. An Evaluation of Five Object-Oriented Development Methods. Bristol, England: Hewlett-Packard Laboratories. Bear, S., Allen, P., Coleman, D., and Hayes, F. Graphical Specification of Object- Oriented Systems. Object-Oriented Programming Systems, Languages, and Applications. Ottawa, Canada: OOPSLA'90. Beck, K., and Cunningham, W. October 1989. A Laboratory for Teaching Object- Oriented Thinking. SIGPLAN Notices, vol. 24(10). Berard, E. 1986. An Object-Oriented Design Handbook. Rockville, MD: EVB Software Engineering. Berzins, V., Gray, M, and Naumann, D. May 1986. Abstraction-Based Software Development. Communications of the ACM, vol. 29(5). Blaha, M. April 1988. Relational Database Design Using an Object-Oriented Methodology. Communications of the ACM, vol. 31(4). Booch, G. September 1981. Describing Software Design in Ada. SIGPLAN Notices, vol. 16(9). Booch, G. March/April 1982. Object-Oriented Design. Ada Letters, vol. 1(3). Booch, G. February 1986. Object-Oriented Development. IEEE Transactions on Software Engineering, vol. 12(2). Booch, G. 1987. On the Concepts of Object-Oriented Design. Denver, CO: Rational. Booch, G. Summer 1989. What Is and What Isn't Object-Oriented Design. American Programmer, vol. 2(7-8). Booch, G., and Vilot, M. Object-Oriented Design. The C++ Report. Booch, G., Jacobson, I., and Kerth, N. September 1988. Specification and Design Methodologies in Support of Object-Oriented Programming, Course Notes. San Diego, CA: OOPSLA'88. Bowles, A. November/December 1991. Evolution vs. Revolution: Should Structured Methods Be Objectified? Object Magazine, vol. 1(4). Boyd, S. July/August 1987. Object-Oriented Design and PAMELA™. Ada Letters vol. 7(4).
666 Библиография Bril, R., deBunje, Т., and Ouvry, A. October 1991. Development of SCORE: Towards the Industrialization of an Object-Oriented Method Using the Formal Design Language COLD-1 as Notation. Eindhoven, The Netherlands: Philips Research Laboratories. Brookman, D. November/December 1991. SA/SD versus OOD. Ada Letters, vol. XI(9). Bruno, G., and Balsamo, A. November 1986. Petri Net-Based Object-Oriented Modeling of Distributed Systems. SIGPLAN Notices, vol. 21(11). Buhr, R. 1984. System Design with Ada. Englewood Cliffs, NJ: Prentice Hall. Buhr, R. August 22, 1988. Machine Charts for Visual Prototyping in System Design. SCE Report 88-2. Ottawa, Canada: Carleton University. Buhr, R. September 14,1988. Visual Prototyping in System Design. SCE Report 88-14. Ottawa, Canada: Carleton University. Buhr, R. 1989. System Design with Machine Charts: A CAD Approach with Ada Examples. Englewood Cliffs, NJ: Prentice Hall. Buhr, R., Karam, G., Hayes, C, and Woodside, M. March 1989. Software CAD: A Revolutionay Approach. IEEE Transactions on Software Engineering vol. 15(3). Bulman, D. August 1989. An Object-Based Development Model. Computer Language, vol. 6(8). Cherry, G. 1987. PAMELA 2: An Ada-Based Object-Oriented Design Method. Reston, VA: Thought**Tools. Cherry, G. 1990. Software Construction by Object-Oriented Pictures. Canandaigua, NY: Thought**Tools. Clark, R. June 1987. Designing Concurrent Objects. Ada Letters, vol. 7(6). Coad, P. September 1991. OOD Criteria. Journal of Object-Oriented Programming, vol.(5). Coleman, D., Hayes, F., and Bear, S. December 1990. Introducing Objectcharts or How to Use Statecharts in Object-Oriented Design. Bristol, England: Hewlett- Packard Laboratories. Comer, E. July 1989. Ada Box Structure Methodology Handbook. Melbourne, FL: Software Productivity Solutions. Constantine, L. Summer 1989. Object-Oriented and Structured Methods: Towards Integration. American Programmer, vol. 2(7-8). CRI, CISI Ingenierie, and Matra. June 20,1987. HOOD: Hierarchical Object-Oriented Design. Paris, France. Cribbs, J., Moon, S., and Roe, С 1992. An Evaluation of Object-Oriented Analysis and Design Methodologies. Raleigh, NC: Alcatel Network Systems.
Библиография 667 Cunningham, W., and Beck, K. November 1986. A Diagram for Object-Oriented Programs. SIGPLAN Notices, vol. 21(11). Davis, N., Irving, M., and Lee, J. 1988. The Evolution of Object-Oriented Design from Concept to Method. Surrey, United Kingdom: Logica Space and Defence Systems Limited. Dean, H. May 1991. Object-Oriented Design Using Message Flow Decomposition. Journal of Object-Oriented Programming, vol. 4(2). deChampeaux, D., Balzer, В., Bulman, D., Culver-Lozo, K., Jacobson, I., and Mel- lor, S. 1992. The Object-Oriented Software Development Process. Vancouver, Canada: OOPSLA'92. deChampeaux, D., Lea, D., and Faure, P. 1992. The Process of Object-Oriented Design. Vancouver, Canada: OOPSLA'92. Edwards, J., and Henderson-Sellers, B. November 1991. A Graphical Notation for Object-Oriented Analysis and Design. New South Wales, Australia: University of New South Wales. Felsinger, R. 1987a. Integrating Object-Oriented Design, Structured Analysis/ Structured Design, and Ada for Real-Time Systems. Mt. Pleasant, SC. Felsinger, R. 1987b. Object-Oriented Design, Course Notes. Torrance, CA: Data Processing Management Association. Fichman, R., and Kemerer, С October 1992. Object-Oriented and Conventional Analysis and Design Methodologies. IEEE Computer, vol. 25(10). Firesmith, D. May 6, 1986. Object-Oriented Development. Fort Wayne, In: Magnavox Electronic Systems Co. Firesmith, D. 1993. Object-Oriented Requirements Analysis and Logical Design. New York, NY: John Wiley and Sons. Fowler, M. 1992. A Comparison of Object-Oriented Analysis and Design Methods. Vancouver, Canada: OOPSLA'92. Gamma, E., Helm, R., Johnson, R., and Vlissides, J. 1993. A Catalog of Object- Oriented Design Patterns. Cupertino, CA: Taligent. Gamma, E., Helm, R., Johnson, R., and Vlissides, J. 1995. Design Patterns: Elements of Reusable Object-Oriented Software. Reading, MA: Addison-Wesley. Gane, С Summer 1989. Object-Oriented Data/Process Modeling. American Programmer, vol. 2(7-8). Giddings, R. May 1984. Accommodating Uncertainty in Software Design. Communications of the ACM, vol. 27(5). Gomaa, H. September 1984. A Software Design Method for Real-Time Systems. Communications of the ACM, vol. 27(9).
668 Библиография Gossain, S., and Anderson, B. An Iterative Design Model for Reusable Objects. Ottawa, Canada: OOPSLA'90. Gouda, M., Han, Y, Jensen, E., Johnson, W., and Kain, R. November 1977. Towards a Methodology of Distributed Computer System Design. Sixth Texas Conference on Computing Systems. New York, NY: Association of Computing Machinery. Graham, I. 1991. Object-Oriented Methods. Wokingham, England: Addison-Wesley. Grosch, J. December 1983. Type Derivation Graphs—A Way to Visualize the Type Building Possibilities of Programming Languages. SIGPLAN Notices vol. 18(12). Harel, D. 1987. Statecharts: A Visual Formalism for Complex Systems. Science of Computer Programming, vol. 8. Harel, D. May 1988. On Visual Formalisms. Communications of the ACM vol. 31(5). Henderson-Sellers, B. 1992. A Book of Object-Oriented Knowledge. Englewood Cliffs, NJ: Prentice Hall. Inwood, С 1992. Analysis versus Design: Is There a Difference? The C++ Journal, vol. 2(1). Jackson, M. Summer 1989. Object-Oriented Software. American Programmer vol. 2(7-8). Jacobson, I. August 1985. Concepts for Modeling Large Real-Time Systems. Academic dissertation. Stockholm, Sweden: Royal Institute of Technology, Department of Computer Science. Jacobson, I. October 1987. Object-Oriented Development in an Industrial Environment. SIGPLAN Notices, vol. 22(12). Jacobson, I., Christerson, M., Jonsson, P., and Overgaard, G. 1992. Object-Oriented Software Engineering. Wokingham, England: Addison-Wesley. Jamsa, K. January 1984. Object-Oriented Design vs. Structured Design — A Student's Perspective. Software Engineering Notes, vol. 9(1). Johnson, R., and Russo, V May 1991. Reusing Object-Oriented Designs. Urbana, IL: University of Illinois. Jones, A. 1979. The Object Model: A Conceptual Tool for Structuring Software. In: Operating Systems, ed. R. Bayer et al. New York, NY: Springer-Verlag. Kadie, С 1986. Refinement Through Classes: A Development Methodology for Object- Oriented Languages. Urbana, IL: University of Illinois. Kaplan, S., and Johnson, R. July 21, 1986. Designing and Implementing for Reuse. Urbana, IL: University of Illinois, Department of Computer Science. Kay, A. August 1969. The Reactive Engine. Salt Lake City, UT: The University of Utah, Department of Computer Science.
Библиография 669 Kelly, J. 1986. A Comparison of Four Design Methods for Real-Time Systems. Proceedings of the Ninth International Conference on Software Engineering. New York, NY: Computer Society Press of the IEEE. Kent, W. 1983. Fact-Based Data Analysis and Design. In: Entity-Relationship Approach to Software Engineering, ed. C. Davis et al. Amsterdam, The Netherlands: Elsevier Science. Kerth, N. L. 1988. MOOD: A Methodology for Structured Object-Oriented Design. Tutorial presented at OOPSLA'88, San Diego, CA. Kim, J., and Lerch, J. 1992. Towards a Model of Cognitive Process in Logical Design: Comparing Object-Oriented and Traditional Functional Decomposition Software Methodologies. Pittsburgh, PA: Carnegie Mellon University. Kruchten, P. 2003. The Rational Unified Process: An Introduction. Third Edition. Boston, MA: Addison-Wesley. Ladden, R. July 1988. A Survey of Issues to Be Considered in the Development of an Object-Oriented Development Methodology for Ada. Software Engineering Notes, vol. 13(3). Lieberherr, K., and Riel, A. October 1989. Contributions to Teaching Object-Oriented Design and Programming. SIGPLAN Notices, vol. 24(10). Liskov, B. 1980. A Design Methodology for Reliable Software Systems. In: Tutorial on Software Design Techniques, Third Edition, ed. P. Freeman and A. Wasserman. New York, NY: Computer Society Press of the IEEE. Lorenz, M. 1993. Object-Oriented Software Development. Englewood Cliffs, NJ: Prentice Hall. Mannino, P. April 1987. A Presentation and Comparison of Four Information System Development Methodologies. Software Engineering Notes, vol. 12(2). Martin, B. 1993. Designing Object-Oriented C++ Applications Using the Booch Method. Englewood Cliffs, NJ: Prentice Hall. Masiero, P., and Germano, F. July 1988. JSD as an Object-Oriented Design Method. Software Engineering Notes, vol. 13(3). Meyer, B. 1988. Object-Oriented Software Construction. Englewood Cliffs, NJ: Prentice Hall. Meyer, B. March 1987. Reusability: The Case for Object-Oriented Design. IEEE Software, vol. 4(2). Meyer, B. 1989. From Structured Programming to Object-Oriented Design: The Road to Eiffel. Structured Programming, vol. 10(1). Mills, H. June 1988. Stepwise Refinement and Verification in Box-Structured Systems. IEEE Computer, vol. 21(6).
670 Библиография Mills, H., Linger, R., and Hevner, A. 1986. Principles of Information System Design and Analysis. Orlando, FL: Academic Press. Minkowitz, C, and Henderson, P. March 1987. Object-Oriented Programming of Discrete Event Simulation Using Petri Nets. Stirling, Scotland: University of Stirling. Monarchi, D., and Puhr, G. September 1992. A Research Typology for Object-Oriented Analysis and Design. Communications of the ACM, vol. 35(9). Mostow, J. Spring 1985. Toward Better Models of the Design Process. AI Magazine, vol. 6(1). Moulin, B. 1983. The Use of EPAS/IPSO Approach for Integrating Entity Relationship Concepts and Software Engineering Techniques. In: Entity-Relationship Approach to Software Engineering, ed. С Davis et al. Amsterdam, The Netherlands: Elsevier Science. Mullin, M. 1989. Object-Oriented Program Design with Examples in C++. Reading, MA: Addison-Wesley. Nielsen, K., and Shumate, K. August 1987. Designing Large Real-Time Systems with Ada. Communications of the ACM, vol. 30(8). Nielsen, K. March 1988. An Object-Oriented Design Methodology for Real-Time Systems in Ada. San Diego, CA: Hughes Aircraft Company. Nies, S. 1986. The Ada Object-Oriented Approach. Proceedings of the First Interna- . ? , tional Conference on Ada Programming Language Applications for the NASA Space Station. Houston, TX: NASA Lyndon B. Johnson Space Center. Ossher, H. 1987. A Mechanism for Specifying the Structure of Large, Layered, Systems. In: Research Directions in Object-Oriented Programming, ed. B. Schriver and P. Wegner. Cambridge, MA: The MIT Press. Page-Jones, M., Constantine, L., and Weiss, S. October 1990. Modeling Object- Oriented Systems: The Uniform Object Notation. Computer Language vol. 7(10). Parnas, D. 1979. On the Criteria to Be Used in Decomposing Systems into Modules. Classics in Software Engineering, ed. E. Yourdon. New York, NY: Yourdon Press. Parnas, D., Clements, P., and Weiss, D. March 1985. The Modular Structure of Complex Systems. IEEE Transactions on Software Engineering, vol. SE-11(3). Pasik, Α., and Schor, M. January 1984. Object-Centered Representation and Reasoning. SIGART Newsletter no. 87. Rajlich, V., and Silva, J. 1987. Two Object-Oriented Decomposition Methods. Detroit, MI: Wayne State University.
Библиография 671 Ramamoorthy, С, and Sheu, P. Fall 1988. Object-Oriented Systems. IEEE Expert vol. 3(3). Reenskaug, T. August 1981. User-Oriented Descriptions of Smalltalk Systems. Byte, vol. 6(8). Reiss, S. 1987. An Object-Oriented Framework for Conceptual Programming. In: Research Directions in Object-Oriented Programming, ed. B. Schriver and P. Wegner. Cambridge, MA: The MIT Press. Richter, С August 1986. An Assessment of Structured Analysis and Structured Design. Software Engineering Notes, vol. 11(4). Rine, D. October 1987. A Common Error in the Object Structure of Object-Oriented Methods. Software Engineering Notes, vol. 12(4). Rosenberg, D., and Jennett, P. July 1992. Object-Oriented Analysis and Design Methods. Frameworks, vol. 6(4). Ross, R. 1987. Entity Modeling: Techniques and Application. Boston, MA: Database Research Group. Rosson, M., and Gold, E. October 1989. Problem-Solution Mapping in Object- Oriented Design. SIGPLAN Notices, vol. 24(10). Rumbaugh, J., Blaha, M., Premerlani, W., Eddy, F., and Lorensen, W. 1991. Object- Oriented Modeling and Design. Englewood Cliffs, NJ: Prentice Hall. Sahraoui, A. 1987. Towards a Design Approach Methodology Combining OOP and Petri Nets for Software Production. Toulouse, France: Laboratoire d'Automatique et d'analyses des systemes du C.N.R.S. Sakai, H. 1983. A Method for Entity-Relationship Behavior Modeling. In: Entity- Relationship Approach to Software Engineering, ed. C. Davis et al. Amsterdam, The Netherlands: Elsevier Science. Seidewitz, E. May 1985. Object Diagrams. Greenbelt, MD: NASA Goddard Space Flight Center. Seidewitz, E., and Stark, M. 1986a. Towards a General Object-Oriented Software Development Methodology. Proceedings of the First International Conference on Ada Programming Language Applications for the NASA Space Station. Houston, TX: NASA Lyndon B. Johnson Space Center. Seidewitz, E., and Stark, M. August 1986b. General Object-Oriented Software Development. Report SEL-86-002. Greenbelt, MD: NASA Goddard Space Flight Center. Seidewitz, E., and Stark, M. July/August 1987. Towards a General Object-Oriented Design Methodology. Ada Letters, vol. 7(4).
672 Библиография Seidewitz, E., and Stark, M. 1988. An Introduction to General Object-Oriented Software Development. Rockville, MD: Millennium Systems. Shilling, J., and Sweeney, P. October 1989. Three Steps to Views: Extending the Object-Oriented Paradigm. SIGPLAN Notices, vol. 24(10). Shlaer, S., Mellor, S., and Hywari, W. 1990. OODLE: A Language-Independent Notation for Object-Oriented Design. Berkeley, CA: Project Technology, California. Shumate, K. 1987. Layered Virtual Machine/Object-Oriented Design. San Diego, CA: Hughes Aircraft Company. Smith, M., and Tockey, S. 1988. An Integrated Approach to Software Requirements Definition Using Objects. Seattle, WA: Boeing Commercial Airplane Support Division. Solsi, S., and Jones, E. March/April 1991. Simple Yet Complete Heuristics for Transforming Data Flow Diagrams into Booch Style Diagrams. Ada Letters vol. XI(2). Song, X. May 1992. Comparing Software Design Methodologies Through Process Modeling. Irvine, CA: University of California. Stark, M. April 1986. Abstraction Analysis: From Structured Analysis to Object- Oriented Design. Greenbelt, MD: NASA Goddard Space Flight Center. Strom, R. October 1986. A Comparison of the Object-Oriented and Process Paradigms. SIGPLAN Notices, vol. 21(10). Teledyne Brown Engineering. October 1987. Software Methodology Catalog, Report MC87-COMM/ADP-0036. Tinton Falls, NJ. The Fusion Object-Oriented Analysis and Design Method. May 1992. Bristol, England: Hewlett Packard Laboratories. Thomas, D. May/June 1989. In: Search of an Object-Oriented Development Process. Journal of Object-Oriented Programming, vol. 2(1). Wahl, S. December 13,1988. Introduction to Object-Oriented Software. C++ Tutorial Program of the USENIX Conference. Denver, CO: USENIX Association. Walters, N. July/August 1991. An Ada Object-Based Analysis and Design Approach. Ada Letters, vol. XI(5). Wasserman, Т., Pircher, P., and Muller, R. December 1988. An Object-Oriented Structured Design Method for Code Generation. San Francisco, CA: Interactive Development Environments. Wasserman, Т., Pircher, P., and Muller, R. Summer 1989. Concepts of Object-Oriented Structured Design. American Programmer, vol. 2(7-8). Wasserman, Т., Pircher, P., and Muller, R. March 1990. The Object-Oriented Structured Design Notation for Software Design Representation. IEEE Computer, vol. 23(3).
Библиография 673 Webster, D. December 1988. Mapping the Design Information Representation Terrain. IEEE Spectrum, vol. 21(12). Williams, L. 1986. The Object Model in Software Engineering. Boulder, CO: Software Engineering Research. Wirfs-Brock, R., and Wilkerson, B. October 1989. Object-Oriented Design: A Responsibility-Driven Approach. SIGPLAN Notices, vol. 24(10). Wirfs-Brock, R., Wilkerson, В., and Wiener, L. 1990. Designing Object-Oriented Software. Englewood Cliffs, NJ: Prentice Hall. Xong, X., and Osterweil, L. June 1992. A Detailed Objective Comparison and Integration of Two Object-Oriented Design Methodologies. Irvine, CA: University of California. Yau, S., and Tsai, J. June 1986. A Survey of Software Design Techniques. IEEE Transactions on Software Engineering, vol. SE-12(6). Zachman, J. 1987. A Framework for Information Systems Architecture. IBM Systems Journal, vol. 26(3). Zimmerman, R. 1983. Phases, Methods, and Tools—A Triad of System Development. In: Entity-Relationship Approach to Software Engineering, ed. С Davis et al. Amsterdam, The Netherlands: Elsevier Science. Ж. Объектно-ориентированное программирование Ada and C++: Business Case Analysis. July 1991. Washington, DC: Deputy Assistant Secretary of the Air Force. Adams, S. July 1986. MetaMethods: The MVC Paradigm. HOOPLA: Hooray for Object-Oriented Programming Languages, vol. 1(4). Everette, WA: Object- Oriented Programming for Smalltalk Applications Developers Association. Agha, G. October 1986. An Overview of Actor Languages. SIGPLAN Notices vol. 21(10). Agha, G. 1988. Actors: A Model of Concurrent Computation in Distributed Systems. Cambridge, MA: The MIT Press. Agha, G., and Hewitt, С 1987. Actors: A Conceptual Foundation for Concurrent Object-Oriented Programming. In: Research Directions in Object-Oriented Programming, ed. B. Schriver and P. Wegner. Cambridge, MA: The MIT Press. Aksit, M., and Tripathi, A. September 1988. Data Abstraction Mechanisms in Sina/st. SIGPLAN Notices, vol. 23(11). Albano, A. June 1983. Type Hierarchies and Semantic Data Models. SIGPLAN Notices, vol. 18(6).
674 Библиография Almes, G., Black, Α., Lazowska, Ε., and Noe, J. January 1985. The Eden System: A Technical Review. IEEE Transactions on Software Engineering, vol. SE-11(1). Alpert, S., Woyak, S., Shrobe, H., and Arowood, L. December 1990. Object-Oriented Programming in AI. IEEE Expert, vol. 5(6). Althoff, J. August 1981. Building Data Structures in the Smalltalk-80 System. Byte, vol. 6(8). Ambler, A. 1980. Gypsy: A Language for Specification and Implementation of Verifiable Programs. In: Programming Language Design, ed. A. Wasserman. New York, NY: Computer Society Press. America, P. 1987. POOL-T: A Parallel Object-Oriented Language. In: Object-Oriented Concurrent Programming, ed. Yonezawa and M. Tokoro. Cambridge, MA: The MIT Press. Apple Computer. 1989. MacApp: The Expandable Macintosh Application, version 2.0B9. Cupertino, CA. Apple Computer. 1989. Macintosh Programmer's Workshop Pascal 3.0 Reference. Cupertino, CA. AT&T Bell Laboratories. 1989. UNIX System V ATT C++ Language System, Release 2.0 Library Manual. Murray Hill, NJ. AT&T Bell Laboratories. 1989. UNIX System V ATT C++ Language System, Release 2.0 Product Reference Manual. Murray Hill, NJ. AT&T Bell Laboratories. 1989. UNIX System V ATT C++ Language System, Release 2.0 Release Notes. Murray Hill, NJ. AT&T Bell Laboratories. 1989. UNIX System V ATT C++ Language System, Release 2.0 Selected Readings. Murray Hill, NJ. Attardi, G. 1987. Concurrent Strategy Execution in Omega. In: Object-Oriented Concurrent Programming, ed. Yonezawa and M. Tokoro. Cambridge, MA: The MIT Press. Bach, I. November/December 1982. On the Type Concept of Ada. Ada Letters vol. 11(3). Badrinath, В., and Ramamritham, K. May 1988. Synchronizing Transactions on Objects. IEEE Transactions on Computers, vol. 37(5). Ballard, M., Maier, D., and Wirfs-Brock, A. November 1986. QUICKTALK: A Smalltalk-80 Dialect for Defining Primitive Methods. SIGPLAN Notices vol. 21(11). Beaudet, P., and Jenkins, M. June 1988. Simulating the Object-Oriented Paradigm in Nial. SIGPLAN Notices, vol. 23(6).
Библиография 675 Bennett, J. October 1987. The Design and Implementation of Distributed Smalltalk. SIGPLAN Notices, vol. 22(12). Bergin, J., and Greenfield, S. March 1988. What Does Modula-2 Need to Fully Support Object-Oriented Programming? SIGPLAN Notices, vol. 23(3). Bhaskar, K. October 1983. How Object-Oriented Is Your System? SIGPLAN Notices, vol. 18(10). Birman, K., Joseph, Т., Raeuchle, Т., and Abbadi, A. June 1985. Implementing Fault- Tolerant Distributed Objects. IEEE Transactions on Software Engineering, vol. SE-11(6). Birtwistle, G., Dahl, O-J., Myhrhaug, В., and Nygard, K. 1979. Simula begin. Lund, Sweden: Studentlitteratur. Black, Α., Hutchinson, N., Jul, E., and Levy, H. November 1986. Object Structure in the Emerald System. SIGPLAN Notices, vol. 21(11). Black, Α., Hutchinson, N., Jul, E., Levy, H., and Carter, L. July 1986. Distribution and Abstract Types in Emerald. Report 86-02-04. Seattle, WA: University of Washington. Blaschek, G. 1989. Implementation of Objects in Modula-2. Structured Programming, vol. 10(3). Blaschek, G., Pomberger, G., and Stritzinger, A. 1989. A Comparison of Object- Oriented Programming Languages. Structured Programming, vol. 10(4). Block, F., and Chan, N. October 1989. An Extended Frame Language. SIGPLAN Notices, vol. 24(10). Bobrow, D. November 1984. If Prolog Is the Answer, What Is the Question? Palo Alto, CA: Xerox Palo Alto Research Center. Bobrow, D. 1985. An Overview of KRL, a Knowledge Representation Language. In: Readings in Knowledge Representation, ed. R. Brachman and H. Levesque. Los Altos, CA: Morgan Kaufmann. Bobrow, D., DeMichiel, L., Gabriel, R., Keene, S., Kiczales, G., and Moon, D. September 1988. Common Lisp Object System Specification X3J13 Document 88-002R. SIGPLAN Notices, vol. 23. Bobrow, D., Kahn, K., Kiczales, G., Masinter, L., Stefik, M., and Zdybel, F. August 1985. COMMONLOOPS: Merging Common Lisp and Object-Oriented Programming, Report ISL-85-8. Palo Alto, CA: Xerox Palo Alto Research Center, Intelligent Systems Laboratory. Borgida, A. January 1985. Features of Languages for the Development of Information Systems at the Conceptual Level. IEEE Software, vol. 2(1).
676 Библиография Borgida, A. October 1986. Exceptions in Object-Oriented Languages. SIGPLAN Notices, vol. 21(10). Borning, Α., and Ingalls, D. 1982a. A Type Declaration and Inference System for Smalltalk. Palo Alto, CA: Xerox Palo Alto Research Center. Borning, Α., and Ingalls, D. 1982b. Multiple Inheritance in Smalltalk-80. Proceedings of the National Conference on Artificial Intelligence. Menlo Park, CA: AAAI. Bos, J. September 1987. PCOL-A Protocol-Constrained Object Language. SIGPLAN Notices, vol. 22(9). Briot, J., and Cointe, P. October 1989. Programming with Explicit Metaclasses in Smalltalk. SIGPLAN Notices, vol. 24(10). Buzzard, G., and Mudge, T. 1987. Object-Based Computing and the Ada Programming Language. In: Object-Oriented Computing: Concepts, vol. 1, ed. G. Peterson. New York, NY: Computer Society Press of the IEEE. Canning, P., Cook, W., Hill, W., and OlthofF, W. October 1989. Interfaces for Strongly Typed Object-Oriented Programming. SIGPLAN Notices, vol. 24(10). Caudill, P., and Wirfs-Brock, A. November 1986. A Third Generation Smalltalk-80 Implementation. SIGPLAN Notices, vol. 21(11). Chambers, C, Ungar, D., and Lee, E. October 1989. An Efficient Implementation of Self, a Dynamically Typed Object-Oriented Language Based on Prototypes. SIGPLAN Notices, vol. 24(10). Chang, S. 1990. Visual Languages and Visual Programming. New York, NY: Plenum Press. Chin, R., and Chanson, S. March 1991. Distributed Object-Based Programming Systems. ACM Computing Surveys, vol. 23(1). Clark, K. December 1988. PARLOG and Its Application. IEEE Transactions on Software Engineering, vol. 14(12). Cleaveland, С 1980. Programming Languages Considered as Abstract Data Types. Communications of the ACM. Coad, P., and Nicola, J. 1993. Object-Oriented Programming. Englewood Cliffs, NJ: Yourdon Press. Cointe, P. October 1987. Metaclasses Are First Class: The ObjVlisp Model. SIGPLAN Notices, vol. 22(12). Connor, R., Dearie, Α., Morrison, R., and Brown, A. October 1989. An Object Addressing Mechanism for Statically Typed Languages with Multiple Inheritance. SIGPLAN Notices, vol. 24(10).
Библиография 677 Conrad, J., Dengler, P., Francis, В., Glynn, J., Harvey, В., Hollis, В., Ramachandran, R., Schenken, J., Short, S., and Ullman, C. 2001. Introducing .NET. Birmingham, United Kingdom: Wrox Press. Conroy, Т., and Pelegri-Llopart, E. 1983. An Assessment of Method-Lookup Caches for Smalltalk-80 Implementations. In: Smalltalk-80: Bits of History, Words of Advice, ed. G. Krasner. Reading, MA: Addison-Wesley. Coplien, J. 1992. Advanced C++ Programming Styles and Idioms. Reading, MA: Addison-Wesley. Corradi, Α., and Leonardi, L. December 1988. The Role of Opaque Types in Building Abstractions. SIGPLAN Notices, vol. 23(12). Cox, B. January 1983. The Object-Oriented Pre-compiler. SIGPLAN Notices vol. 18(1). Cox, B. October/November 1983. Object-Oriented Programming in С Unix Review. Cox, B. January 1984. Message/Object Programming: An Evolutionary Change in Programming Technology. IEEE Software, vol. 1(1). Cox, B. February/March 1984. Object-Oriented Programming: A Power Tool for Software Craftsmen. Unix Review. Cox, B. 1986. Object-Oriented Programming: An Evolutionary Approach. Reading, MA: Addison-Wesley. Сох, В., and Hunt, B. August 1986. Objects, Icons, and Software-ICs. Byte vol. 11(8). Cox, P., and Pietrzykowski, T. March 1989. Prograph: A Pictorial View of Object- Oriented Programming. Nova Scotia, Canada: Technical University of Nova Scotia. deJong, P. October 1986. Compilation into Actors. SIGPLAN Notices, vol. 21(10). Deutsch, P. August 1981. Building Control Structures in the Smalltalk-80 System. Byte, vol. 6(8). Deutsch, P. 1983. Efficient Implementation of the Smalltalk-80 System. Proceedings of the 11th Annual ACM Symposium on the Principles of Programming Languages. New York, NY: Association of Computing Machinery. Dewhurst, S., and Stark, K. 1989. Programming in C++. Englewood Cliffs, NJ: Prentice Hall. Diederich, J., and Milton, J. May 1987. Experimental Prototyping in Smalltalk. IEEE Software, vol. 4(3). Dixon, R., McKee, Т., Schweizer, P., and Vaughn, M. October 1989. A Fast Method Dispatcher for Compiled Languages with Multiple Inheritance. SIGPLAN Notices, vol. 24(10).
678 Библиография Dony, С. August 1988. An Object-Oriented Exception Handling System for an Object- Oriented Language. Proceedings ofECOOP'88: European Conference on Object-Oriented Programming. New York, NY: Springer-Verlag. Duff, С August 1986. Designing an Efficient Language. Byte, vol. 11(8). Dussud, P. October 1989. TICLOS: An Implementation of CLOS for the Explorer Family. SIGPLAN Notices, vol. 24(10). Eccles, J. 1988. Porting from Common Lisp with Flavors to C++. Proceedings of USENIXC++ Conference. Berkeley, CA: USENIX Association. Edelson, D. September 1987. How Objective Mechanisms Facilitate the Development of Large Software Systems in Three Programming Languages. SIGPLAN Notices, vol. 22(9). Ellis, M., and Stroustrup, B. 1990. The Annotated C++ Reference Manual. Reading, MA: Addison-Wesley. Endres, T. May 1985. Clascal—An Object-Oriented Pascal. Computer Language vol. 2(5). Entsminger, G. 1990. The Tao of Objects. Redwood City, С A: M & Τ Books. Filman, R. October 1987. Retrofitting Objects. SIGPLAN Notices, vol. 22(12). Finzer, W., and Gould, L. June 1984. Programming by Rehearsal. Byte, vol. 9(6). Foote, В., and Johnson, R. October 1989. Reflective Facilities in Smalltalk-80. SIGPLAN Notices, vol. 24(10). Freeman-Benson, B. October 1989. A Module Mechanism for Constraints in Smalltalk. SIGPLAN Notices, vol. 24(10). Fukunaga, K., and Jirose, S. November 1986. An Experience with a Prolog-Based Object-Oriented Language. SIGPLAN Notices, vol. 21(11). Gabriel, R., White, J., and Bobrow, D. September 1991. CLOS Integrating Object- Oriented and Functional Programming. Communications of the ACM, vol. 34(9). Goldberg, A. August 1981. Introducing the Smalltalk-80 System. Byte, vol. 6(8). Goldberg, A. September 1988. Programmer as Reader. IEEE Software, vol. 4(5). Goldberg, Α., and Kay, A. March 1976. Smalltalk-72 Instruction Manual. Palo Alto, CA: Xerox Palo Alto Research Center. Goldberg, Α., and Kay, A. 1977. Methods for Teaching the Programming Language Smalltalk. Report SSL 77-2. Palo Alto, CA: Xerox Palo Alto Research Center. Goldberg, Α., and Pope, S. Summer 1989. Object-Oriented Programming Is Not Enough. American Programmer, vol. 2(7-8). Goldberg, Α., and Robson, D. 1983. Smalltalk-80: The Language and Its Implementation. Reading, MA: Addison-Wesley.
Библиография 679 Goldberg, Α., and Robson, D. 1989. Smalltalk-80: The Language. Reading, MA: Addison-Wesley. Goldberg, Α., and Ross, J. August 1981. Is the Smalltalk-80 System for Children? Byte, vol. 6(8). Goldstein, T. May 1989. The Object-Oriented Programmer. The C++ Report vol. 1(5). Gonsalves, G., and Silvestri, A. December 1986. Programming in Smalltalk-80: Observations and Remarks from the Newly Initiated. SIGPLANNotices vol. 21(12). Gorlen, K. 1989. An Introduction to C++. In: UNIX System V ATT C++ Language System, Release 2.0 Selected Readings. Murray Hill, NJ: ATT Bell Laboratories. Gorlen, K., Orlow, S., and Plexico, P. 1990. Data Abstraction and Object-Oriented Programming in C++. New York, NY: John Wiley and Sons. Gougen, J., and Meseguer, J. 1987. Unifying Functional, Object-Oriented, and Relational Programming with Logical Semantics. In: Research Directions in Object- Oriented Programming, ed. B. Schriver and P. Wegner. Cambridge, MA: The MIT Press. Graube, N. August 1988. Reflexive Architecture: From ObjVLisp to CLOS. Proceedings of ECOOP'88: European Conference on Object-Oriented Programming. New York, NY: Springer-Verlag. Grogono, P. November 1989. Polymorphism and Type Checking in Object-Oriented Languages. SIGPLAN Notices, vol. 24(11). Grogono, P. 1991. Issues in the Design of an Object-Oriented Programming Language. Structured Programming, vol. 12(1). Hagmann, R. 1983. Preferred Classes: A Proposal for Faster Smalltalk-80 Execution. In: Smalltalk-80: Bits of History, Words of Advice, ed. G. Krasner. Reading, MA: Addison-Wesley. Hailpern, В., and Nguyen, V. 1987. A Model for Object-Based Inheritance. In: Research Directions in Object-Oriented Programming, ed. B. Schriver and P. Wegner. Cambridge, MA: The MIT Press. Halbert, D., and O'Brien, P. September 1988. Using Types and Inheritance in Object- Oriented Programming. IEEE Software, vol. 4(5). Halstead, R. 1987. Object Management on Distributed Systems. In: Object-Oriented Computing: Implementations, vol. 2, ed. G. Peterson. New York, NY: Computer Society Press of the IEEE. Harland, D., Szyplewski, M., and Wainwright, J. October 1985. An Alternative View of Polymorphism. SIGPLAN Notices, vol. 20(10). Hendler, J. October 1986. Enhancement for Multiple Inheritance. SIGPLAN Notices, vol. 21(10).
680 Библиография Hines, Т., and Unger, E. 1986. Conceptual Object-Oriented Programming. Manhattan, KS: Kansas State University. Ingalls, D. 1978. The Smalltalk-76 Programming System Design and Implementation. Proceedings of the Fifth Annual ACM Symposium on Principles of Programming Languages. New York, NY: Association of Computing Machinery. Ingalls, D. August 1981a. Design Principles Behind Smalltalk. Byte, vol. 6(8). Ingalls, D. August 1981b. The Smalltalk Graphics Kernel. Byte, vol. 6(8). Ingalls, D. 1983. The Evolution of the Smalltalk Virtual Machine. In: Smalltalk-80: Bits of History, Words of Advice, ed. G. Krasner. Reading, MA: Addison-Wesley. Ingalls, D. November 1986. A Simple Technique for Handling Multiple Polymorphism. SIGPLAN Notices, vol. 21(11). Ishikawa, Y, and Tokoro, M. 1987. Orient84/K: An Object-Oriented Concurrent Programming Language for Knowledge Representation. In: Object-Oriented Concurrent Programming, ed. Yonezawa and M. Tokoro. Cambridge, MA: The MIT Press. Jackson, M. May 1988. Objects and Other Subjects. SIGPLAN Notices, vol. 23(5). Jacky, J., and Kalet, I. September 1987. An Object-Oriented Programming Discipline for Standard Pascal. Communications of the ACM, vol. 30(9). Jacobson, I. November 1986. Language Support for Changeable, Large, Real-Time Systems. SIGPLAN Notices, vol. 21(11). Jeffery, D. February 1989. Object-Oriented Programming in ANSI C. Computer Language. Jenkins, M., and Glasgow, J. January 1986. Programming Styles in Nial. IEEE Software, vol. 3(1). Johnson, R. November 1986. Type-Checking Smalltalk. SIGPLAN Notices vol. 21(11). Johnson, R., Graver, J., and Zurawski, L. September 1988. TS: An Optimizing Compiler for Smalltalk. SIGPLAN Notices, vol. 23(11). Kaehler, T. November 1986. Virtual Memory on a Narrow Machine for an Object- Oriented Language. SIGPLAN Notices, vol. 21(11). Kaehler, Т., and Patterson, D. 1986. A Taste of Smalltalk. New York, NY: W. W. Norton. Kaehler, Т., and Patterson, D. August 1986. A Small Taste of Smalltalk. Byte, vol. 11(8). Kahn, K., Tribble, E., Miller, M., and Bobrow, D. November 1986. Objects in Concurrent Logic Programming Languages. SIGPLAN Notices, vol. 21(11).
Библиография 681 Kahn, К., Tribble, E., Miller, Μ., and Bobrow, D. 1987. Vulcan: Logical Concurrent Objects. In: Research Directions in Object-Oriented Programming, ed. B. Schriver and P. Wegner. Cambridge, MA: The MIT Press. Kaiser, G., and Garlan, D. October 1987. MELDing Data Flow and Object-Oriented Programming. SIGPLAN Notices, vol. 22(12). Kalme, С March 27,1986. Object-Oriented Programming: A Rule-Based Perspective. Los Angeles, CA: Inference Corporation. Kay, A. New Directions for Novice Programming in the 1980s. Palo Alto, CA: Xerox Palo Alto Research Center. Keene, S. 1989. Object-Oriented Programming in Common Lisp. Reading, MA: Addison-Wesley. Kelly, K., Rischer, R., Pleasant, M., Steiner, D., McGrew, C, Rowe, J., and Rubin, M. March 30, 1986. Textual Representations of Object-Oriented Programs for Future Programmers. Palo Alto, CA: Xerox AI Systems. Kempf, R. October 1987. Teaching Object-Oriented Programming with the KEE System. SIGPLAN Notices, vol. 22(12). Kempf, J., Harris, W., D'Souza, R., and Snyder, A. October 1987. Experience with CommonLoops. SIGPLAN Notices, vol. 22(12). Khoshafian, S., and Copeland, G. November 1986. Object Identity. SIGPLANNotices, vol. 21(11). Kiczales, G., Rivieres, J., and Bobrow, D. 1991. The Art of the Metaobject Protocol. Cambridge, MA: The MIT Press. Kilian, M. April 1987. An Overview of the Trellis/Owl Compiler. Hudson, MA: Digital Equipment Corporation. Kimminau, D., and Seagren, M. 1987. Comparison of Two Prototype Developments Using Object-Based Programming. Naperville, IL: AT&T Bell Laboratories. Knowledge Systems Corporation. 1987. PluggableGauges Version 1.0 User Manual. Cary, NC. Knudsen, J., and Madsen, O. August 1988. Teaching Object-Oriented Programming Is More Than Teaching Object-Oriented Programming Languages. Proceedings of ECOOP'88: European Conference on Object-Oriented Programming. New York, NY: Springer-Verlag. Knudsen, J. August 1988. Name Collision in Multiple Classification Hierarchies. Proceedings of ECOOP'88: European Conference on Object-Oriented Programming. New York, NY: Springer-Verlag. Korson, T, and McGregor, J. September 1990. Understanding Object-Oriented: A Unifying Paradigm. Communications of the ACM, vol. 33(9).
682 Библиография Koshmann, Т., and Evens, M. July 1988. Bridging the Gap Between Object-Oriented and Logic Programming. IEEE Software, vol. 5(4). Koskimies, K., and Paakki, J. July 1987. TOOLS: A Unifying Approach to Object- Oriented Language Interpretation. SIGPLAN Notices, vol. 22(7). Krasner, G. August 1981. The Smalltalk-80 Virtual Machine. Byte, vol. 6(8). Krasner, G., ed. 1983. Smalltalk-80: Bits of History, Words of Advice. Reading, MA: Addison-Wesley. Krasner, G., and Pope, S. August/September 1988. A Cookbook for Using the Model- View-Controller User Interface Paradigm in Smalltalk-80. Journal of Object- Oriented Programming, vol. 1(3). Kristensen, В., Madsen, O., Moller-Pedersen, В., and Nygaard, K. 1987. The BETA Programming Language. In: Research Directions in Object-Oriented Programming, ed. B. Schriver and P. Wegner. Cambridge, MA: The MIT Press. LaLonde, W. April 1989. Designing Families of Data Types Using Exemplars. ACM Transactions on Programming Languages and Systems, vol. 11(2). LaLonde, W., and Pugh, J. 1990. Inside Smalltalk, vol. 1 and 2. Englewood Cliffs, NJ: Prentice Hall. LaLonde, W., Thomas, D., and Pugh, J. November 1986. An Examplar Based Smalltalk. SIGPLAN Notices, vol. 21(11). Lang, K., and Peralmutter, B. November 1986. Oaklisp: An Object-Oriented Scheme with First Class Types. SIGPLAN Notices, vol. 21(11). Laursen, J., and Atkinson, R. October 1987. Opus: A Smalltalk Production System. SIGPLAN Notices, vol. 22(12). Lieberherr, K., and Holland, I. March 1989. Formulations and Benefits of the Law of Demeter. SIGPLAN Notices, vol. 24(3). Lieberherr, K., and Holland, I. September 1989. Assuring Good Style for Object- Oriented Programs. IEEE Software, vol. 6(5). Lieberherr, K., Holland, I., Lee, G., and Riel, A. June 1988. An Objective Sense of Style. IEEE Computer, vol. 21(6). Lieberman, H. November 1986. Using Prototypical Objects to Implement Shared Behavior in Object-Oriented Systems. SIGPLAN Notices, vol. 21(11). Lieberman, H. 1987. Concurrent Object-Oriented Programming in Act 1. In: Object- Oriented Concurrent Programming, ed. A. Yonezawa and M. Tokoro. Cambridge, MA: The MIT Press. Lieberman, H., Stein, L., and Ungar, D. May 1988. Of Types and Prototypes: The Treaty of Orlando. SIGPLAN Notices, vol. 23(5).
Библиография 683 Lim, J., and Johnson, R. April 1989. The Heart of Object-Oriented Concurrent Programming. SIGPLAN Notices, vol. 24(4). Linowes, J. August 1988. It's an Attitude. Byte, vol. 13(8). Lippman, S., Lajoie, J., and Moo, B. 2005. C++ Primer. Fourth Edition. Boston, MA: Addison-Wesley. Liskov, В., Atkinson, R., Bloom, Т., Moss, E., Schaffert, C, Scheifler, R., and Snyder, R. 1981. CLUReference Manual New York, NY: Springer-Verlag. Liskov, В., Snyder, Α., Atkinson, R., and Schaffert, С 1980. Abstraction Mechanisms in CLU. In: Programming Language Design, ed. A. Wasserman. New York, NY: Computer Society Press. Liu, C. March 1991. On the Object-Orientedness of C++. SIGPLANNotices vol. 26(3). Lujun, S., and Zhongxiu. August 1987. An Object-Oriented Programming Language for Developing Distributed Software. SIGPLAN Notices, vol. 22(8). MacLennan, B. 1987. Values and Objects in Programming Languages. In: Object- Oriented Computing: Concepts, vol. 1, ed. G. Peterson. New York, NY: Computer Society Press of the IEEE. Madsen, O. 1987. Block Structure and Object-Oriented Languages. In: Research Directions in Object-Oriented Programming, ed. B. Schriver and P. Wegner. Cambridge, MA: The MIT Press. Madsen, O., and Moller-Pedersen, B. August 1988. What Object-Oriented Programming May Be-And What It Does Not Have to Be. Proceedings ofECOOP'88: European Conference on Object-Oriented Programming. New York, NY: Sprin- ger-Verlag. Madsen, O., and Moller-Pedersen, B. October 1989. Virtual Classes: A Powerful Mechanism in Object-Oriented Programming. SIGPLAN Notices, vol. 24(10). Manci, D. 1990. Use of Metrics to Evaluate C++. Liberty Corner, NJ: AT&T Bell Laboratories. Mannino, M., Choi, I., and Batory, D. November 1990. The Object-Oriented Functional Data Language. IEEE Transactions on Software Engineering vol. 16(11). Marcus, R. November 1985. Generalized Inheritance. SIGPLAN Notices vol. 20(11). Markowitz, V, and Raz, Υ 1983. Eroll: An Entity-Relationship, Role-Oriented Query Language. In: Entity-Relationship Approach to Software Engineering, ed. C. Davis et al. Amsterdam, The Netherlands: Elsevier Science. Masini, G., Napoli, Α., Colnet, D., Leonard, D., and Tompre, K. 1991. Object-Oriented Languages. London, England: Academic Press.
684 Библиография Mellender, F. October 1988. An Integration of Logic and Object-Oriented Programming. SIGPLAN Notices, vol. 23(10). Methfessel, R. April 1987. Implementing an Access and Object-Oriented Paradigm in a Language That Supports Neither. SIGPLAN Notices, vol. 22(4). Meyer, B. November 1986. Genericity versus Inheritance. SIGPLAN Notices vol. 21(11). Meyer, B. February 1987. Eiffel: Programming for Reusability and Extendability. SIGPLAN Notices, vol. 22(2). Meyer, B. November/December 1988. Harnessing Multiple Inheritance. Journal of Object-Oriented Programming, vol. 1(4). Micallef, J. April/May 1988. Encapsulation, Reusability, and Extensibility in Object- Oriented Programming Languages. Journal of Object-Oriented Programming, vol. 1(1). Microsoft C++ Tutorial. 1992. Redmond, WA: Microsoft Corporation. Microsoft Windows Guide to Programming. 1992. Redmond, WA: Microsoft Corporation. Minsky, N., and Rozenshtein, D. October 1987. A Law-Based Approach to Object- Oriented Programming. SIGPLAN Notices, vol. 22(12). Minsky, N., and Rozenshtein, D. October 1989. Controllable Delegation: An Exercise in Law-Governed Systems. SIGPLAN Notices, vol. 24(10). Miranda, E. October 1987. BrouHaHa-A Portable Smalltalk Interpreter. SIGPLAN Notices, vol. 22(12). Mittal, S., Bobrow, D., and Kahn, K. November 1986. Virtual Copies: At the Boundary Between Classes and Instances. SIGPLAN Notices, vol. 21(11). Moon, D. November 1986. Object-Oriented Programming with Flavors. SIGPLAN Notices, vol. 21(11). Morrison, R., Dearie, Α., Connor, R., and Brown, A. July 1991. An Ad Hoc Approach to the Implementation of Polymorphism. ACM Transactions on Programming Languages and Systems, vol. 13(3). Mossenbock, H., and Tempi, J. 1989. Object Oberon—A Modest Object-Oriented Language. Structured Programming, vol. 10(4). Mudge, T. March 1985. Object-Based Computing and the Ada Language. IEEE Computer, vol. 18(3). Murray, R. 1990. C++ Tactics. Liberty Corner, NJ: AT&T Bell Laboratories. Nelson, M. October 1991. Concurrency and Object-Oriented Programming. SIGPLAN Notices, vol. 26(10).
Библиография 685 Nierstrasz, О. October 1987. Active Objects in Hybrid. SIGPLANNotices, vol. 22(12). Novak, G. June 1983. Data Abstraction in GLISP. SIGPLAN Notices, vol. 18(6). Novak, G. Fall 1983. GLISP: A Lisp-Based Programming System with Data Abstraction. AI Magazine, vol. 4(3). Nygaard, K. October 1986. Basic Concepts in Object-Oriented Programming. SIGPLAN Notices, vol. 21(10). Nygaard, K., and Dahl, O-J. 1981. The Development of the Simula Languages. In: History of Programming Languages, ed. R. Wexelblat. New York, NY: Academic Press. O'Brien, P. November 15, 1985. Trellis Object-Based Environment: Language Tutorial. Hudson, MA: Digital Equipment Corporation. O'Grady, F. July/August 1990. Is There Life After COBOL? American Programmer, vol. 3(7-8). Object-Oriented Programming Workshop. October 1986. SIGPLAN Notices, vol. 21(10). OlthofF, W. 1986. Augmentation of Object-Oriented Programming by Concepts of Abstract Data Type Theory: The ModPascal Experience, Kaiserslautern, West Germany: University of Kaiserslautern. Osterbye, K. June/July 1988. Active Objects: An Access-Oriented Framework for Object-Oriented Languages. Journal of Object-Oriented Programming, vol. 1 (2). Paepcke, A. October 1989. PCLOS: A Critical Review. SIGPLAN Notices, vol. 24(10). Pare Place Systems. 1988. The Smalltalk-80 Programming System Version VI 2.3. Palo Alto, CA. Pascoe, G. August 1986. Elements of Object-Oriented Programming. Byte, vol. 11(8). Pascoe, G. November 1986. Encapsulators: A New Software Paradigm in Smalltalk- 80. SIGPLAN Notices, vol. 21(11). Perez, E. September/October 1988. Simulating Inheritance with Ada. Ada Letters, vol. 8(7). Peterson, G., ed. 1987. Object-Oriented Computing Concepts. New York, NY: Computer Society Press of the IEEE. Pinson, L., and Wiener, R. 1988. An Introduction to Object-Oriented Programming and Smalltalk. Reading, MA: Addison-Wesley. Pohl, I. 1989. C++for С Programmers. Redwood City, CA: Benjamin/Cummings. Pokkunuri, B. November 1989. Object-Oriented Programming. SIGPLAN Notices, vol. 24(11).
686 Библиография Ponder, С, and Bush, В. June 1992. Polymorphism Considered Harmful. SIGPLAN Notices, vol. 27(6). Pountain, D. August 1986. Object-Oriented FORTH. Byte, vol. 11(8). Proceedings of ECOOP'88: European Conference on Object-Oriented Programming. August 1988. New York, NY: Springer-Verlag. Proceedings ofOOPSLA'86: Object-Oriented Programming Systems, Languages, and Applications. November 1986. SIGPLAN Notices, vol. 21(11). Proceedings ofOOPSLA'87: Object-Oriented Programming Systems, Languages,and Applications. October 1987. SIGPLAN Notices, vol. 22(12). Proceedings ofOOPSLA'88: Object-Oriented Programming Systems, Languages, and Applications. September 1988. SIGPLAN Notices, vol. 23(11). Proceedings ofOOPSLA'89: Object-Oriented Programming Systems, Languages, and Applications. October 1989. SIGPLAN Notices, vol. 24(10). Proceedings ofOOPSLA'90. Object-Oriented Programming Systems, Languages, and Applications. October 1990. SIGPLAN Notices, vol. 25(10). Proceedings ofOOPSLA'91. Object-Oriented Programming Systems, Languages, and Applications. November 1991. SIGPLAN Notices, vol. 26(11). Proceedings ofOOPSLA'92. Object-Oriented Programming Systems, Languages, and Applications. October 1992. SIGPLAN Notices, vol. 27(10). Proceedings of the ACM SIGPLAN Workshop on Object-Based Concurrent Programming April 1989. SIGPLAN Notices, vol. 24(4). Proceedings of the USENIX Association C++ Worhhop. November 1987. Berkeley, С A: USENIX Association. Proceedings of the Workshop on Data Abstraction, Databases, and Conceptual Modeling. 1980. SIGPLAN Notices, vol. 16(1). Pugh, J. March 1984. Actors-The Stage Is Set. SIGPLAN Notices, vol. 19(3). Rathke, C. 1986. ObjTalk: Representation von Wissen in einer objektorientierten Sprache. Stuttgart, West Germany: Institut fur Informatik der Universitat Stuttgart. Rentsch, T. September 1982. Object-Oriented Programming. SIGPLAN Notices, vol. 17(12). Rettig, M., Morgan, Т., Jacobs, J., and Wimberly, D. January 1989. Object-Oriented Programming in ΑΙ. ΑΙ Expert. Robson, D. August 1981. Object-Oriented Software Systems. Byte, vol. 6(8). Rumbaugh, J. October 1987. Relations as Semantic Constructs in an Object-Oriented Language. SIGPLAN Notices, vol. 22(12).
Библиография 687 Russo, V., and Kaplan, S. 1988. A C++ Interpreter for Scheme. Proceedings of USENIXC++ Conference. Berkeley, CA: USENIX Association. Sakkinen, M. August 1988. On the Darker Side of C++. Proceedings ofECOOP'88: European Conference on Object-Oriented Programming. New York, NY: Sprin- ger-Verlag. Sakkinen, M. December 1988. Comments on "the Law of Demeter" and C++. SIGPLAN Notices, vol. 23(12). Saltzer, J. 1979. Naming and Binding of Objects. In: Operating Systems, ed. R. Bayer et al. New York, NY: Springer-Verlag. Sandberg, D. November 1986. An Alternative to Subclassing. SIGPLAN Notices, vol. 21(11). Sandberg, D. October 1988. Smalltalk and Exploratory Programming. SIGPLAN Notices, vol. 23(10). Saunders, J. March/April 1989. A Survey of Object-Oriented Programming Languages. Journal of Object-Oriented Programming, vol. 1(6). Schaffert, C, Cooper, Т., and Wilpolt, С November 25, 1985. Trellis Object-Based Environment: Language Reference Manual. Hudson, MA: Digital Equipment Corporation. Schaffert, C, Cooper, Т., Bullis, В., Kilian, M., and Wilpolt, C. November 1986. An Introduction to Trellis/Owl. SIGPLAN Notices, vol. 21(11). Schmucker, K. 1986a. MacApp: An Application Framework. Byte, vol. 11(8). Schmucker, K. 1986b. Object-Oriented Languages for the Macintosh. Byte, vol. 11(8). Schmucker, K. 1986c. Object-Oriented Programming for the Macintosh. Hasbrouk Heights, NJ: Hayden. Schriver, В., and Wegner, P., eds. 1987. Research Directions in Object-Oriented Programming. Cambridge, MA: The MIT Press. Seidewitz, E. October 1987. Object-Oriented Programming in Smalltalk and Ada. SIGPLAN Notices, vol. 22(12). Seidewitz, E. March/April 1992. Object-Oriented Programming with Mixins in Ada. Ada Letters, vol. XII(2). Shafer, D. 1988. Hyper Talk Programming. Indianapolis, IN: Hayden. Shah, Α., Rumbaugh, J., Hamel, J., and Borsari, R. October 1989. DSM: An Object- Relationship Modeling Language. SIGPLAN Notices, vol. 24(10). Shammas, N. October 1988. Smalltalk a la C. Byte, vol. 13(10). Shan, Υ October 1989. An Event-Driven Model-View-Controller Framework for Smalltalk. SIGPLAN Notices, vol. 24(10).
688 Библиография Shapiro, J. 1991. A C++ Toolkit Englewood Cliffs, NJ: Prentice Hall. Shaw, M. 1981. ALPHARD: Form and Content New York, NY: Springer-Verlag. Shibayama, E. September 1988. How to Invent Distributed Implementation Schemes of an Object-Based Concurrent Language—A Transformational Approach. SIGPLAN Notices, vol. 23(11). Shibayama, E., and Yonezawa, A. 1987. Distributed Computing in ABCL/1. In: Object-Oriented Concurrent Programming, ed. Yonezawa and M. Tokoro. Cambridge, MA: The MIT Press. Shopiro, J. December 13, 1988. Programming Techniques with C++. C++ Tutorial Program of the USENIX Conference. Denver, CO: USENIX Association. Shopiro, J. December 1989. An Example of Multiple Inheritance in C++: A Model of the Iostream Library. SIGPLAN Notices, vol. 24(12). Simonian, R., and Crone, M. November/December 1988. InnovAda: True Object- Oriented Programming in Ada. Journal of Object-Oriented Programming vol. 1(4). Snyder, A. February 1985. Object-Oriented Programming for Common Lisp. Report ATC-85-1. Palo Alto, CA: Hewlett-Packard. Snyder, A. November 1986. Encapsulation and Inheritance in Object-Oriented Programming Languages. SIGPLAN Notices, vol. 21(11). Snyder, A. 1987. Inheritance and the Development of Encapsulated Software Components. In: Research Directions in Object-Oriented Programming, ed. B. Schriver and P. Wegner. Cambridge, MA: The MIT Press. Snyder, A. January 1993. The Essence of Objects: Concepts and Terms. IEEE Software, vol. 10(1). Software Productivity Solutions. 1988. Classical-Ada User Manual Melbourne, FL. Stankovic, J. April 1982. Software Communication Mechanisms: Procedure Calls versus Messages. IEEE Computer, vol. 15(4). Stefik, M., and Bobrow, D. Winter 1986. Object-Oriented Programming: Themes and Variations. AI Magazine, vol. 6(4). Stefik, M., Bobrow, D., Mittal, S., and Conway, L. Fall 1983. Knowledge Programming in Loops. AI Magazine, vol. 4(3). Stein, L. October 1987. Delegation Is Inheritance. SIGPLAN Notices, vol. 22(12). Stroustrup, B. January 1982. Classes: An Abstract Data Type Facility for the С Language. SIGPLAN Notices, vol. 17(1). Stroustrup, B. October 1986. An Overview of C++. SIGPLAN Notices, vol. 21(10).
Библиография 689 Stroustrup, В. 1987. The Evolution of C++. Proceedings of the USENIX C++ Workshop. Santa Fe, NM: USENIX Association. Stroustrup, B. November 1987. Possible Directions for C++. Proceedings of the USENIX C++ Worbhop. Santa Fe, NM: USENIX Association. Stroustrup, B. 1988a. Parameterized Types for C++. Proceedings of USENIX C++ Conference. Berkeley, CA: USENIX Association. Stroustrup, B. May 1988b. What Is Object-Oriented Programming? IEEE Software vol. 5(3). Stroustrup, B. August 1988c. A Better C? Byte, vol. 13(8). Stroustrup, B. 1991. The C+ Programming Language. Second Edition. Reading, MA: Addison-Wesley. Stroustrup, B. 2000. The C++ Programming Language. Special Third Edition. Boston, MA: Addison-Wesley. Suzuki, N. 1981. Inferring Types in Smalltalk. In: Proceedings of the Eighth Annual Symposium of ACM Principles of Programming Languages. New York, NY: Association of Computing Machinery. Suzuki, N., and Terada, M. 1983. Creating Efficient Systems for Object-Oriented Languages. Proceedings of the 11th Annual ACM Symposium on the Principles of Programming Languages. New York, NY: Association of Computing Machinery. Symposium on Actor Languages. October 1980. Creative Computing. Tektronix. 1988. Modular Smalltalk. Tesler, L. August 1986. Programming Experiences. Byte, vol. 11(8). The Smalltalk-80 System. August 1981. Byte, vol. 6(8). Thomas, D. March 1989. What's in an Object? Byte, vol. 14(3). Tieman, M. May 1,1988. User's Guide to GNU C++. Cambridge, MA: Free Software Foundation. Tokoro, M., and Ishikawa, Y. October 1986. Concurrent Programming in Orient84/K: An Object-Oriented Knowledge Representation Language. SIGPLAN Notices, vol. 21(10). Touati, H. May 1987. Is Ada an Object-Oriented Programming Language? SIGPLAN Notices, vol. 22(5). Touretzky, D. 1986. The Mathematics of Inheritance Systems. Los Altos, CA: Morgan Kaufman Publishers. Tripathi, Α., and Berge, E. An Implementation of the Object-Oriented Concurrent Programming Language SINA. Software—Practice and Experience, vol. 19(3).
690 Библиография U.S. Department of Defense. February 1983. Reference Manual for the Ada Programming Language. Washington, DC: Ada Joint Program Office. Ungar, D. September 1988. Are Classes Obsolete? SIGPLAN Notices, vol. 23(11). Ungar, D., and Smith, R. October 1987. Self: The Power of Simplicity. SIGPLAN Notices, vol. 22(12). van den Bos, J., and Laffra, С October 1989. PROCOL: A Parallel Object Language with Protocols. SIGPLAN Notices, vol. 24(10). Vaucher, J., Lapalme, G., and Malenfant, J. August 1988. SCOOP: Structured Concurrent Object-Oriented Prolog. Proceedings ofECOOP'88: European Conference on Object-Oriented Programming. New York, NY: Springer-Verlag. Warren, S., and Abbe, D. May 1980. Presenting Rosetta Smalltalk. Datamation. Watanabe, Т., and Yonezawa, A. September 1988. Reflection in an Object-Oriented Concurrent Language. SIGPLAN Notices, vol. 23(11). Wegner, P. October 1987. Dimensions of Object-Based Language Design. SIGPLAN Notices, vol. 22(12). Wegner, P. January 1988. Workshop on Object-Oriented Programming at ECOOP 1987. SIGPLAN Notices, vol. 23(1). Wegner, P. August 1990. Concepts and Paradigms of Object-Oriented Programming. OOPS Messenger, vol. 1(1). Wegner, P. October 1992. Dimensions of Object-Oriented Modeling. IEEE Computer, vol. 25(10). Wiener, R. June 1987. Object-Oriented Programming in C++-A Case Study. SIGPLAN Notices, vol. 22(6). Williams, G. Summer 1989. Designing the Future: The Power of Object-Oriented Programming. American Programmer, vol. 2(7-8). Wilson, R. November 1, 1987. Object-Oriented Languages Reorient Programming Techniques. Computer Design, vol. 26(20). Winblad, Α., Edwards, S., and King, D. 1990. Object-Oriented Software. Reading, MA: Addison-Wesley. Winston, P., and Horn, B. 1989. Lisp. Third Edition. Reading, MA: Addison-Wesley. Wirfs-Brock, R., and Wilkerson, B. September 1988. An Overview of Modular Smalltalk. SIGPLAN Notices, vol. 23(11). Wirth, N. June 1987. Extensions of Record Types. SIGCSE Bulletin, vol. 19(2). Wirth, N.July 1988a. From Modula to Oberon. Software—Practice and Experience, vol. 18(7).
Библиография 691 Wirth, N. July 1988b. The Programming Language Oberon. Software—Practice and Experience, vol. 18(7). Wolf, W. September 1989. A Practical Comparison of Two Object-Oriented Languages. IEEE Software, vol. 6(5). Yokote, Y, and Tokoro, M. November 1986. The Design and Implementation of Concurrent Smalltalk. SIGPLAN Notices, vol. 21(11). Yokote, Y, and Tokoro, M. October 1987. Experience and Evolution of Concurrent Smalltalk. SIGPLAN Notices, vol. 22(12). Yonezawa, Α., and Tokoro, M., eds. 1987. Object-Oriented Concurrent Programming. Cambridge, MA: The MIT Press. Yonezawa, Α., Briot, J., and Shibayama, E. November 1986. Object-Oriented Concurrent Programming in ABCL/1. SIGPLAN Notices, vol. 21(11). Yonezawa, Α., Shibayama, E., Takada, Т., and Honda, Υ 1987. Modeling and Programming in an Object-Oriented Concurrent Language ABCL/1. In: Object-Oriented Concurrent Programming, ed. Yonezawa and M. Tokoro. Cambridge, MA: The MIT Press. Yourdon, E. February 1990. Object-Oriented COBOL. American Programmer vol. 3(2). Yourdon, E. January 1992. Modeling Magic. American Programmer, vol. 5(1). Zave, P. September 1989. A Compositional Approach to Multiparadigm Programming. IEEE Software, vol. 6(5). 3. Разработка программного обеспечения Abdel-Hamid, Т., and Madnick, S. 1991. Software Project Dynamics. Englewood Cliffs, NJ: Prentice Hall. Abelson, H., and Sussman, G. 1985. Structure and Interpretation of Computer Programs. Cambridge, MA: The MIT Press. Andrews, D., and Leventhal, N. 1993. FUSION: Integrating IE, CASE, and J AD: A Handbook for Reengineering the Systems Organization. Englewood Cliffs, NJ: Yourdon Press. Appleton, D. January 15, 1986. Very Large Projects. Datamation. Axon, J. 1974a. The Program Development Process: The Individual Programmer. Vol. 1. Reading, MA: Addison-Wesley. Axon, J. 1974b. The Program Development Process: The Programming Team. Vol. 2. Reading, MA: Addison-Wesley. Babich, W. 1986. Software Configuration Management. Reading, MA: Addison- Wesley.
692 Библиография Ben-Ari, Μ. 1982. Principles of Concurrent Programming. Englewood Cliffs, NJ: Prentice Hall. Berard, E. 1993. Essays on Object-Oriented Software Engineering. Englewood Cliffs, NJ: Prentice Hall. Berson, A. 1992. Client/Server Architecture. New York, NY: McGraw-Hill. Berzins, V., and Luqi. 1991. Software Engineering with Abstractions. Reading, MA: Addison-Wesley. Biggerstaff, Т., and Perlis, A. 1989. Software Reusability. New York, NY: ACM Press. Bisant, D., and Lyle, J. October 1989. A Two-Person Inspection Method to Improve Programming Productivity. IEEE Transactions on Software Engineering, vol. 15(10). Bischofberger, W., and Keller, R. 1989. Enhancing the Software Life Cycle by Prototyping. Structured Programming. Bloom, P. April 1993. Trends in Client-Server/Cooperative Processing Application Development Tools. American Programmer. Boar, B. 1984. Application Prototyping. New York, NY: John Wiley and Sons. Boehm, B. August 1986. A Spiral Model of Software Development and Enhancement. Software Engineering Notes, vol. 11(4). Boehm, B. September 1992. Risk Control. American Programmer, vol. 5(7). Boehm, B. 1989. IEEE Tutorial on Software Risk Management. IEEE Computer Society Press. Boehm, B. October 2002. Software Risk Management: Overview and Recent Developments. 17th International Forum on COCOMO and Software Cost Modeling. Los Angeles, CA. Boehm, В., and Papaccio, P. 1988. Understanding and Controlling Software Costs. IEEE Transactions on Software Engineering, vol. 4(10). Boehm-Davis, D., and Ross, L. October 1984. Approaches to Structuring the Software Development Process. Report GEC/DIS/TR-84-B1V-1. Arlington, VA: General Electric. Booch, G. 1986. Software Engineering with Ada. Menlo Park, CA: Benjamin/Cum- mings. Brooks, F. 1975. The Mythical Man-Month. Reading, MA: Addison-Wesley. Brooks, F. April 1987. No Silver Bullet: Essence and Accidents of Software Engineering. IEEE Computer, vol. 20(4). Charette, R. 1989. Software Engineering Risk Analysis and Management. New York, NY: McGraw-Hill.
Библиография 693 Chidamber, S., and Kemerer, C. 1991. Towards a Metrics Suite for Object-Oriented Design. Phoenix, Arizona: OOPSLA'91. Chidamber, S., and Kemerer, C. 1993. A Metrics Suite for Object-Oriented Design. Cambridge, MA: MIT Sloan School of Management. Chmura, L., Norcio, Α., and Wicinski, T. July 1990. Evaluating Software Design Processes by Analyzing Change Date Over Time. IEEE Transactions on Software Engineering, vol. 16(7). Corkill, D. D. September 1991. Blackboard Systems. AI Expert, vol. 6(9), pp. 40-47. Cox, B. November 1990. Planning the Software Industrial Revolution. IEEE Software, vol. 7(6). Curtis, B. May 17, 1989. . . .But You Have to Understand, This Isn't the Way We Develop Software at Our Company. MCC Technical Report Number STP-203- 89. Austin, TX: Microelectronics and Computer Technology Corporation. Curtis, В., Kellner, M., and Over, J. September 1992. Process Modeling. Communications of the ACM, vol. 35(9). Dahl, O., Dijkstra, E., and Hoare, С A. R. 1972. Structured Programming. London, England: Academic Press. Davis, A. 1990. Software Requirements: Analysis and Specification. Englewood Cliffs, NJ: Prentice Hall. Davis, Α., Bersoff, E., and Comer, E. October 1988. A Strategy for Comparing Alternative Software Development Life Cycle Models. IEEE Transactions on Software Engineering, vol. 14(10). Davis, C, Jajodia, S., Ng, P., and Yeh, R., eds. 1983. Entity-Relationship Approach to Software Engineering. Amsterdam, The Netherlands: Elsevier Science. DeMarco, Т., and Lister, T. 1987. Peopleware. New York, NY: Dorset House. DeRemer, F., and Kron, H. 1980. Programming-in-the-Large versus Programming- in-the-Small. In: Tutorial on Software Design Techniques, Third Edition, ed. P. Freeman and A. Wasserman. New York, NY: Computer Society Press of the IEEE. Dewire, D. 1992. Client/Server Computing. New York, NY: McGraw-Hill. Dijkstra, E. 1979. Programming Considered as a Human Activity. In: Classics in Software Engineering, ed. E. Yourdon. New York, NY: Yourdon Press. Dijkstra, E. 1982. Selected Writings on Computing: A Personal Perspective. New York, NY: Springer-Verlag. Dowson, M. August 1986. The Structure of the Software Process. Software Engineering Notes, vol. 11(4).
694 Библиография Dowson, M., Nejmeh, В., and Riddle, W. February 1990. Software Engineering Practices in Europe, Japan, and the U.S. Boulder, CO: Software Design and Analysis. Dreger, B. 1989. Function Point Analysis. Englewood Cliffs, NJ: Prentice Hall. Eastman, N. 1984. Software Engineering and Technology. Technical Directions vol. 10(1). Bethesda, MD: IBM Federal Systems Division. Fagan, M. June 1976. Design and Code Inspections and Process Control in the Development of Programs. IBM-TR-00.73. Foster, С 1981. Real-Time Programming. Reading, MA: Addison-Wesley. Freedman, D. February 1992. The Devil Is in the Details: Everything Important Must Be Reviewed. American Programmer, vol. 5(2). Freeman, P. 1975. Software Systems Principles. Chicago, IL: Science Research Associates. Freeman, P., and Wasserman, Α., eds. 1983. Tutorial on Software Design Techniques. Fourth Edition. New York, NY: Computer Society Press of the IEEE. Gehani, N., and McGettrick, A. 1986. Software Specification Techniques. Reading, MA: Addison-Wesley. Gilb, T. 1988. Principles of Software Engineering Management. Reading, MA: Addi- son-Wesley. Glass, R. 1982. Modern Programming Practices: A Report from Industry. Englewood Cliffs, NJ: Prentice Hall. Glass, R. 1983. Real-Time Software. Englewood Cliffs, NJ: Prentice Hall. Glass, R. 1991. Software Conflict. Englewood Cliffs, NJ: Yourdon Press. Goldberg, Α., and Rubin, K. 1992. Tutorial on Object-Oriented Project Management. Vancouver, Canada: OOPSLA'92. Guengerich, S. 1992. Downsizing Information Systems. Carmel, IN: Sams. Guindon, R., Krasner, H., and Curtis, B. 1987. Breakdowns and Processes During the Early Activities of Software Design by Professionals. Empirical Studies of Programmers, Second Workshop. Norwood, NJ: Ablex Publishing Company. Guttman, M., and Matthews, J. November/December 1992. Managing a Large Project. Object Magazine, vol. 2(4). Hansen, P. 1977. The Architecture of Concurrent Programs. Englewood Cliffs, NJ: Prentice Hall. Hantos, P. 2005. Inherent Risks in Object-Oriented Development. U.S. Air Force Software Technology Support Center (STSC): CrossTalk, The Journal of Defense Software Engineering.
Библиография 695 Henderson-Sellers, В. 1996. Object-Oriented Metrics: Measures of Complexity. Upper Saddle River, NJ: Prentice Hall. Henderson-Sellers, В., and Edwards, J. September 1990. The Object-Oriented Systems Lifecycle. Communications of the ACM, vol. 33(9). Hoare, С April 1984. Programming: Sorcery or Science? IEEE Software, vol. 1(2). Holt, R., Lazowska, E., Graham, G., and Scott, M. 1978. Structured Concurrent Programming. Reading, MA: Addison-Wesley. Humphrey, W. 1988. Characterizing the Software Development Process: A Maturity Framework. IEEE Software, vol. 5(2). Humphrey, W. 1988. 1989. Managing the Software Process. Reading, MA: Addison- Wesley. Hunt, J. May 2002. Blackboard Architectures. JayDee Technology Ltd 27. www.agent.ai/doc/upload/2004 02/hunt02_l.pdf. IEEE-Std-1220-2005. 2005. IEEE Standard for Application and Management of the Systems Engineering Process. New York, NY: IEEE. IEEE-Std-12207.0-1996. 1996. Standard for Information Technology-Software Life Cycle Processes. New York, NY: IEEE. IEEE-Std-12207.1-1997. 1997a. Standard for Information Technology-Software Life Cycle Processes—Life Cycle Data. New York, NY: IEEE. IEEE-Std-12207.2-1997. 1997b. Standard for Information Technology-Software Life Cycle Processes—Implementation Considerations. New York, NY: IEEE. Jackson, M. 1975. Principles of Program Design. Orlando, FL: Academic Press. Jackson, M. 1983. System Development. Englewood Cliffs, NJ: Prentice Hall. Jensen, R., and Tonies, C. 1979. Software Engineering. Englewood Cliffs, NJ: Prentice Hall. Jones, C. September 1984. Reusability in Programming: A Survey of the State of the Art. IEEE Transactions on Software Engineering, vol. SE-10(5). Jones, С September 1992. Risky Business: The Most Common Software Risks. American Programmer, vol. 5(7). Kan, S. H. 2002. Metrics and Models in Software Quality Engineering. Second Edition. Boston, MA: Addison-Wesley. Karam, G., and Casselman, R. February 1993. A Cataloging Framework for Software Development Methods. IEEE Computer. Kemerer, C, and Darcy, D. November/December 2005. OO Metrics in Practice. IEEE Software, vol. 22(6), p. 17.
696 Библиография Kishida, К., Teramoto, Μ., Torri, Κ., and Urano, Y. September 1988. Quality Assurance Technology in Japan. IEEE Software, vol. 4(5). Lammers, S. 1986. Programmers at Work. Redmond, WA: Microsoft Press. Laranjeira, L. May 1990. Software Size Estimation of Object-Oriented Systems. IEEE Transactions on Software Engineering, vol. 16(5). Ledgard, H. Summer 1985. Programmers: The Amateur vs. the Professional. Abacus, vol. 2(4). Lejter, M., Myers, S., and Reiss, S. December 1992. Support for Maintaining Object- Oriented Programs. IEEE Transactions on Software Engineering vol. 18(12). Linger, R., and Mills, H. 1977. On the Development of Large Reliable Programs. In: Current Trends in Programming Methodology: Software Specification and Design, vol. 1, ed. R. Yeh. Englewood Cliffs, NJ: Prentice Hall. Linger, R., Mills, H., and Witt, B. 1979. Structured Programming: Theory and Practice. Reading, MA: Addison-Wesley. Liskov, В., and Guttag, J. 1986. Abstraction and Specification in Program Development. Cambridge, MA: The MIT Press. Lorenz, M., and Kidd, J. 1994. Object-Oriented Software Metrics. Englewood Cliffs, NJ: Prentice Hall. Lorin, H. 1972. Parallelism in Hardware and Software. Englewood Cliffs, NJ: Prentice Hall. Luqi. August 1990. A Graph Model for Software Evolution. IEEE Transactions on Software Engineering, vol. 16(8). Luqi. May 1990. Software Evolution Through Rapid Prototyping. IEEE Computer, vol. 22(5). Martin, J., and McClure, С 1988. Structured Techniques: The Basis for CASE. Englewood Cliffs, NJ: Prentice Hall. Matsubara, T. July/August 1990. Bringing Up Software Designers. American Programmer, vol. 3(7-8). McCabe, Т., and Butler, C. December 1989. Design Complexity Measurement and Testing. Communications of the ACM, vol. 32(12). Mellichamp, D. 1983. Real-flme Computing. New York, NY: Van Nostrand Reinhold. Meyer, B. 1995. Object Success: A Manager's Guide to Object-Oriented Technology and Its Impact on the Corporation. Upper Saddle River, NJ: Prentice Hall. Mills, H. November 1986. Structured Programming: Retrospect and Prospect. IEEE Software, vol. 3(6).
Библиография 697 Mills, J. July 1985. A Pragmatic View of the System Architect. Communications of the ACM, vol. 28(7). Mimno, P. April 1993. Cilent-Server Computing. American Programmer. Mullin, M. 1990. Rapid Prototyping for Object-Oriented Systems. Reading, MA: Addison-Wesley. Munck, R. 1985. Toward Large Software Systems That Work. Proceedings of the AIAA/ACM/NASA/IEEE Computers in Aerospace V Conference. Menlo Park, CA: AIAA. Myers, G. 1978. Composite/Structured Design. New York, NY: Van Nostrand Rein- hold. Newport, J. April 28, 1986. A Growing Gap in Software. Fortune. Ng, P., and Yeh, R. 1990. Modern Software Engineering. New York, NY: Van Nostrand Reinhold. Office of the Under Secretary of Defense for Acquisition. September 1987. Report of the Defense Science Board Task Force on Military Software. Washington, DC. The Official Handbook of Mascot, Version 3.1. June 1987. London, England: Crown Copyright. Oman, P., and Lewis, T. 1990. Milestones in Software Evolution. Los Alamitos, CA: Computer Society Press of the IEEE. Orr, K. 1971. Structured Systems Development. New York, NY: Yourdon Press. Page- Jones, M. 1988. The Practical Guide to Structured Systems Design. Englewood Cliffs, NJ: Yourdon Press. Parnas, D. December 1985. Software Aspects of Strategic Defense Systems. Communications of the ACM, vol. 28(12). Parnas, D. July 1985a. Why Conventional Software Development Does Not Produce Reliable Programs. Software Aspects of Strategic Defense Systems. Report DCS- 47-IR. Victoria, Canada: University of Victoria. Parnas, D. July 1985b. Why Software Is Unreliable. Software Aspects of Strategic Defense Systems. Report DCS-47-IR. Victoria, Canada: University of Victoria. Parnas, D., and Clements, P. 1986. A Rational Design Process: How and Why to Fake It. IEEE Transactions on Software Engineering, vol. SE-12(2). Peters, L. 1981. Software Design. New York, NY: Yourdon Press. Pressman, R. 1988. Making Software Happen. Englewood Cliffs, NJ: Prentice Hall. Parnas, D. 1992. Software Engineering: A Practitioner's Approach. Third Edition. New York, NY: McGraw-Hill. Rakos, J. 1990. Software Project Management for Small to Medium Sized Projects. Englewood Cliffs, NJ: Prentice Hall.
698 Библиография Ramamoorthy, С, Garg, V., and Prakask, A. July 1986. Programming in the Large. IEEE Transactions on Software Engineering, vol. SE-12(7). Rechtin, E. October 1992. The Art of Systems Architecting. IEEE Spectrum vol. 29(10). Rettig, M. October 1990. Software Teams. Communications of the ACM, vol. 33(10). Ross, D., Goodenough, J., and Irvine, С 1980. Software Engineering: Process, Principles, and Goals. Tutorial on Software Design Techniques, Third Edition, ed. P. Freeman and A. Wasserman. New York, NY: Computer Society Press of the IEEE. Rubinstein, R., and Hersh, H. 1984. The Human Factor. Burlington, MA: Digital Press. Schulmeyer, G., and McManus, J. 1992. Handbook of Software Quality Assurance. Second Edition. New York, NY: Van Nostrand Reinhold. Shaw, M. November 1990. Prospects for an Engineering Discipline of Software. IEEE Software, vol. 7(6). Smith, M., and Robson, D. June 1992. A Framework for Testing Object-Oriented Programs. Journal of Object-Oriented Programming, vol. 5(3). Software Process Workshop. May 1988. SIGSOFT Software Engineering Notes vol. 14(4). Sommerville, I. 1989. Software Engineering. Third Edition. Wokingham, England: Addison-Wesley. Song, X., and Osterweil, L. 1993. Executing an Iterative Design Process. Irvine, CA: University of California. Spector, Α., and GifFord, D. April 1986. Computer Science Perspective of Bridge Design. Communications of the ACM, vol. 29(4). Stevens, W., Myers, G., and Constantine, L. 1979. Structured Design. In: Classics in Software Engineering, ed. E. Yourdon. New York, NY: Yourdon Press. Symons, С 1988. Function Point Analysis: Difficulties and Improvements. IEEE Transactions on Software Engineering, vol. 14(1). Taylor, D. 1990. Object-Oriented Technology: A Manager's Guide. Alameda, CA: Servio Corporation. The Software Trap: Automate—Or Else. May 9, 1988. Business Week. Thomsett, R. July/August 1990. Effective Project Teams. American Programmer vol. 3(7-8). Thomsett, R. June 1991. Managing Superlarge Projects: A Contingency Approach. American Programmer, vol. 4(6).
Библиография 699 U.S. Department of Defense. July 30, 1982. Report of the DoD Joint Service Task Force on Software Problems. Washington, DC. van Genuchten, M. June 1991. Why Is Software Late? An Empirical Study of Reasons for Delay in Software Development. IEEE Transactions on Software Engineering, vol. 17(6). Vick, C, and Ramamoorthy, С 1984. Software Engineering. New York, NY: Van Nostrand Reinhold. Vonk, R. 1990. Prototyping. Englewood Cliffs, NJ: Prentice Hall. Walsh, J. 1992. Preliminary Defect Data from the Iterative Development of a Large C++ Program. Vancouver, Canada: OOPSLA'92. Walsh, J. January 1993. Software Quality in an Iterative Object-Oriented Development Paradigm. Santa Clara, CA: Rational. Ward, M. 1990. Software That Works. San Diego, CA: Academic Press. Ward, P., and Mellor, S. 1985. Structured Development for Real-Time Systems: Introduction and Tools. Englewood Cliffs, NJ: Yourdon Press. Wegner, P. 1980. Research Directions in Software Technology. Cambridge, MA: The MIT Press. Wegner, P. July 1984. Capital-intensive Software Technology. IEEE Software, vol. 1(3). Weinberg, G. 1988. Understanding the Professional Programmer. New York, NY: Dorset House Publishing. Weinberg, G., and Freedman, D. 1990. Handbook of Walkthroughs, Inspections, and Technical Reviews. New York, NY: Dorset House. Whitten, N. 1990. Managing Software Development Projects. New York, NY: John Wiley and Sons. Wilde, N., and Huitt, R. December 1992. Maintenance Support for Object-Oriented Programs. IEEE Transactions on Software Engineering, vol. 18(12). Wilde, N., Matthews, P., and Huitt, R. January 1993. Maintaining Object-Oriented Software. IEEE Software, vol. 10(1). Wirth, N. 1986. Algorithms and Data Structures. Englewood Cliffs, NJ: Prentice Hall. Workshop on Software Configuration Management. November 1989. SIGSOFT Software Engineering Notes, vol. 17(7). Yamaura, T. January 1992. Standing Naked in the Snow. American Programmer, vol. 5(1). Yeh, R., ed. 1977. Current Trends in Programming Methodology: Software Specification and Design. Englewood Cliffs, NJ: Prentice Hall.
700 Библиография Yourdon, E. 1975. Techniques of Program Structure and Design. Englewood Cliffs, NJ: Prentice Hall. Yourdon, E., ed. 1979. Classics in Software Engineering. New York, NY: Yourdon Press. Yourdon, E. 1989a. Modern Structured Analysis. Englewood Cliffs, NJ: Prentice Hall. Yourdon, E. 1989b. Structured Walkthroughs. Englewood Cliffs, NJ: Prentice Hall. Yourdon, E. August 1989c. The Year of the Object. Computer Language, vol. 6(8). Yourdon, E. Summer 1989d. Object-Oriented Observations. American Programmer vol. 2(7-8). Yourdon, E., and Constantine, L. 1979. Structured Design. Englewood Cliffs, NJ: Prentice Hall. Zahniseer, R. July/August 1990. Building Software in Groups. American Programmer, vol. 3(7-8). Zave, P. February 1984. The Operational versus the Conventional Approach to Software Development. Communications of the ACM, vol. 27(2). Zelkowitz, M. June 1978. Perspectives on Software Engineering. ACM Computing Surveys, vol. 10(2). И. Специальные ссылки Alexander, С. 1979. The Timeless Way of Building. New York, NY: Oxford University Press. DeGrace, P., and Stahl, L. 1990. Wicked Problems, Righteous Solutions. Englewood Cliffs, NJ: Yourdon Press. Fukuyama, F. 1992. The End of History and the Last Man. New York, NY: The Free Press. Gall, J. 1986. Systemantics: How Systems Really Work and How They Fail. Second Edition. Ann Arbor, MI: The General Systemantics Press. Gleick, J. 1987. Chaos. New York, NY: Penguin Books. Heckbert, P. 1988. Ray Tracing Jell-0 Brand Gelatin. Communications of the ACM, vol. 31(2). Heinlein, R. 1966. The Moon Is a Harsh Mistress. New York, NY: The Berkeley Publishing Group. Hofstadter, D. 1979. Сгцае1, Escher, Bach: An Eternal Golden Braid. New York, NY: Vintage Books. International Council on Systems Engineering (INCOSE). 2006. INCOSE Systems Engineering Handbook. Version 3. INCOSE-TP-2003-002-03.
Библиография 701 Inside Macintosh, vol. 1-5. 1988. Reading, MA: Addison-Wesley. Kawasaki, G. 1990. The Macintosh Way. Glenview, IL: Scott, Foresman and Company. Lakoff, G., and Johnson, M. 1980. Metaphors We Live By. Chicago, IL: The University of Chicago Press. Lammers, S. 1986. Programmers at Work. Bellevue, WA: Microsoft Press. Meyer, C, and Matyas, S. M. 1982. Cryptography. New York, NY: John Wiley and Sons. Parker, T. 1983. Rules of Thumb. Boston, MA: Houghton Mifflin Company. Peter, L. 1986. The Peter Pyramid. New York, NY: William Morrow. Petroski, H. 1985. To Engineer Is Human. New York, NY: St. Martin's Press. Rand, Ayn. 1979. Introduction to Objectivist Epistemology. New York, NY: New American Library. Reti, L. 1988. The Unknown Leonard. New York, NY: Abradale Press. Sears, R, Zemansky, M., and Young., H. 1987. University Physics. Seventh Edition. Reading, MA: Addison-Wesley. U.S. Department of Commerce/National Institute of Standards and Technology. October 25, 1999. Data Encryption Standard (DES), Federal Information Processing Standards Publication 46-3. vonOech, R. 1990. A Whack on the Side of the Head. New York, NY: Warner Books. Wagner, J. 1986. The Search for Signs of Intelligent Life in the Universe. New York, NY: Harper and Row. Whitehead, A. 1958. An Introduction to Mathematics. New York, NY: Oxford University Press. К. Теория Aho, Α., Hopcroft, J., and Ullman, J. 1974. The Design and Analysis of Computer Programs. Reading, MA: Addison-Wesley. Almarode, J. October 1989. Rule-Based Delegation for Prototypes. SIGPLAN Notices, vol. 24(10). Appelbe, W., and Ravn, A. April 1984. Encapsulation Constructs in Systems Programming Languages. ACM Transactions on Programming Languages and Systems, vol. 6(2). Averill, E. April 1982. Theory of Design and Its Relationship to Capacity Measurement. Proceedings of the Fourth Annual International Conference on Computer Capacity Management. San Francisco, CA: Association of Computing Machinery.
702 Библиография Ватт, Α., and Feigenbaum, E. 1981. The Handbook of Artificial Intelligence. Los Altos, CA: William Kaufmann. Bastani, R, and Iyengar, S. March 1987. The Effect of Data Structures on the Logical Complexity of Programs. Communications of the ACM, vol. 30(3). Bastani, R, Hilal, W., and Sitharama, S. October 1987. Efficient Abstract Data Type Components for Distributed and Parallel Systems. IEEE Computer vol. 20(10). Belkhouche, В., and Urban, J. May 1986. Direct Implementation of Abstract Data Types from Abstract Specifications. IEEE Transactions on Software Engineering, vol. SE-12(5). Bensley, E., Brando, Т., and Prelle, M. September 1988. An Execution Model for Distributed Object-Oriented Computation. SIGPLAN Notices, vol. 23(11). Berztiss, A. 1980. Data Abstraction, Controlled Iteration, and Communicating Processes. Communications of the ACM. Bishop, J. 1986. Data Abstraction in Programming Languages. Wokingham, England: Addison-Wesley. Boehm, H., Demers, Α., and Donahue, J. October 1980. An Informal Description of Russell Technical Report TR 80-430. Ithaca, NY: Cornell University. Borning, Α., Duisberg, R., Freeman-Benson, В., Kramer, Α., and Woolf, M. October 1987. Constraint Hierarchies. SIGPLAN Notices, vol. 22(12). Boute, R. January 1988. Systems Semantics: Principles, Applications, and Implementation. ACM Transactions on Programming Languages and Systems, vol. 10(1). Brachman, R. October 1983. What Is-a Is and Isn't: An Analysis of Taxonomic Links in Semantic Networks. IEEE Computer, vol. 16(10). Brachman, R., and Levesque, H., eds. 1985. Readings in Knowledge Representation. Los Altos, CA: Morgan Kaufmann. Brooks, R. April 1987. Intelligence without Representation. Cambridge, MA: MIT Artificial Intelligence Laboratory. Bruce, K., and Wegner, P. October 1986. An Algebraic Model of Subtypes in Object- Oriented Languages. SIGPLAN Notices, vol. 21(10). Card, S., Moran, Т., and Newell, A. 1983. The Psychology of Human-Computer Interaction. Hillsdale, NJ: Lawrence Erlbaum Associates. Cardelli, L., and Wegner, P. December 1985. On Understanding Types, Data Abstraction, and Polymorphism. ACM Computing Surveys, vol. 17(4). Claybrook, В., and Wyckof, M. 1980. Module: An Encapsulation Mechanism for Specifying and Implementing Abstract Data Types. Communications of the ACM.
Библиография 703 Cline, Α., and Rich, E. December 1983. Building and Evaluating Abstract Data Types. Report TR-83-26. Austin, TX: University of Texas, Department of Computer Sciences. Cohen, A. January 1984. Data Abstraction, Data Encapsulation, and Object-Oriented Programming. SIGPLAN Notices, vol. 19(1). Cohen, N. November/December 1985. Tasks as Abstraction Mechanisms. Ada Letters, vol. 5(3-6). Cohen, R, and Loiselle, С August 1988. Beyond ISA: Structures for Plausible Inference in Semantic Nets. Proceedings of the Seventh National Conference on Artificial Intelligence. Saint Paul, MN: American Association for Artificial Intelligence. Collins, W. 1992. Data Structures: An Object-Oriented Approach. Reading, MA: Addison-Wesley. Cook, W., and Palsberg, J. October 1989. A Denotational Semantics of Inheritance and Its Correctness. SIGPLAN Notices, vol. 24(10). Courtois, P., Heymans, R, and Parnas, D. October 1971. Concurrent Control with "Readers" and "Writers." Communications of the ACM, vol. 14(10). Danforth, S., and Tomlinson, С March 1988. Type Theories and Object-Oriented Programming. A CM Computing Surveys, vol. 20(1). Demers, Α., Donahue, J., and Skinner, G. Data Types as Values: Polymorphism, Type-Checking, Encapsulation. Proceedings of the Fifth Annual ACM Symposium on Principles of Programming Languages. New York, NY: Association of Computing Machinery. Dennis, J., and Van Horn, E. March 1966. Programming Semantics for Multipro- grammed Computations. Communications of the ACM, vol. 9(3). Donahue, J., and Demers, A. July 1985. Data Types Are Values. ACM Transactions on Programming Languages and Systems, vol. 7(3). Eckart, J. April 1987. Iteration and Abstract Data Types. SIGPLANNotices, vol. 22(4). Embley, D., and Woodfield, S. 1988. Assessing the Quality of Abstract Data Types Written in Ada. Proceedings of the 10th International Conference on Software Engineering. New York, NY: Computer Society Press of the IEEE. Ferber, J. October 1989. Computational Reflection in Class-Based Object-Oriented Languages. SIGPLAN Notices, vol. 24(10). Fisher, J., and Gipson, D. November 1992. In: Search of Elegance. Computer Language, vol. 9(11). Gannon, J., Hamlet, R., and Mills, H. July 1987. Theory of Modules. IEEE Transactions on Software Engineering, vol. SE-13(7).
704 Библиография Gannon, J., McMullin, P., and Hamlet, R. July 1981. Data Abstraction Implementation, Specification, and Testing. ACM Transactions on Programming Languages and Systems, vol. 3(3). Gardner, M. May/June 1984. When to Use Private Types. Ada Letters, vol. 3(6). Goguen, J., Thatcher, J., and Wagner, E. 1977. An Initial Algebra Approach to the Specification, Correctness, and Implementation of Abstract Data Types. In: Current Trends in Programming Methodology: Data Structuring, vol. 4, ed. R. Yeh. Englewood Cliffs, NJ: Prentice Hall. Goldberg, D. 1989. Genetic Algorithms. Reading, MA: Addison-Wesley. Graube, N. October 1989. Metaclass Compatibility. SIGPLAN Notices, vol. 24(10). Gries, D., and Prins, J. July 1985. A New Notion of Encapsulation. SIGPLANNotices, vol. 20(7). Grogono, P., and Bennett, A. November 1989. Polymorphism and Type Checking in Object-Oriented Languages. SIGPLAN Notices, vol. 24(11). Guttag, J. 1980. Abstract Data Types and the Development of Data Structures. In: Programming Language Design, ed. A. Wasserman. New York, NY: Computer Society Press of the IEEE. Hammons, C, and Dobbs, P. May/June 1985. Coupling, Cohesion, and Package Unity in Ada. Ada Letters, vol. 4(6). Harel, D., and Kahana, C. October 1992. On Statecharts with Overlapping. ACM Transactions on Software Engineering and Methodology, vol. 1(4). Harel, D., Lachover, H., Naamad, Α., Pnueli, Α., Politi, M., Sherman, R., Shtull- Trauring, S., and Trakhtenbrot, M. April 1990. STATEMATE: A Working Environment for the Development of Complex Reactive Systems. IEEE Transactions on Software Engineering, vol. 16(4). Harrison, G., and Liu, D. July/August 1986. Generic Implementations Via Analogies in the Ada Programming Language. Ada Letters, vol. 6(4). Hayes, P. 1981. The Logic of Frames. In: Readings in Artificial Intelligence, ed. B. Webber and N. Nilsson. Palo Alto, CA: Tioga. Hayes-Roth, F. July 1985. A Blackboard Architecture for Control. Artificial Intelligence, vol. 26(3). Hayes-Roth, F., Waterman, D., and Lenat, D. 1983. Building Expert Systems. Reading, MA: Addison-Wesley. Haynes, C, and Friedman, D. October 1987. Embedding Continuations in Procedural Objects. ACM Transactions on Programming Languages and Systems, vol. 9(4). Henderson, P. February 1986. Functional Programming, Formal Specification, and Rapid Prototyping. IEEE Transactions on Software Engineering vol. SE-12(2).
Библиография 705 Herlihy, M., and Liskov, B. October 1982. A Value Transmission Method for Abstract Data Types. ACM Transactions on Programming Languages and Systems, vol. 4(4). Hesselink, W. January 1988. A Mathematical Approach to Nondeterminism in Data ypes. ACM Transactions on Programming Languages and Systems, vol. 10(1). Hibbard, P., Hisgen, Α., Rosenbers, J., Shaw, M., and Sherman, M. 1981. Studies in Ada Style. New York, NY: Springer-Verlag. Hilfinger, P. 1982. Abstraction Mechanisms and Language Design. Cambridge, MA: The MIT Press. Hoare, С October 1974. Monitors: An Operating System Structuring Concept. Communications of the ACM, vol. 17(10). Hoare, С 1985. Communicating Sequential Processes. Englewood Cliffs, NJ: Prentice Hall. Hogg, J., and Weiser, S. October 1987. OTM: Applying Objects to Tasks. SIGPLAN Notices, vol. 22(12). Jajodia, S., and Ng. P. 1983. On Representation of Relational Structures by Entity- Relationship Diagrams. In: Entity-Relationship Approach to Software Engineering, ed. С Davis et al. Amsterdam, The Netherlands: Elsevier Science. Johnson, С 1986. Some Design Constraints Required for the Assembly of Software Components: The Incorporation of Atomic Abstract Types into Generically Structured Abstract Types. Proceedings of the First International Conference on Ada Programming Language Applications for the NASA Space Station. Houston, TX: NASA Lyndon B. Johnson Space Center. Kernighan, В., and Plauger, P. 1981. Software Tools in Pascal. Reading, MA: Addison- Wesley. Knight, B. 1983. A Mathematical Basis for Entity Analysis. In: Entity-Relationship Approach to Software Engineering, ed. С Davis et al. Amsterdam, The Netherlands: Elsevier Science. Knuth, D. 1973. The Art of Computer Programming, vol. 1-3. Reading, MA: Addison- Wesley. Kosko, B. 1992. Neural Networks and Fuzzy Systems. Englewood Cliffs, NJ: Prentice Hall. LaLonde, W., and Pugh, J. August 1985. Specialization, Generalization, and Inheritance: Teaching Objectives Beyond Data Structures and Data Types. SIGPLAN Notices, vol. 20(8). Leeson, J., and Spear, M. March 1987. Type-Independent Modules: The Preferred Approach to Generic ADTs in Modula-2. SIGPLAN Notices, vol. 22(3).
706 Библиография Lenzerini, M., and Santucci, G. 1983. Cardinality Constraints in the Entity-Relationship Model. In: Entity-Relationship Approach to Software Engineering, ed. C. Davis et al. Amsterdam, The Netherlands: Elsevier Science. Levesque, H. July 1984. Foundations of a Functional Approach to Knowledge Representation. Artificial Intelligence, vol. 23(2). Lindgreen, P. 1983. Entity Sets and Their Description. In: Entity-Relationship Approach to Software Engineering, ed. С Davis et al. Amsterdam, The Netherlands: Elsevier Science. Lins, C. 1989. A First Look at Literate Programming. Structured Programming. Liskov, B. 1980. Programming with Abstract Data Types. In: Programming Language Design, ed. A. Wasserman. New York, NY: Computer Society Press of the IEEE. Liskov, B. May 1988. Data Abstraction and Hierarchy. SIGPLAN Notices, vol. 23(5). Liskov, В., and Scheifler, R. July 1983. Guardians and Actions: Linguistic Support for Robust, Distributed Programs. ACM Transactions on Programming Languages and Systems, vol. 5(3). Liskov, В., and Zilles, S. 1977. An Introduction to Formal Specifications of Data Abstractions. In: Current Trends in Programming Methodology: Software Specification and Design, vol. 1, ed. R. Yeh. Englewood Cliffs, NJ: Prentice Hall. Lowry, M., and McCartney, R.. 1991. Automating Software Design. Cambridge, MA: The MIT Press. Lucco, S. October 1987. Parallel Programming in a Virtual Object Space. SIGPLAN Notices, vol. 22(12). Maes, P. October 1987. Concepts and Experiments in Computational Reflection. SIGPLAN Notices, vol. 22(12). Mark, L. 1983. What Is the Binary Relationship Approach? In: Entity-Relationship Approach to Software Engineering, ed. С Davis et al. Amsterdam, The Netherlands: Elsevier Science. Markowitz, V., and Raz, Y. 1983. A Modified Relational Algebra and Its Use in an Entity-Relationship Environment. In: Entity-Relationship Approach to Software Engineering, ed. С Davis et al. Amsterdam, The Netherlands: Elsevier Science. Matsuoka, S., and Kawai, S. September 1988. Using Tuple Space Communication in Distributed Object-Oriented Languages. SIGPLAN Notices, vol. 23(11). McAllester, D., and Zabih, F. November 1986. Boolean Classes. SIGPLAN Notices, vol. 21(11). McCullough, P. October 1987. Transparent Forwarding: First Steps. SIGPLAN Notices, vol. 22(12).
Библиография 707 Merlin, P., and Bochmann, G. January 1983. On the Construction of Submodule Specifications and Communication Protocols. ACM Transactions on Programming Languages and Systems, vol. 5(1) Meyer, B. 1987. Programming as Contracting. Report TR-EI-12/CO. Goleta, CA: Interactive Software Engineering. Meyer, B. October 1992. Applying "Design by Contract." IEEE Computer vol. 25(10). Minoura, Т., and Iyengar, S. January 1989. Data and Time Abstraction Techniques for Multilevel Concurrent Systems. IEEE Transactions on Software Engineering, vol. 15(1). Murata, T. 1984. Modeling and Analysis of Concurrent Systems. In: Software En- gineering, ed. С Vick and С Ramamoorthy. New York, NY: Van Nostrand Reinhold. Mylopoulos, J., and Levesque, H. 1984. An Overview of Knowledge Representation. In: On Conceptual Modeling: Perspectives from Artificial Intelligence, Databases, and Programming Languages, ed. M. Brodie, J. Mylopoulos, and J. Schmidt. New York, NY: Springer-Verlag. Nakano, R. 1983. Integrity Checking in a Logic-Oriented ER Model. In: Entity- Relationship Approach to Software Engineering, ed. C. Davis et al. Amsterdam, The Netherlands: Elsevier Science. Newton, M., and Watkins, J. November/December 1988. The Combination of Logic and Objects for Knowledge Representation. Journal of Object-Oriented Programming, vol. 1(4). Nii, P. Summer 1986. Blackboard Systems: The Blackboard Model of Problem Solving and the Evolution of Blackboard Architectures. AI Magazine, vol. 7(2). Ohori, Α., and Buneman, P. October 1989. Static Type Inference for Parametric Classes. SIGPLAN Notices, vol. 24(10). Pagan, F. 1981. Formal Specification of Programming Languages. Englewood Cliffs, NJ: Prentice Hall. Parent, C, and Spaccapieta, S. July 1985. An Algebra for a General Entity-Relationship Model. IEEE Transactions on Software Engineering vol. SE-11(7). Parnas, D. 1977. The Influence of Software Structure on Reliability. In: Current Trends in Programming Methodology: Software Specification and Design vol. 1, ed. R. Yeh. Englewood Cliffs, NJ: Prentice Hall. Parnas, D. 1980. Designing Software for Ease of Extension and Contraction. In: Tutorial on Software Design Techniques, Third Edition, ed. P. Freeman and A. Wasserman. New York, NY: Computer Society Press of the IEEE.
708 Библиография Parnas, D., Clements, P., and Weiss, D. 1983. Enhancing Reusability with Information Hiding. Proceedings of the Workshop on Reusability in Programming, Stratford, CT: ITT Programming. Pattee, H. 1973. Hierarchy Theory. New York, NY: George Braziller. Peckham, J., and Maryanski, F. September 1988. Semantic Data Models. ACM Computing Surveys, vol. 20(3). Pedersen, С October 1989. Extending Ordinary Inheritance Schemes to Include Generalization. SIGPLAN Notices, vol. 24(10). Peterson, J. September 1977. Petri Nets. Computing Surveys, vol. 9(3). Reed, D. September 1978. Naming and Synchronization in a Decentralized Computer System. Cambridge, MA: The MIT Press. Rich, C, and Wills, L. January 1990. Recognizing a Program's Design: A Graph- Parsing Approach. IEEE Software, vol. 7(1). Robinson, L., and Levitt, K. 1977. Proof Techniques for Hierarchically Structured Programs. In: Current Trends in Programming Methodology: Program Validation, vol. 2, ed. R. Yeh. Englewood Cliffs, NJ: Prentice Hall. Ross, D. July/August 1986. Classifying Ada Packages. Ada Letters, vol. 6(4). Ruane, L. January 1984. Abstract Data Types in Assembly Language Programming. SIGPLAN Notices, vol. 19(1). Rumbaugh, J. September 1988. Controlling Propagation of Operations Using Attributes on Relations. SIGPLAN Notices, vol. 23(11). Sedgewick, R. 1983. Algorithms. Reading, MA: Addison-Wesley. Shankar, K. 1984. Data Design: Types, Structures, and Abstractions. In: Software Engineering, ed. С Vick and C. Ramamoorthy. New York, NY: Van Nostrand Reinhold. Shaw, M. 1984. The Impact of Modeling and Abstraction Concerns on Modern Programming Languages. On Conceptual Modeling: Perspectives from Artificial Intelligence, Databases, and Programming Languages, ed. M. Brodie, J. Mylopoulos, and J. Schmidt. New York, NY: Springer-Verlag. Brodie, J. October 1984. Abstraction Techniques in Modern Programming Languages. IEEE Software, vol. 1(4). Brodie, J. May 1989. Larger Scale Systems Require Higher-Level Abstractions. SIG- SOFT Engineering Notes, vol. 14(3). Shaw, M., Feldman, G., Fitzgerald, R., Hilfinger, P., Kimura, I., London, R., Rosenberg, J., and Wulf, W. 1981. Validating the Utility of Abstraction Techniques. In: ALPHARD: Form and Content, ed. M. Shaw. New York, NY: Springer-Verlag.
Библиография 709 Shaw, M., Wulf, W., and London, R. 1981. Abstraction and Verification in ALPHARD: Iteration and Generators. In: ALPHARD: Form and Content, ed. M. Shaw. New York, NY: Springer-Verlag. Sherman, M., Hisgen, Α., and Rosenberg, J. 1982. A Methodology for Programming Abstract Data Types in Ada. Proceedings of the AdaTEC Conference on Ada. New York, NY: Association of Computing Machinery. Siegel, J. April 1988. Twisty Little Passages. HOOPLA: Hooray for Object-Oriented Programming Languages, vol. 1(3). Everette, WA: Object Oriented Programming for Smalltalk Application Developers Association. Stefik, M., Bobrow, D., and Kahn, K. January 1986. Integrating Access-Oriented Programming into a Multiparadigm Environment. IEEE Software, vol. 3(1). Strom, R., and Yemini, S. January 1986. Typestate: A Programming Language Concept for Enhancing Software Reliability. IEEE Transactions on Software Engineering, vol. SE-12(1). Stubbs, D., and Webre, N. 1985. Data Structures with Abstract Data Types and Pascal Monterey, CA: Brooks/Cole. Swaine, M. June 1988. Programming Paradigms. Dr. Dobb s Journal of Software Tools no. 140. Tabourier, Υ 1983. Further Development of the Occurrences Structure Concept: The EROS Approach. In: Entity-Relationship Approach to Software Engineering, ed. С Davis et al. Amsterdam, The Netherlands: Elsevier Science. Tanenbaum, A. 1981. Computer NetworL·. Englewood Cliffs, NJ: Prentice Hall. Tenenbaum, Α., and Augenstein, M. 1981. Data Structures Using Pascal Englewood Cliffs, NJ: Prentice Hall. Throelli, L. October 1987. Modules and Type Checking in PL/LL. SIGPLAN Notices, vol. 22(12). Tomlinson, C, and Singh, V. October 1989. Inheritance and Synchronization with Enabled-sets. SIGPLAN Notices, vol. 24(10). Toy, W. 1984. Hardware/Software Tradeoffs. In: Software Engineering, ed. C. Vick and С Ramamoorthy. New York, NY: Van Nostrand Reinhold. Vegdahl, S. November 1986. Moving Structures between Smalltalk Images. SIGPLAN Notices, vol. 21(11). Walters, N. October 1992. Using Harel Statecharts to Model Object-Oriented Behavior. SIGSOFT Notices, vol. 17(4). Wasserman, A. 1980. Introduction to Data Types. In: Programming Language Design, ed. A. Wasserman. New York, NY: Computer Society Press of the IEEE.
710 Библиография Weber, H., and Ehrig, H. July 1986. Specification of Modular Systems. IEEE Transactions on Software Engineering, vol. SE-12(7). Wegner, P. June 6r 1981. The Ada Programming Language and Environment. Unpublished draft. Wegner, P. 1987a. On the Unification of Data and Program Abstraction in Ada. In: Object-Oriented Computing: Concepts, vol. 1, ed. G. Peterson. New York, NY: Computer Society Press of the IEEE. Wegner, P. 1987b. The Object-Oriented Classification Paradigm. In: Research Directions in Object-Oriented Programming, ed. B. Schriver and P. Wegner. Cambridge, MA: The MIT Press. Wegner, P., and Zdonik, S. August 1988. Inheritance as an Incremental Modification Mechanism or What Like Is and Isn't Like. Proceedings ofECOOP'88: European Conference on Object-Oriented Programming. New York, NY: Springer- Verlag. Weihl, W., and Liskov, B. April 1985. Implementation of Resilient, Atomic Data Types. ACM Transactions on Programming Languages and Systems, vol. 7(2) Weinberg, G. 1971. The Psychology of Computer Programming. New York, NY: Van Nostrand Reinhold. Weller, D., and York, B. May 1984. A Relational Representation of an Abstract Type System. IEEE Transactions on Software Engineering, vol. SE-10(3). White, J. July 1983. On the Multiple Implementation of Abstract Data Types within a Computation. IEEE Transactions on Software Engineering, vol. SE-9(4). Wirth, N. December 1974. On the Composition of Well-Structured Programs. Computing Surveys, vol. 6(4). Wirth, N. January 1983. Program Development by Stepwise Refinement. Communications of the ACM, vol. 26(1). Wirth, N. 1986. Algorithms and Data Structures. Second Edition. Englewood Cliffs, NJ: Prentice Hall. Wirth, N. April 1988. Type Extensions. ACM Transactions on Programming Languages and Systems, vol. 10(2). Wolf, Α., Clarke, L., and Wileden, J. April 1988. A Model of Visibility Control. IEEE Transactions on Software Engineering, vol. 14(4). Woods, W. October 1983. What's Important about Knowledge Representation? IEEE Computer, vol. 16(10). Zilles, S. 1984. Types, Algebras, and Modeling. In: On Conceptual Modeling: Perspectives from Artificial Intelligence, Databases, and Programming Languages, ed. M. Brodie, J. Mylopoulos, and J. Schmidt. New York, NY: Springer-Verlag. Zippel, R. June 1983. Capsules. SIGPLANNotices, vol. 18(6).
Библиография 711 Л. Инструменты и среды Andrews, Т., and Harris, С. 1987. Combining Language and Database Advances in an Object-Oriented Development Environment. Billerica, MA: Ontologic. Corradi, Α., and Leonardi, L. 1986. An Environment Based on Parallel Objects. Bologna, Italy: Universita di Bologna. Deutsch, P., and Taft, E. June 1980. Requirements for an Experimental Programming Environment. Report CSL-80-10. Palo Alto, CA: Xerox Palo Alto Research Center. Diederich, J., and Milton, J. October 1987. An Object-Oriented Design System Shell. SIGPLAN Notices, vol. 22(12). Durant, D., Carlson, G., and Yao, P. 1987. Programmer i Guide to Windows. Berkeley, CA: Sybex. Erman, L., Lark, J., and Hayes-Roth, F. December 1988. ABE: An Environment for Engineering Intelligent Systems. IEEE Transactions on Software Engineering, vol. 14(12). Ferrel, P., and Meyer, R. October 1989. Vamp: The Aldus Application Framework. SIGPLAN Notices, vol. 24(10). Fischer, H., and Martin, D. 1987. Integrating Ada Design Graphics into the Ada Software Development Process. Encino, CA: Mark V Business Systems. Goldberg, A. 1984a. Smalltalk-80: The Interactive Programming Environment. Reading, MA: Addison-Wesley. Goldberg, A. 1984b. The Influence of an Object-Oriented Language on the Programming Environment. In: Interactive Programming Environments, ed. B. Barstow. New York, NY: McGraw-Hill. Goldstein, I., and Bobrow, D. March \9%\. An Experimental Description-Based Programming Environment. Report CSL-81-3. Palo Alto, CA: Xerox Palo Alto Research Center. Gorlen, K. May 1986. Object-Oriented Program Support. Bethesda, MD: National Institute of Health. Hecht, Α., and Simmons, A. 1986. Integrating Automated Structured Analysis and Design with Ada Programming Support Environments. Proceedings of the First International Conference on Ada Programming Language Applications for the NASA Space Station. Houston, TX: NASA Lyndon B. Johnson Space Center. Hedin, G., and Magnusson B. August 1988. The Mjolner Environment: Direct Interaction with Abstractions. Proceedings ofECOOP'88: European Conference on Object-Oriented Programming. New York, NY: Springer-Verlag.
712 Библиография Hudson, S., and King, R. June 1988. The Cactic Project: Database Support for Software Environments. IEEE Transactions on Software Engineering, vol. 14(6). International Business Machines. April 1988. Operating System/2 Seminar Proceedings, IBM OS/2 Standard Edition Version 1.1, IBM Operating System/2 Update, Presentation Manager. Boca Raton, FL. Kant, E. 1987. Interactive Problem Solving with a Task Configuration and Control System. Ridgefield, CT: Schlumberger-Doll Research. Kleyn, M., and Gingrich, P. September 1988. GraphTrace—Understanding Object- Oriented Systems Using Concurrently Animated Views. SIGPLAN Notices, vol. 23(11). Laff, M., and Hailpern, B. July 1985. SW-2—An Object-Based Programming Environment. SIGPLAN Notices, vol. 20(7). MacLenna, B. July 1985. A Simple Software Environment Based on Objects and Relations. SIGPLAN Notices, vol. 20(7). Marques, J., and Guedes, P. October 1989. Extending the Operating System to Support an Object-Oriented Environment. SIGPLAN Notices, vol. 24(10). Minsky, N., and Rozenshtein, D. February 1988. A Software Development Environment for Law-Governed Systems. SIGPLAN Notices, vol. 24(2). Moreau, D., and Dominick, W. 1987. Object-Oriented Graphical Information Systems: Research Plan and Evaluation Metrics. Lafayette, LA: University of Southwestern Louisiana, Center for Advanced Computer Studies. Nakata, S., and Yamazak, G. 1983. ISMOS: A System Based on the E-R Model and Its Application to Database-Oriented Tool Generation. In: Entity-Relationship Approach to Software Engineering, ed. С Davis et al. Amsterdam, The Netherlands: Elsevier Science. Nye, A. 1989. Xlib Programming Manual for Version 11. Newton, MA: O'Reilly and Associates. O'Brien, P., Halbert, D., and Kilian, M. October 1987. The Trellis Programming Environment. SIGPLAN Notices, vol. 22(12). Open Look Graphical User Interface Functional Specification. 1990. Reading, MA: Addison-Wesley. OSF/Motif Style Guide, Version 1.0. 1989. Cambridge, MA: Open Software Foundation. Penedo, M., Ploedereder, E., and Thomas, I. February 1988. Object Management Issues for Software Engineering Environments. SIGPLAN Notices, vol. 24(2). Reenskaug, Т., and Skaar, A. October 1989. An Environment for Literate Smalltalk Programming. SIGPLAN Notices, vol. 24(10).
Библиография 713 Rosenplatt, W., Wileden, J., and Wolf, A. October 1989. OROS: Toward a Type Model for Software Development Environments. SIGPLAN Notices, vol. 24(10). Russo, V., and Campbell, R. October 1989. Virtual Memory and Backing Storage Management in Multiprocessor Operating Systems Using Object-Oriented Design Techniques. SIGPLAN Notices, vol. 24(10). Scheifler, R., and Gettys, J. 1986. The X Window System. ACM Transactions on Graphics, vol. 63. Schwan, K., and Matthews, J. July 1986. Graphical Views of Parallel Programs. Software Engineering Notes, vol. 11(3). Shear, D. December 8, 1988. CASE Shows Promise but Confusion Still Exists. EDN, vol. 33(25). Sun Microsystems. March 29, 1987. NeWS Technical Overview. Mountain View, CA. Tarumi, H., Agusa, K., and Ohno, Y. 1988. A Programming Environment Supporting Reuse of Object-Oriented Software. In: Proceedings of the 10th International Conference on Software Engineering. New York, NY: Computer Society Press of the IEEE. Taylor, R., Belz, F., Clarke, L., Osterweil, L., Selby, R., Wileden, J., Wolf, Α., and Young, M. February 1988. Foundations for the Arcadia Environment. SIGPLAN Notices, vol. 24(2). Tesler, L. August 1981. The Smalltalk Environment. Byte, vol. 6(8). Vines, D., and King, T. 1988. Gaia: An Object-Oriented Framework for an Ada Environment. Minneapolis, MN: Honeywell. Weinand, Α., Gamma, E., and Marty, R. 1989. Design and Implementation of ET++, a Seamless Object-Oriented Application Framework. Structured Programming, vol. 10(2). Wiorkowski, G., and Kull, D. 1988. DB2 Design and Development Guide. Reading, MA: Addison-Wesley. M. Унифицированный язык моделирования Bennett, S., Skelton, J., and Lunn, K. 2005. Schaum 's Outline ofUML. Second Edition. United Kingdom: McGraw-Hill. Blaha, M., and Rumbaugh, J. 2005. Object-Oriented Modeling and Design with UML. Second Edition. Upper Saddle River, NJ: Prentice Hall. Bock, C. 2003. UML 2 Activity and Action Models. Journal of Object Technology vol. 2(4), pp. 43-53. www. jot. fm/issues/issue_2003_07/column3.
714 Библиография Воск, С. 2003. UML 2 Activity and Action Models, Part 2: Actions. Journal of Object Technology, vol. 2(5), pp. 41-56. www.jot.fm/issues/issue_2003_09/column4. Воск, С 2003. UML 2 Activity and Action Models, Part 3: Control Nodes. Journal of Object Technology, vol. 2(6), pp. 7-23. www. jot. fm/issues/issue_2003__ll/columnl. Воск, С 2004. UML 2 Activity and Action Models, Part 4: Object Nodes. Journal of Object Technology, vol. 3(1), pp. 27-41. www.jot.fm/issues/issue_2004_01/column3. Воск, С 2004. UML 2 Activity and Action Models, Part 5: Partitions. Journal of Object Technology, vol. 3(7), pp. 37-56. www.jot.fm/issues/issue_2004_07/column4. Booch, G., Rumbaugh, J., and Jacobson, I. 2005. The Unified Modeling Language User Guide. Second Edition. Boston, MA: Addison-Wesley. Fowler, M. 2003. UML Distilled: A Brief Guide to the Standard Object Modeling Language. Third Edition. Boston, MA: Addison-Wesley. Maksimchuk, R., andNaiburg, E. 2005. UML for Mere Mortals. Boston, MA: Addison- Wesley. Naiburg, E., and Maksimchuk, R. 2001. UML for Database Design. Boston, MA: Addison-Wesley. Rumbaugh, J., Jacobson, I., and Booch, G. 2005. The Unified Modeling Language Reference Manual. Second Edition. Boston, MA: Addison-Wesley. Object Management Group. 2004. UML Superstructure Specification, v2.0. www. uml. org. H. Web-ориентированное моделирование Cavaness, С 2004. Programming Jakarta Struts. Second Edition. Indianapolis, IN: O'Reilly. Constantine, L. L., and Lockwood, L. A. D. 1999. Software for Use: A Practical Guide to the Models and Methods of Usage-Centered Design. Reading, MA: Addison-Wesley. Garrett, J. J. 2002. The Elements of User Experience. Boston, MA: New Riders Press. Geary, D., and Horstmann, C. 2004. Core JavaServer Faces. Upper Saddle River, NJ: Prentice Hall. Monson-Haefel, R. 2001. Enterprise JavaBeans. Third Edition. Indianapolis, In: O'Reilly.
предметный указатель А Абстрагирование, 75 Абстракция, 389 основная, 142; 167 Агент, 120 Агрегация, 94; 139 Анализ абстракций, 166 архитектурный, 315 компонентный, 315 объектно-ориентированный, 73; 160 поведения, 325 предметной области, 162 прецедентов использования, 163 структурный, 165 характеристик, 161 Аналитик, 346 Артефакт, 204 Архитектор проекта, 344 Ассоциация, 127; 226 рефлексивная, 227 В Видимость реализации, 231 Г Глоссарий, 376 Глубина дерева наследования, 354 д Действие, 218; 256 Действующее лицо, 208 Декомпозиция алгоритмическая, 49 объектно-ориентированная, 50 Диаграмма взаимодействий, 274 внутренней структуры, 202 коммуникации, 274 композитной структуры, 248 компонентов, 195 конечных автоматов, 252 обзора взаимодействий, 245 объектов, 271 пакетов, 186 последовательностей, 239 прецедентов использования, 208 развертывания, 203 Достаточность, 143 Доступ, 191 3 Зависимость, 140 И Иерархия, 389 Импорт, 191 Инвариант, 77 Индивидуальность объекта, 116 Инженер, ответственный за повторное использование, 346 Инкапсуляция, 81; 389 Инспектирование проекта, 342 Интеграция, 349 Интерфейс, 125
716 Предметный указатель К Качество программного продукта, 352 Квалификатор, 234 Класс, 123; 225 абстрактный, 132 ассоциаций, 238 дружественный, 126 связанный, 230 шаблонный, 230 Классическая категоризация, 155 Клиент, 76; 274 Количество выполненных контрактов, 354 классов в расчете на одного разработчика, 354 вспомогательных, 353 основных, 353 методов в классе, 354 основных итераций, 354 подсистем, 353 потомков, 354 сценариев, 353 человеко-часов, затраченных на класс, 353 Компонент, 350; 391 Контейнер, 123; 376 Контролер качества, 347 Контроллер, 120 Контроль версий, 348 типов, 95 динамический, 97 сильный, 97 слабый, 97 статический, 97 Конфликт детализации, 169 Концептуальная кластеризация, 156 Μ Макропроцесс, 290 Менеджер по интеграции, 347 проекта, 346 Метод, 52 CRC-карточек, 164 прозрачного ящика, 390 черного ящика, 419 Методология, 52 Механизм, 54 использования взаимодействий, 243 реализации, 142 сотрудничества, 250 Модель информационной доски, 457 контрактная, 76 объектная, 48 Модуль, 66 Модульность, 85; 389 Η Наследование, 129 множественное, 134 одиночное, 130 Недостаток связности среди методов, 354 О Объект защищенный, 145 управляющий, 107 Ограничение, 234 Операция элементарная, 144 Ответственный за документацию, 347 Отклик на класс, 354 Отношение extend, 213 include, 213 обобщения, 217 Π Пакетный доступ, 126 Параллелизм, 99 Перегрузка, 133 Передача сообщений, 113 Переход, 254 управляемый, 256 Персистентность, 100 Плотность ошибок, 352 Поведение объекта, 112
Предметный указатель 717 производное, 36 Повторное использование, 350 Подкласс, 131 Подсистема, 391 Показатель СВО, 354 CPD, 354 DIT, 354 KSLOC, 352 LCOM, 354 NCC, 354 NKC, 353 NKS, 353 NMI, 354 NOC, 354 NOS, 353 NSS, 353 PDC, 353 RFC, 354 WMC, 354 Полиморфизм, 132 Полнота, 143 Полюс ассоциации, 227 Последовательность рассуждений обратная, 458 прямая, 458 Постусловие, 77 Поток объектов, 223 Предусловие, 77; 458 Принцип минимальных обязательств, 75 наименьшего удивления, 75 Программист системный, 347 Продвижение класса, 169 Проектирование архитектурное, 315 композиционное, 52 компонентов, 316 объектно-ориентированное, 72 Ρ Разработчик компонентов, 345 Роль, 252 Связанность, 142 объектов, 354 Связность, 143 функциональная, 392 Связывание динамическое, 97 позднее, 97 раннее, 97 статическое, 97 Сегмент, 391 Сервер, 76; 120; 274 Синхронизация, 122 защищенная, 122 параллельная, 122 последовательная, 122 Система, 391 почти разложимая, 44 разложимая, 43 Системный администратор, 347 Сообщение, 241 асинхронное, 241 найденное, 241 потерянное, 241 синхронное, 241 Сопровождение ПО, 39 Состояние вложенное, 258 конечное, 253 начальное, 253 сложное, 258 Сохранение ПО, 39 Спецификация дополнительная, 376 прецедента использования, 419 Структурное разделение, 118 Суперкласс, 131 Τ Теория прототипов, 157 Тестирование, 349 компонентов, 350 модулей, 349 системы, 350 Точка включения, 213
718 Предметный указ расширения, 213 функциональная, 162 У Узел, 205 действия, 218 конечный действий, 218 потока, 219 объединения, 221 объекта, 218 принятия решения, 219 разветвления, 221 слияния, 219 управления, 218 Управление конфигурацией, 348 э Эволюция ПО, 39 Я Язык программирования объектный, 72
Научно-популярное издание Гряди Буч, Роберт А. Максимчук, Майкл У. Энгл, Бобби Дж. Янг, Джим Коналлен, Келли А. Хьюстон Объектно-ориентированный анализ и проектирование с примерами приложений 3-е издание Литературный редактор П.Н. Мачуга Верстка А.Н. Политик Художественный редактор ВТ. Павлютин Корректор Л.А. Гордиенко ООО "И.Д. ВИЛЬЯМС" 127055, г. Москва, ул. Лесная, д. 43, стр. 1 Подписано в печать 08.04.2008. Формат 70χ 100/16. Гарнитура Times. Печать офсетная. Усл. печ. л. 45,0. Уч.-изд. л. 35,8. Тираж 1500 экз. Заказ № 9125. Отпечатано по технологии CtP в ОАО "Печатный двор" им. А. М. Горького 197110, Санкт-Петербург, Чкаловский пр., 15.
ОБЪЕКТНО- ОРИЕНТИРОВАННЫЕ МЕТОДЫ. ПРИНЦИПЫ И ПРАКТИКА, 3-Е ИЗДАНИЕ Ян Грехем www.williamspublishing.com в продаже Новое издание этой весьма популярной книги было полностью переработано автором с целью отразить все те значительные изменения, которые произошли в объектно-ориентированной методологии с момента выхода предыдущего, второго издания (1991 г.). В частности, большое внимание здесь уделяется многоуровневому проектированию и компонентной технологии, языкам Java и UML. Книга включает обсуждение всех ключевых концепций методологии ООП, преимуществ и недостатков, свойственных объектно- ориентированному подходу, а также описание технологий и инструментов, доступных разработчику в настоящее время. Книга будет полезна как специалистам-профессионалам, так тем, кто только приступает к изучению методологии ООП.