Компонентный подход в программировании

       

Многоуровневая система


Название. Многоуровневая система (layers).

Назначение. Реализация больших систем, которые имеют большое количество разноплановых элементов, использующих друг друга. Некоторые аспекты работы таких систем могут включать в себя много операций, выполняемых разными компонентами на разных уровнях (т.е. одна задача решается за счет последовательных обращений между элементами разных уровней, другая — тоже, но участвующие в решении этих задач элементы могут быть различны). При этом нужно принимать во внимание следующие факторы:

Действующие силы.

  • Изменения в требованиях к решению одной из задач не должны приводить к изменениям в коде многочисленных компонентов, желательно, чтобы они сводились к изменениям внутри одного компонента. То же касается и изменений платформы, на которой работает система.
  • Интерфейсы между компонентами должны быть стабильными или даже соответствовать имеющимся стандартам.
  • Части системы должны быть заменяемы. Компоненты должны быть заменяемы другими, если те реализуют такие же интерфейсы. В идеале может даже потребоваться в ходе работы переключиться на другую реализацию, даже если при начале работы системы она не была доступна.
  • Низкоуровневые компоненты должны позволять разрабатывать другие системы быстрее.
  • Компоненты с похожими областями ответственности должны быть сгруппированы для повышения понятности системы и удобства внесения в нее изменений.
  • Нет возможности выделить компоненты некоторого стандартного размера: одни из них решают достаточно сложные задачи, другие — совсем простые.
  • Сложные компоненты нуждаются в дальнейшей декомпозиции.
  • Использование большого числа компонентов может отрицательно сказаться на производительности, поскольку данным придется часто преодолевать границы между компонентами.
  • Разработка системы должна быть эффективно поделена между отдельными разработчиками. При этом интерфейсы и зоны ответственности компонентов, передаваемых разным разработчикам, должны быть очень четко определены.

Решение. Выделяется некоторый набор уровней, каждый из которых отвечает за решение своих собственных подзадач. Для этого он использует интерфейс, предоставляемый предыдущим уровнем, предоставляя, в свою очередь, некоторый интерфейс для следующего уровня.

Каждый отдельный уровень может быть в дальнейшем декомпозирован на более мелкие компоненты.

Структура. Основными компонентами являются уровни. Иногда выделяют клиентов, использующих интерфейс самого верхнего уровня. Каждый уровень предоставляет интерфейс для решения определенного множества задач. Сам он решает их, опираясь на интерфейс предшествующего уровня.

На каждом уровне может находиться много более мелких компонентов.


увеличить изображение
Рис. 7.11.  Пример структуры многоуровневой системы.

Классы для уровней условные, они обычно декомпозируются на наборы более мелких компонентов

Динамика. Сценарии работы системы могут быть получены компоновкой следующих четырех. Часто в виде многих уровней реализуются коммуникационные системы, две такие системы могут взаимодействовать через самый нижний уровень — при этом пара симметричных сценариев (по подъему–спуску обращений) выполняется в рамках одного общего сценария на разных машинах.

  • Обращение клиента к верхнему уровню инициирует цепочку обращений с верхнего уровня до самого нижнего.
  • Событие на нижнем уровне (например, приход сообщения по сети или нажатие на кнопку мыши) инициирует цепочку обращений, идущую снизу вверх, вплоть до некоторого события самого верхнего уровня, видимого клиентам.
  • Обращение клиента к верхнему уровню приводит к цепочке вызовов, которая, однако, не доходит до самого низа. Такая ситуация реализуется, если, например, один из уровней кэширует ответы на запросы и может выдать ответ на ранее уже подававшийся запрос без обращения к более низким уровням.
  • То же самое может произойти и с событием, которое передается с самого нижнего уровня. Дойдя до некоторого уровня, оно может поглотиться им (с изменением состояния каких-то компонентов), потому что не соответствует никакому событию на более высоких уровнях. Например, нажатие клавиши Capslock не приводит само по себе ни к каким реакциям программы, но изменяет значение нажимаемых после этого клавиш, меняя их регистр на противоположный.


увеличить изображение
Рис. 7.12.  Составной сценарий пересылки сообщения по сети

Реализация. Основные шаги реализации следующие:

  • Определить критерии группировки задач по уровням. Это критически важный шаг. Неправильное распределение задач, скорее всего, приведет к необходимости перепроектировать систему.
  • Определить количество уровней, которые будут реализованы, и их имена. Часто приходится объединять концептуально различные задачи, чтобы добиться большей эффективности системы. С другой стороны, произвольное смешение задач на уровне ведет к непонятной архитектуре и к системе, очень неудобной для сопровождения. При возможности поместить некоторую задачу на несколько уровней, стоит размещать ее на самом высоком уровне из тех, где она может быть решена с достаточной производительностью.
  • Определить интерфейсы, предоставляемые нижними уровнями верхним. Здесь нужно помнить, что с помощью несколько большего, чем минимально необходимый, набора интерфейсных операций нижнего уровня можно добиться значительного повышения производительности системы в целом.
  • Определить компоненты и их взаимодействие в рамках каждого отдельного уровня.
  • Определить способы взаимодействия соседних уровней. Можно использовать проталкивание, вытягивание данных или комбинацию этих подходов.
  • Отделить соседние уровни. В идеале нижние уровни не должны знать ничего о верхних, каждый уровень должен знать только о непосредственно предшествующем ему. Для этого передачу данных с нижнего уровня можно организовать в виде обратных вызовов (callbacks) — указатель на функцию, которую нужно вызвать для передачи сообщения наверх, верхний уровень может передавать в качестве параметра при предшествующих запросах.
  • Спроектировать и реализовать обработку ошибок. Ошибки лучше обрабатывать на самом нижнем уровне, который в состоянии их заметить.

