М. Фаулер, К. Скотт - UML. Основы - 2002 (1158629), страница 25
Текст из файла (страница 25)
Язык Лача разрешает также помечать классы как общедоступные или пакетные. Общедоступные элементы общедоступного класса могут использоваться любым классом, который импортирует пакет, содержащий исходный класс. Пакетный класс может быть использован только другими классами в том же самом пакете.
Последний штрих в эти тонкости добавляет язык С++. В языке С++ какой-либо метод или класс может быть определен как «дружественный» (Уг1епс() для класса. Такой дружественный элемент обладает полным доступом ко всем элементам класса. Отсюда пошло высказывание: «в С++ друзья прикасаются к закрытым частям друг друга». При определении видимости пользуйтесь правилами того языка, на котором вы программируете. С какой бы точки зрения вы не смотрели на модель 1)МЬ, следует с осторожностью относиться к смыслу маркеров видимости и осознавать, что их смысл может меняться от языка к языку. По моему мнению, обычно видимость изменяется в процессе кодирова- ния. Поэтому не следует определять ее слишком рано.
Пакеты и кооперации Один из старейших вопросов методологии разработки программного обеспечения: как разбить большую систему на небольшие подсистемыу Мы задаем этот вопрос, поскольку чем больше становятся системы, тем труднее разбираться в них и во вносимых в них изменениях. Структурные методы использовали функциональную декомпозицию, согласно которой вся система в целом представляется как одна функция и разбивается на подфункции, которые в свою очередь тоже разбиваются на подфункции и т.
д, Эти функции похожи на варианты использования в объектно-ориентированной системе в том, что функции представляют собой действия, выполняемые системой в целом. В прежние времена процесс и данные рассматривались отдельно друг от друга. Другими словами, помимо функциональной декомпозиции существовала также структура данных. Она имела второстепенное значение, хотя некоторые методы информационных технологий группировали записи данных в предметные области и формировали матрицы, чтобы показать взаимосвязь функций и записей данных. Именно с этой точки зрения мы можем оценить те огромные изменения, которые произвели объекты.
Разделение процесса и данных осталось в прошлом, функциональная декомпозиция тоже, однако старейший вопрос по-прежнему все еще существует. Одна из идей заключается в группировке классов в блоки более высокого уровня. Эта идея, применяемая самым произвольным образом, 11В Глава 7. Пакеты и кооперации проявляется во многих объектных методах. В языке СМ1. такой механизм группировки получил название пакет (рас)тане).
Пакеты Идея пакета может быть применена не только к классам, но и к любому другому элементу модели. Без некоторых эвристических процедур группировка классов может оказаться произвольной. Одной из них, которую я считаю самой полезной и которая повсеместно используется в языке УМЕ, является завиеимоеть. Я использую термин диаграмма пакетов по отношению к диаграмме, которая содержит пакеты классов и зависимости между ними. Строго говоря, диаграмма пакетов является всего лишь разновидностью диаграммы классов, на которой показаны только пакеты и зависимости. Сам я использую эти диаграммы очень часто, поэтому и называю их диаграммами пакетов.
Однако следует помнить, что этот термин введен мною, а не является официальным именем диаграммы в языке СМ1. Между двумя элементами существует зависимость, если изменения в определении одного элемента могут повлечь за собой изменения в другом. Что касается классов, то характер зависимостей может быть самым различным: один класс посылает сообщение другому; один класс включает другой класс как часть своих данных; один класс ссылается на другой как на параметр некоторой операции. Если класс меняет свой интерфейс, то любое сообщение, которое он поеылает, может оказаться ошибочным. В идеальном случае только изменения в интерфейсе класеа должны оказывать влияние на другие классы. Искусство проектирования больших систем включает в себя минимизацию зависимостей; таким образом влияние изменений уменьшается, а для изменения системы требуются меньшие усилия.
В языке ПМ1. имеются разнообразные виды зависимостей, каждый из которых обладает самостоятельной семантикой и етереотипом. По моему мнению, намного проще начинать с зависимости без стереотипа и использовать более конкретные виды зависимостей только по мере необходимости. На рис.
7.1 изображены классы предметной области, моделирующие бизнес-систему и сгруппированные в два пакета: Заказы и Клиенты. Оба пакета являются частью пакета предметной области в целом. Приложение Сбора Заказов имеет зависимости с обоими пакетами предметной области. Пользовательский Интерфейс Сбора Заказов имеет зависимости с Приложением Сбора Заказов и А%'Т (средством разработки графического интерфейса пользователя в языке )атта). Пакеты Пакет ЗееисииОсть Рис. 7.г.
Диаграмма валетов Между двумя пакетами существует некоторая зависимость, если существует какая-либо зависимость. между любыми двумя классами в пакетах. Например, если любой класс в пакете Список Рассылки зависит от какого-либо класса в пакете Клиенты, то между зтими пакетами существует зависимость. Существует очевидное сходство между зависимостями пакетов и зависимостями компиляции.
Тем не менее, между ними имеется принципиальное различие: зависимости пакетов не являются транзитивными. Можно привести следующий пример траизитивного отношения: у Джима борода длиннее, чем у Гради, а у Гради длиннее, чем у Айвара, отсюда можно заключить, что у Джима борода длиннее, чем у Айвара. Чтобы понять, почему ето так важно для зависимостей, обратимся снова к рис.
7.1, Если изменяется какой-либо класс в пакете Заказы, то зто совсем не означает, что должны быть внесены изменения в пакет Пользовательский Интерфейс Сбора Заказов. Это всего лишь означает, что нужно проверить, не изменился ли пакет Приложение Сбора Заказов. Пакет Пользовательский Интерфейс Сбора Заказов может потребовать изменений только в том случае, если изменится интерфейс пакета Приложение Сбора Заказов. В данной ситуации Приложение Сбора Заказов защищает Пользовательский Интерфейс Сбора Заказов от изменений в заказах.
1го Глава 7. Пакеты и кооперации Такое поведение системы является классической особенностью многоуровневой архитектуры. Действительно, именно такова семантика поведения конструкции «1трогФв» в языке дача, но поведение конструкции «1пс1цбеэ» в языке С/С++ другое.
В языке С/С++ конструкция «1пс1цт(ев» является транзитивной, а это означает, что Пользовательский Интерфейс Сбора Заказов следует считать зависимым от пакета Заказы. Транзитивная зависимость затрудняет ограничение области действия изменений при компиляции.
(Хотя большинство зависимостей не являются транзитивными, вы можете определить специальный стереотип для этой цели.) Классы в пакетах могут быть общедоступными, закрытыми и защищенными. Таким образом, пакет Заказы зависит от общедоступных методов общедоступного класса в пакете Клиенты. Если изменить некоторый закрытый метод в любом классе пакета Клиенты или общедоступный метод в каком-либо закрытом классе пакета Клиенты, то эти изменения не затронут ни один из классов в пакете Заказы.
В данном случае может оказаться полезным сократить интерфейс этого пакета за счет экспорта только небольшого подмножества операций, ассоциированных с общедоступными классами в этом пакете. Это можно сделать присвоением всем классам закрытой видимости с тем, чтобы они могли быть видимы только для других классов того же самого пакета, а также посредством добавления экстрадоступных классов для общедоступного поведения. После чего эти экстра-классы, получившие название фасадов (~асат(еа) (Гамма и др., 1995 1201), делегируют общедоступные операции своим соседям по пакету. Хотя пакеты не дают ответа на вопрос, как уменьшить количество зависимостей в вашей системе, однако они помогают выделить эти зависимости. Как только они окажутся на виду, вам останется лишь поработать над их сокращением.
По моему мнению„диаграммы пакетов являются основным средством управления общей структурой системы. На рис. 7.2 изображена более сложная диаграмма пакетов, содержа- щая ряд дополнительных конструкций. Во-первых, мы видим, что добавлен пакет Предметная Область, который содержит пакеты Заказы и Клиенты. Это представляется весьма полезным, поскольку означает, что вместо множества отдельных зависимостей можно изобразить зависимости, направленные к этому пакету и от пакета в целом. Когда показывается содержимое некоторого пакета, то имя пакета помещается в небольшой верхний прямоугольник, а состав пакета изображается внутри основного прямоугольника. Пакет может содержать внутри себя перечень некоторых классов, как в случае пакета Общий; другую диаграмму пакетов, как в случае пакета Предметная Область; или некоторую диаграмму классов (которая не показана, но идея сама по себе является очевидной).
Пакеты Рис. 7.2. Расширенная диаграмма пакетов Я считаю, что в большинстве случаев вполне достаточно перечислить основные классы, но иногда оказывается полезным указать на диаграмме дополнительную информацию. В данном случае я показал, что хотя Приложение Сбора Заказов связано зависимостью со всем пакетом Предметная Область, Приложение Списка Рассылки зависит только от пакета Клиенты.