Подход BCE

Пакеты

Иерархия классов

Углубленное моделирование классов

Моделирование открытых интерфейсов

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

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

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

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

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

1 “Создать” (Create).

2 “Читать” (Read).

3 “Обновить” (Update).

4 “Удалить” (Delete).

Этот набор операций известен как CRUD-операции. CRUD-операции позволяют другим объектам отправлять сообщение объекту с требованием выполнить следующие действия.

1 Создать новый экземпляр объекта (Create).

2 Получить доступ к состоянию объекта(Read).

3 Модифицировать состояние объекта (Update).

4 Объект уничтожает сам себя (Delete).

Дополнительные концепции моделирования включают:

● стереотипы,

● ограничения,

● производную информацию,

● видимость,

● ассоциативные классы,

● параметризованные классы и т.д.

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

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

Если ограничение является слишком длинным или же оно должно быть выражено с использованием трех или более графических символов, можно воспользоваться таким понятием UML, как примечание. Примечания может содержать текст ограничения, однако, в общем случае, оно может содержать любую информацию. Чтобы показать, что примечание является ограничением, его необходимо дополнительно обозначить как стереотип с помощью ключевого слова «constraint».

Подобно примечаниям, дескрипторы представляют произвольную текстовую информацию в модели, в том числе, ограничения. Аналогично ограничениям дескрипторы записываются внутри фигурных скобок.

Видимость и инкапсуляция. В UML в качестве стандартных обозначений видимости приняты следующие знаки: + (для открытой), # (для защищенной ) и – (для закрытой) видимости. Знаки помещаются перед именем свойства. CASE-средства часто заменяют эти обозначения на свои собственные. На рис.5.2. представлен класс, изображенный с помощью CASE-средства Rational Software Architect (RSA). Открытые элементы класса изображены зеленым цветом, защищенные – желтым, закрытые – красным.

 

Рисунок 5.2. Изображение класса в RSA

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

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

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

 

Рисунок 5.3. Производный атрибут (/).

На рис. 5.3. показан производный атрибут conf_items_count, который хранит количество элементов конфигурации, из которых собран компьютер. Его можно вычислять каждый раз, как количество элементов коллекции, можно вычислить один раз и хранить в этом атрибуте.

Типичным случаем производной ассоциации можно считать ассоциацию, образованную тремя классами, уже соединенными двумя ассоциациями, при этом третья ассоциативная связь замыкает контур (рис.5.4.).

Рисунок 5.4. Производная ассоциация

Производную ассоциацию можно ввести т. к. кратность ассоциации между Order и Invoice равна 1 к 1.

Производная ассоциация не вносит в модель какой-либо новой информации. Всегда можно связать клиента (Customer) с определенным заказом (Order), отыскав один заказ для каждого счета-фактуры (Invoice), а затем одного клиента для каждого заказа.

Ассоциативный класс - ассоциация, которая сама является классом. Ассоциативный класс обычно используется в тех случаях, когда между двумя классами существует ассоциация “многие ко многим” и каждый экземпляр ассоциации (связь) обладает собственными значениями атрибутов. Чтобы обеспечить возможность хранить эти атрибуты, требуется класс - ассоциативный класс (рис.5.5.).

 

Рисунок 5.5. Ассоциативный класс

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

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

Постановка задачи для примера создает некоторые проблемы. Нам требуется класс для хранения подробной информации о сотруднике (Employee), а также класс для хранения информации об уровнях зарплаты (SalaryLevel). Проблема состоит в моделировании текущих назначений зарплаты работникам, а также хронологии этих назначений. На первый взгляд кажется естественным использовать ассоциативный класс. Но подобное решение неверно, т. к. у одного сотрудника в разные периоды времени может оказаться один уровень зарплаты (т. е. ключи emp_ID+level_id будут одинаковые, а остальные атрибут будут отличаться). Но никакие два объекта ассоциативного класса не могут иметь одинаковых составных ключей (т.е. одинаковых связей с объектами Employee и SalaryLevel). В этом случае лучше использовать материализованный класс (рис. 5.6.).

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

 

Рисунок 5.6. Материализованный класс

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

Хорошо известный принцип когнитивной психологии - правило 7±2 - гласит, что кратковременная память человеческого мозга может одновременно справиться приблизительно с девятью (7±2) предметами (графическими элементами, идеями, понятиями и т.д.). Нижняя граница, равная пяти (7-2), указывает на то, что работа, менее чем с пятью предметами, составляет тривиальную проблему.

Но нам необходимы большие системы, а большие системы сложны. Значительная часть этой сложности привнесена человеком, а не присуща самой системе.

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

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

Классом может владеть только один пакет. Это не препятствует появлению класса в других пакетах или взаимодействию с классами в других пакетах. Используя объявление класса внутри пакета как закрытого, защищенного или открытого, можно контролировать взаимодействие и зависимости между классами в разных пакетах.

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

Пакеты создаются в диаграмме классов или диаграмме прецедентов. В первом случае диаграмма пакетов представляет модель системы с точки зрения ее состояний (описывает архитектуру системы). Во втором случае - с точки зрения поведения системы (описывает функциональную структуру).

Подход BCE (Boundary-Control-Entity – граница-управление-сущность) представляет собой подход к объектному моделированию, основанный на трехфакторном представлении классов. В языке UML для классов определены три стереотипа: boundary (граница), control (управление) и entity (сущность). Это и определило выбор аббревиатуры BCE.

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

Управляющие классы (control class) описывают объекты, которые перехватывают входные события, инициированные пользователем, и контролируют выполнение бизнес-процесса. Управляющий класс представляет действия и виды деятельности прецедентов. Управляющие объекты зачастую не сохраняются после выполнения программы.

Классы-сущности (entity class) описывают объекты, которые представляют семантику сущностей, принадлежащих проблемной области. Они соотносятся со структурами данных системной базы данных. Объекты-сущности всегда сохраняются после выполнения программы и участвуют во многих прецедентах.

В правильно спроектированной иерархии пакетов актер может взаимодействовать только с пограничными объектами из пакета BoundaryPackage, объекты-сущности из пакета EntityPackage могут взаимодействовать только с управляющими объектами из ControlPackage и управляющие объекты из ControlPackage могут взаимодействовать со объектами любого типа.

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

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

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

Основным преимуществом подхода BCE является группирование классов в виде иерархических уровней. Это способствует лучшему пониманию модели и уменьшает ее сложность.

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

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