Следствия применения образца.

Достоинства:

  • Возможность легко заменять и переиспользовать компоненты одного уровня, не оказывая влияния на остальные уровни. Возможность отлаживать и тестировать уровни по отдельности.
  • Поддержка стандартов. Многоуровневость системы делает возможной поддержку стандартных интерфейсов, таких как POSIX.

Недостатки:

  • Изменение функциональности одного уровня может привести к каскадному изменению всех уровней. Существенный рост производительности нижнего уровня и требование обеспечить соответствующий рост производительности на более высоких уровнях также могут привести к переопределению всех интерфейсов.
  • Падение производительности из-за необходимости проводить все вызовы и данные через все уровни.
  • Часто уровни дублируют работу друг друга, например, при обработке ошибок, поскольку они разрабатываются независимо и не имеют информации о деталях реализации друг друга.
  • Большое количество уровней может привести к существенному повышению сложности системы и падению ее производительности. С другой стороны, слишком малое число уровней (например, два) часто не позволяет обеспечить необходимую гибкость и переносимость.

Примеры. Наиболее известный пример использования данного образца — стандартная модель протоколов связи открытых систем (Open System Interconnection, OSI) [9]. Она состоит из 7 уровней:

  • Самый нижний уровень — физический. Он отвечает за передачу отдельных битов по каналам связи. Основные его задачи — гарантировать правильное определение нуля и единицы разными системами, определить временные характеристики передачи (за какое время передается один бит), обеспечить передачу в одном или двух направлениях, и т.п.
  • Второй уровень — канальный или уровень передачи данных. Его задача — предоставить верхним уровням такие сервисы, чтобы для них передача данных выглядела бы как посылка и прием потока байт без потерь и без перегрузок.
  • Третий уровень — сетевой. Его задача — обеспечить прозрачную связь между компьютерами, не соединенными непосредственно, а также обеспечивать нормальную работу больших сетей, по которым одновременно путешествует очень много пакетов данных.
  • Четвертый уровень — транспортный. Он обеспечивает надежную передачу данных верхних уровней словно по некоторой трубе — пакеты приходят обязательно в той же последовательности, в которой они были отправлены. Заметим, что канальный уровень решает такую же задачу, но только для непосредственно связывающихся друг с другом машин.
  • Пятый, сеансовый уровень предоставляет возможность устанавливать сеансы связи (или сессии), содержащие некоторый набор передаваемых туда и обратно сообщений, и управлять ими.
  • Шестой, уровень представления, определяет форматы передаваемых данных. Например, именно здесь определяется, что целое число будет представляться 4 байтами, причем старшие биты числа идут раньше младших, первый бит интерпретируется как знак, а отрицательные числа представляются в дополнительной системе (т.е. 0x0000000f обозначает 15, а 0x80000000f — 2147483633 = –(231–15)).
  • Наконец, седьмой уровень — прикладной — содержит набор протоколов, которыми непосредственно пользуются программы и с которыми работают пользователи — HTTP, FTP, SMTP, POP3 и пр.

Модель OSI оказалась все же слишком сложна для использования на практике. Сейчас наиболее широко применяемые наборы протоколов строятся по урезанной схеме OSI — в ней отсутствуют пятый и шестой уровни, прикладные протоколы пользуются непосредственно службами протоколов транспортного уровня.

Другой пример многоуровневой архитектуры — архитектура современных информационных систем или систем автоматизации бизнеса. Она включает следующие уровни [3]:

  • Интерфейс взаимодействия с внешней средой.

    Чаще всего этот уровень рассматривается как интерфейс пользователя. В его рамках определяется представление данных для передачи другим системам или пользователям, набор экранов, форм и отчетов, с которыми имеют дело пользователи.

  • Бизнес-логика. На этом уровне реализуются основные правила функционирования данного бизнеса, данной организации.
  • Предметная область. Данный уровень содержит концептуальную схему данных, с которыми имеет дело организация. Эти же данные могут использоваться и другими организациями в своей работе.
  • Уровень управления ресурсами.

    На нем находятся все ресурсы, которыми пользуется система, в том числе другие системы. Очень часто используемые ресурсы сводятся к набору баз данных, необходимых для работы организации. На этом уровне определяется структура используемых ресурсов и способы управления ими, в частности, конкретное размещение данных по таблицам реляционной базы данных или классам объектной базы данных и соответствующий набор индексов. Чаще всего схемы баз данных оптимизируются под конкретный набор запросов, и поэтому их структура несколько отличается от концептуальной схемы данных, находящейся на предыдущем уровне.

Часто два средних уровня объединяются в один — уровень функционирования приложений, что дает в результате широко используемую трехзвенную архитектуру информационных систем.


Содержание раздела