Разбиение системы на модули



3.1.1. Разбиение системы на модули

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

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

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

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

Подсистемы (и реализующие их модули) могут образовывать в системе уровни, либо разделы.

Уровни

Уровневая система может рассматриваться как упорядоченное множество виртуальных миров, каждый из которых построен на основе понятий, поддерживаемых его подсистемами; подсистемы одного уровня обеспечивают реализацию подсистем следующего уровня. Объекты каждого уровня могут быть независимыми, хотя нередко объекты разных уровней могут соответствовать друг другу. Каждая подсистема знает о подсистемах более низких уровней и ничего не знает о более высоких уровнях. Зависимость клиент-сервер существует между более верхним (клиент) и более нижними уровнями (серверы). При этом каждый уровень может иметь свой собственный набор классов и операций. Каждый уровень реализуется через операции объектов и подсистем более нижних уровней. Уровневые архитектуры бывают двух видов: открытые и замкнутые. В замкнутой архитектуре каждый уровень строится на базе непосредственно следующего за ним уровня. Это сокращает зависимости между уровнями и упрощает внесение изменений. В открытой архитектуре каждый уровень строится на базе всех следующих за ним уровней. Это уменьшает потребность в переопределении операций на каждом уровне и приводит к более эффективному и компактному коду. Однако открытая архитектура не удовлетворяет принципу упрятывания информации, поскольку изменения в какой-либо подсистеме могут потребовать соответствующих изменений в подсистемах более высоких уровней.

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

Система с уровневой архитектурой при переносе на другую платформу требует переписывания только одного (самого нижнего) уровня. Пример системы с уровневой архитектурой представлен на рисунке 3.1.



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