Как уже отмечалось в главе 6, создание архитектуры подразумевает выявление основной структуры классов и спецификацию общих взаимодействий, которые оживляют классы. Сконцентрировав внимание прежде всего на этих механизмах, мы с самого начала выявляем элементы наибольшего риска и нацеливаем на них все усилия системных архитекторов. Результаты этой фазы дают хорошую основу (в виде классов и взаимодействий), на базе которой строятся функциональные элементы нашей системы.
В данном разделе мы подробно рассмотрим семантику каждого из четырех выделенных ключевых механизмов.
Механизм передачи сообщений
Под сообщением здесь мы не имеем в виду активизацию методов, как это принято в объектно-ориентированных языках программирования. В данном случае понятие взято из словаря предметной области, из самого высокого уровня абстракции. Вот несколько примеров сообщений в системе управления движением: сигнал запуска путевому устройству, сообщение о прохождении поезда через определенный пункт пути, приказ диспетчера машинисту. Все эти виды сообщений могут передаваться внутри системы управления движением на двух уровнях:
• между компьютерами и устройствами
• между компьютерами.
Сейчас нас интересует второй уровень передачи сообщений. Так как система включает территориально распределенную сеть, мы должны учесть такие факторы, как помехи, отказы оборудования и секретность передачи информации.
Первый шаг при определении сообщений в системе - анализ взаимодействия каждой пары сообщающихся компьютеров (см. рис. 12-3). Для каждой такой пары мы должны задать три вопроса: (1) Какую информацию обрабатывает каждый компьютер? (2) Какая информация будет передаваться с одного компьютера на другой? (3) К какому уровню абстракции будет относиться эта информация? Эмпирического ответа на эти вопросы нет. Мы должны действовать итеративно, пока не придем к уверенности, что определены правильные сообщения и в системе связи нет "узких" мест (которые могут возникать из-за перегрузки линий связи или, например, из-за того, что сообщение разбивается на слишком мелкие пакеты).
Очень важно, чтобы на данном этапе проектирования внимание было сосредоточено на сути, а не на форме сообщений. Слишком часто системные архитекторы начинают проектирование с выбора битового представления сообщений. В реальной задаче преждевременный выбор низкоуровневого представления обязательно приведет к изменениям в дальнейшем и затронет всех, кто пользовался этим представлением. Кроме того, на ранней стадии проектирования у нас пока нет полной информации, как будут использоваться данные сообщения, и, следовательно, мы не можем судить, какое представление будет оптимальным по размеру и времени передачи.
Концентрируя внимание на сути сообщений, мы рассмотрим все классы сообщений. Другими словами, нужно определить назначение и смысл каждого сообщения, а также перечислить операции их обработки.
На диаграмме классов на рис. 12-4 показаны некоторые наиболее важные сообщения в системе управления движением. Заметим, что все сообщения в конечном счете являются экземплярами абстрактного класса Message
, который инкапсулирует поведение, общее для всех сообщений. Три класса следующего уровня представляют главные категории сообщений: сообщение о состоянии поезда, сообщение о плане движения поезда, сообщение путевого устройства. Каждый из этих трех классов будет детализирован в дальнейшем. В результате проектирования должны появиться десятки специализированных классов. Таким образом, существование обобщающих абстрактных классов чрезвычайно важно; без них мы получили бы сотни несвязанных между собой и, следовательно, сложных в использовании модулей, каждый из которых реализовывал бы специализированный класс, По мере проектирования мы будем выявлять другие важные группы сообщений и создавать для них специализированные промежуточные классы. К счастью, изменения в иерархии классов не должны волновать клиентов, использующих классы.Прежде всего нам следует стабилизировать интерфейсы ключевых классов сообщений. Начинать этот процесс лучше всего с основных классов иерархии. Начнем с введения двух следующих типов;
//номер, обозначающий уникальный идентификатор пакета typedef unsigned int PacketId;
//номер, обозначающий уникальный сетевой идентификатор typedet unsigned Int NodeId;
Теперь дадим определение абстрактного класса Message:
class Message { public: