Результаты перехода от модели бизнес-процессов к модели системных процессов представлены на рис. 4.1—4.2. На диаграмме системных процессов первого уровня вместо отдельных процессов введены процессоры — компьютеры, на которых выполняются соответствующие процессы.
Рис. 4.1. Диаграмма системных процессов нулевого уровня
Рис. 4.2. Диаграмма системных процессов первого уровня
Результаты построения абстрактной модели пользовательского интерфейса системы, отражающей последовательность появления экранных форм в приложении, представлены на рис. 4.3.
Рис. 4.3. Диаграмма последовательности экранных форм
4.3.
ОБЪЕКТНО-ОРИЕНТИРОВАННЫЙ АНАЛИЗ
Целью объектно-ориентированного анализа[25] является трансформация функциональных требований к ПО в предварительный системный проект и создание стабильной основы архитектуры системы. В процессе проектирования системный проект «погружается» в среду реализации с учетом всех нефункциональных требований.
Объектно-ориентированный анализ включает два вида деятельности: архитектурный анализ и анализ вариантов использования. Изложение их методики будет сопровождаться примерами из системы регистрации учебного заведения, которая рассматривалась в главе 3.
4.3.1.
АРХИТЕКТУРНЫЙ АНАЛИЗ
Архитектурный анализ выполняется архитектором системы и включает в себя:
· утверждение общих стандартов (соглашений) моделирования и документирования системы;
· предварительное выявление архитектурных механизмов (механизмов анализа);
· формирование набора основных абстракций предметной области (классов анализа);
· формирование начального представления архитектурных уровней.
Соглашения моделирования определяют:
· используемые диаграммы и элементы модели;
· правила их применения;
· соглашения по именованию элементов модели;
· организацию модели (пакеты).
Пример набора соглашений моделирования:
· Имена вариантов использования должны быть короткими глагольными фразами.
· Имена классов должны быть существительными, соответствующими, по возможности, понятиям предметной области.
· Имена классов должны начинаться с заглавной буквы.
· Имена атрибутов и операций должны начинаться со строчной буквы.
· Составные имена должны быть сплошными, без подчеркиваний, каждое отдельное слово должно начинаться с заглавной буквы.
· Все классы и диаграммы, описывающие предварительный системный проект, помещаются в пакет с именем Analysis Model.
· Диаграммы классов, реализующих вариант использования, и диаграммы взаимодействия, отражающие взаимодействие объектов в процессе реализации сценариев варианта использования, помещаются в кооперацию (см. подразд. 2.6) с именем данного варианта использования и стереотипом «use-case realization». Все кооперации помещаются в пакет с именем Use Case Realizations. Связь между вариантом использования и его реализацией изображается на специальной диаграмме трассировки (рис. 4.4).
Рис. 4.4. Фрагмент диаграммы трассировки
Архитектурные механизмы отражают нефункциональные требования к системе (надежность, безопасность, хранение данных в конкретной среде, интерфейсы с внешними системами и т.д.) и их реализацию в архитектуре системы. В процессе анализа они только обозначаются, отвлекаясь от особенностей среды реализации, а все детали их реализации определяются в процессе проектирования.
Архитектурные механизмы, по существу, представляют собой набор типовых решений, или образцов, принятых в качестве стандарта данного проекта.
Идентификация основных абстракций заключается в предварительном определении набора классов системы (классов анализа) на основе описания предметной области и спецификации требований к системе (в частности, глоссария). Способы идентификации основных абстракций аналогичны способам идентификации сущностей в модели ERM.
Так, для системы регистрации идентифицировано пять классов анализа:
· Student (Студент);
· Professor (Профессор);
· Schedule (Учебный график);
· Course (Курс);
· CourseOffering (Предлагаемый курс).
Классы анализа показаны на рис. 4.5.
Рис. 4.5. Классы анализа системы регистрации
Архитектурные уровни образуют иерархию уровней представления любой крупномасштабной системы. В практике разработки таких систем существует ряд типовых решений — архитектурных образцов, среди которых наиболее распространенным является образец «Уровни» (Layers). Этот образец можно описать следующим образом:
Наименование образца:
«Уровни».
Контекст:
Крупномасштабные системы, нуждающиеся в декомпозиции.
Проблема:
Архитектура крупномасштабной системы должна удовлетворять следующим требованиям:
· компоненты системы должны иметь возможность замены;
· изменения в одних компонентах не должны сильно затрагивать другие;
· однородные функции должны группироваться вместе;
· размер компонентов не должен быть слишком большим.
Решение:
Предлагается базовый вариант, включающий следующие уровни (сверху вниз):
· прикладной (Application Subsystems) — набор компонентов, реализующих основную функциональность системы, отраженную в вариантах использования;
· бизнес-уровень (Business-specific) — набор компонентов, специфичных для конкретной предметной области;
· промежуточный (Middleware) — различные платформо-независимые сервисы (библиотеки пользовательского интерфейса, брокеры запросов и др.);
· системный (System software) — ПО для вычислительной и сетевой инфраструктуры (ОС, сетевые протоколы и др.).
Архитектурные уровни представляются в модели в виде пакетов со стереотипом «1ауег». Количество и структура уровней зависят от сложности предметной области и среды реализации. В рамках архитектурного анализа определяется начальная структура модели (набор пакетов и их зависимостей) и рассматриваются только верхние уровни (прикладной и бизнес-уровень).
4.3.2.
АНАЛИЗ ВАРИАНТОВ ИСПОЛЬЗОВАНИЯ
Анализ вариантов использования выполняется проектировщиками и включает в себя:
· идентификацию классов, участвующих в реализации потоков событий варианта использования;
· распределение поведения, реализуемого вариантом использования, между классами (определение обязанностей классов);
· определение атрибутов и ассоциаций классов;
· унификацию классов анализа.
Идентификация классов, участвующих в реализации потоков событий варианта использования
В потоках событий варианта использования выявляются классы трех типов.
Граничные классы (Boundary) — служат посредниками при взаимодействии внешних объектов с системой. Как правило, для каждой пары «действующее лицо — вариант использования» определяется один граничный класс. Типы граничных классов: пользовательский интерфейс (обмен информацией с пользователем без деталей интерфейса — кнопок, списков, окон), системный интерфейс и аппаратный интерфейс (используемые протоколы без деталей их реализации).
Классы-сущности (Entity) — представляют собой основные абстракции (понятия) разрабатываемой системы, рассматриваемые в рамках конкретного варианта использования. Источники выявления классов-сущностей: основные абстракции, созданные в процессе архитектурного анализа, глоссарий, описание потоков событий вариантов использования, сущности, описанные в модели бизнес-анализа (при наличии бизнес-модели).
Управляющие классы (Control) — обеспечивают координацию поведения объектов в системе. Они могут отсутствовать в некоторых вариантах использования, ограничивающихся простыми манипуляциями с хранимыми данными. Как правило, для каждого варианта использования определяется один управляющий класс. Примеры управляющих классов: менеджер транзакций, координатор ресурсов, обработчик ошибок.
Классы анализа отражают функциональные требования к системе и моделируют объекты предметной области. Совокупность классов анализа представляет собой начальную концептуальную модель системы.
Пример набора классов, участвующих в реализации варианта использования «Зарегистрироваться на курсы», приведен на рис. 4.6.
Рис. 4.6. Классы, участвующие в реализации варианта использования «Зарегистрироваться на курсы»
Распределение поведения, реализуемого вариантом использования, между классами
Квалифицированное распределение обязанностей между классами является наиболее важной частью объектно-ориентированного анализа. Исходя из назначения трех выделенных типов классов, можно кратко охарактеризовать распределение обязанностей между ними:
· граничные классы отвечают за взаимодействие с внешней средой системы (действующими лицами);
· классы-сущности отвечают за хранение и манипулирование данными;
· управляющие классы координируют потоки событий варианта использования.
Более детальное распределение обязанностей (в виде операций классов) выполняется с помощью диаграмм взаимодействия (диаграмм последовательности и кооперативных диаграмм).
В процессе анализа конкретного варианта использования в первую очередь строится диаграмма последовательности (одна или более), описывающая основной поток событий и его подчиненные потоки. Для каждого альтернативного потока событий строится отдельная диаграмма (из соображений простоты наглядного восприятия). Нецелесообразно описывать тривиальные потоки событий (например, в потоке участвует только один объект).
Рис. 4.7. Диаграмма последовательности «Зарегистрироваться на курсы» — Основной поток событий
На рис. 4.7—4.11 приведены диаграммы последовательности и кооперативные диаграммы для основного потока событий варианта использования «Зарегистрироваться на курсы».
Рис. 4.8. Кооперативная диаграмма «Зарегистрироваться на курсы» - подчиненный поток «Создать график»
Рис. 4.9. Кооперативная диаграмма «Зарегистрироваться на курсы» — подчиненный поток «Обновить график»
На последней диаграмме (см. рис. 4.11) присутствует объект дополнительного класса-сущности PrimaryScheduleOfferinglnfo. Его назначение будет описано ниже, при рассмотрении связей между классами.
Обязанности каждого класса определяются исходя из сообщений на диаграммах взаимодействия и документируются в классах в виде операций «анализа», которые появляются там в процессе построения диаграмм взаимодействия (соотнесения сообщений с операциями).
Рис. 4.10. Кооперативная диаграмма «Зарегистрироваться на курсы» — подчиненный поток «Удалить график»
Рис. 4.11. Кооперативная диаграмма «Зарегистрироваться на курсы» — подчиненный поток «Принять график»
Каждая операция «анализа» класса соответствует некоторому сообщению, принимаемому объектами данного класса. В процессе проектирования каждая операция «анализа» преобразуется в одну или более операций класса, которые в дальнейшем будут реализованы в коде системы.
Так, диаграмма классов варианта использования «Зарегистрироваться на курсы» (см. рис. 4.6) после построения диаграмм взаимодействия должна принять следующий вид (рис. 4.12).
Рис. 4.12. Диаграмма классов с операциями «анализа»
При построении диаграмм взаимодействия возникают проблемы правильного распределения обязанностей между классами. Для их решения существует ряд образцов[26], некоторые из них приведены ниже.
Образец «Information Expert»
Проблема:
Нужно определить наиболее общий принцип распределения обязанностей между классами. В системе могут быть определены сотни классов, выполняющие тысячи обязанностей. При правильном их распределении система становится гораздо проще для понимания, сопровождения и развития. Кроме того, появляется возможность повторного использования уже разработанных компонентов в последующих приложениях.
Решение:
Следует назначить обязанность информационному эксперту — классу, у которого имеется информация, требуемая для выполнения обязанности.
Пример:
При выполнении подчиненного потока событий «Обновить график» варианта использования «Зарегистрироваться на курсы» (рис. 4.9) студент-пользователь должен получить доступ к своему графику прежде, чем изменить его. Согласно образцу «Information Expert», нужно определить, объект какого класса содержит информацию, необходимую для доступа к графику. На эту роль информационного эксперта, очевидно, претендует объект класса-сущности Student, поскольку график принадлежит именно ему. Поэтому сообщение 3 «get schedule(forSemester)» должно быть направлено от контроллера объекту класса Student. После того, как студент получит график и внесет в него необходимые изменения, они должны быть зафиксированы в объекте Schedule. В данном случае уже сам объект Schedule будет играть роль информационного эксперта, поскольку он непосредственно доступен контроллеру, и сообщение 10 «update with new selections» будет направлено именно ему.
Следствия:
При распределении обязанностей образец Information Expert используется гораздо чаще любого другого образца. Большинство сообщений на приведенных выше диаграммах взаимодействия соответствуют данному образцу. В нем определены основные принципы, которые уже давно используются в объектно-ориентированном анализе и проектировании. Образец Information Expert не содержит неясных или запутанных идей и отражает обычный интуитивно понятный подход. Он заключается в том, что объекты осуществляют действия, связанные с имеющейся у них информацией. Если информация распределена между различными объектами, то при выполнении общей задачи они должны взаимодействовать с помощью сообщений.
Образец Information Expert, как и многие другие понятия объектной технологии, имеет соответствующую аналогию в реальном мире. Например, в организации обязанности обычно распределяются между теми служащими, у которых имеется необходимая для выполнения поставленной задачи информация. Ответственность за создание отчета о прибыли и убытках должен нести тот из служащих, кто имеет доступ ко всей информации, необходимой для создания такого отчета. Возможно, лучше всего для выполнения этой обязанности подойдет руководитель финансового отдела предприятия. Программные объекты взаимодействуют между собой и обмениваются информацией так же, как люди. Начальник финансового отдела компании может запросить требуемые данные у бухгалтеров, работающих со счетами по дебиторской и кредиторской задолженности, чтобы составить отдельные отчеты по кредиту и дебету.
В некоторых ситуациях применение образца Information Expert нежелательно. Например, в системе регистрации нужно определить, какой объект должен отвечать за сохранение информации об учебных курсах в базе данных. Информация, подлежащая сохранению, «известна» объекту Course, а значит, согласно образцу Information Expert, на класс Course следует возложить обязанность по сохранению. Логическим следствием такого рассуждения является вывод о том, что каждый объект должен отвечать за сохранение себя в базе данных. Однако при этом возникает проблема перегруженности класса лишними обязанностями, поскольку класс Course должен содержать методы обращения к базе данных, т.е. должен быть связан с вызовом операторов языка SQL или сервисов JDBC (Java Database Connectivity). Тогда этот класс не будет относиться к предметной области и моделировать учебные курсы. Кроме того, подобные действия будут дублироваться во многих других классах, информация которых подлежит постоянному хранению.
Все эти проблемы приводят к нарушению основного архитектурного принципа проектирования с разделением основных функций системы на уровни, отраженного в образце «Уровни». Разнородные функции не должны реализовываться в одном и том же компоненте. С этой точки зрения класс Course не должен отвечать за сохранение информации в базе данных.
Основное достоинство образца Information Expert - поддержка инкапсуляции. Для выполнения требуемых задач объекты используют собственные данные. Необходимое поведение системы обеспечивается несколькими классами, содержащими требуемую информацию. Это приводит к определениям классов, которые гораздо проще понимать и поддерживать.
Образец «Creator»
Проблема:
Нужно определить, кто должен отвечать за создание нового экземпляра некоторого класса. Создание новых объектов в объектно-ориентированной системе является одним из стандартных видов деятельности. Следовательно, при назначении обязанностей, связанных с созданием объектов, полезно руководствоваться некоторым основным принципом.
Решение:
Следует назначить классу В обязанность создавать экземпляры класса А, если выполняется одно из следующих условий:
· класс В агрегирует, содержит или активно использует объекты класса А;
· класс В обладает данными инициализации, которые будут передаваться объектам класса А при их создании (т.е. класс В является информационным экспертом).
Класс В при этом определяется как создатель (creator) объектов класса А.
Если несколько классов удовлетворяют этим условиям, то предпочтительнее использовать в качестве создателя класс, агрегирующий или содержащий класс А.
Пример:
При выполнении подчиненного потока событий «Создать график» варианта использования «Зарегистрироваться на курсы» (см. рис. 4.8) необходимо решить, кто должен отвечать за создание нового графика в системе. На рисунке 4.13 показано два возможных варианта решения этой задачи.
Рис. 4.13. Два варианта создания графика
В диаграмме на рис. 4.8 выбран вариант 1. Однако согласно образцу «Creator» наилучшим решением является вариант 2 (новый объект класса Schedule создается классом Student, а не RegistrationController, поскольку именно Student удовлетворяет первому из перечисленных выше условий).
Следствия:
Образец «Creator» определяет способ распределения обязанностей, связанный с процессом создания объектов. В объектно-ориентированных системах эта задача является одной из наиболее распространенных. Основным назначением образца Creator является выявление объекта-создателя, который при возникновении любого события должен быть связан со всеми созданными им объектами. При таком подходе обеспечивается низкая степень связанности объектов.
В некоторых случаях в качестве создателя выбирается класс, который содержит данные инициализации, передаваемые объекту во время его создания. На самом деле это пример использования образца Information Expert. В процессе создания инициализирующие данные передаются с помощью метода инициализации некоторого вида, такого, как конструктор языка программирования.
В некоторых сложных случаях вместо данного образца предпочтительнее использовать известный образец Factory (Фабрика)[27] и делегировать обязанность создания объектов вспомогательному классу.
Образец «Low Coupling»
Проблема:
Нужно распределить обязанности между классами таким образом, чтобы снизить взаимное влияние изменений в них и повысить возможность повторного использования.
Решение:
Следует распределить обязанности таким образом, чтобы обеспечить слабую связанность. Связанность (coupling) — это мера, определяющая насколько жестко один элемент связан с другими элементами, или каким количеством данных о других элементах он обладает. Элемент со слабой связанностью зависит от небольшого числа других элементов. Класс с сильной связанностью зависит от множества других классов. Наличие таких классов нежелательно, поскольку оно приводит к возникновению следующих проблем.
· Изменения в связанных классах приводят к локальным изменениям в данном классе.
· Затрудняется понимание каждого класса в отдельности.
· Усложняется повторное использование, поскольку для этого требуется дополнительный анализ классов, с которыми связан данный класс.
Пример:
Рассмотрим подчиненный поток событий «Создать график» варианта использования «Зарегистрироваться на курсы» (см. рис. 4.8). На данной диаграмме при создании нового графика в системе выбран вариант 1 (рис. 4.13). Однако согласно образцу «Low Coupling» наилучшим решением является вариант 2, поскольку при этом у класса RegistrationController будет на одну связь меньше (т.е. будет обеспечена более слабая связанность).
Следствия:
Образец Low Coupling поддерживает независимость классов, что, в свою очередь, повышает возможности повторного использования и обеспечивает более высокую эффективность приложения. Его нельзя рассматривать изолированно от других образцов, таких как Information Expert и High Cohesion. Он также обеспечивает выполнение одного из основных принципов проектирования, применяемых при распределении обязанностей.
Не существует абсолютной меры для определения слишком сильной связанности. Важно лишь понимать связанность объектов и не упустить тот момент, когда дальнейшее повышение связанности может привести к возникновению проблем. В целом следует руководствоваться таким принципом: классы, которые являются достаточно общими по своей природе и с высокой вероятностью будут повторно использоваться в дальнейшем, должны иметь минимальную связанность с другими классами.
Крайним случаем при реализации образца Low Coupling является полное отсутствие связывания между классами. Такая ситуация тоже нежелательна, поскольку основная идея объектного подхода выражается в системе связанных объектов, которые «общаются» между собой посредством передачи сообщений. При слишком частом использовании принципа слабого связывания система будет состоять из нескольких изолированных сложных активных объектов, самостоятельно выполняющих все операции, и множества пассивных объектов, основная функция которых сводится к хранению данных. Поэтому при создании объектно-ориентированной системы должна присутствовать некоторая оптимальная степень связывания между объектами, позволяющая выполнять основные функции посредством взаимодействия этих объектов.
Не следует применять данный образец, когда создаются связи с устойчивыми элементами. Сильная связанность с такими элементами не представляет проблемы. Например, приложение Java 2 Enterprise Edition можно жестко связать с библиотеками Java, поскольку они достаточно стабильны.
Сильная связанность сама по себе не является проблемой. Проблемой является жесткое связывание с неустойчивыми элементами. Важно понимать, что без убедительной мотивации не следует во что бы то ни стало бороться за уменьшение связанности объектов.
Образец «High Cohesion»
Проблема:
Нужно распределить обязанности между классами таким образом, чтобы каждый класс не выполнял много разнородных функций или несвязанных между собой обязанностей. Такие классы создавать нежелательно, поскольку они приводят к возникновению таких же проблем, как у классов с сильной связанностью.
Решение:
Следует распределить обязанности таким образом, чтобы обеспечить сильное сцепление. В терминах объектно-ориентированного проектирования сцепление (cohesion) — это мера связанности и непротиворечивости обязанностей класса. Считается, что элемент обладает сильным сцеплением, если его обязанности тесно связаны между собой, и он не выполняет излишнего объема работы. В роли таких элементов могут выступать классы, подсистемы, модули и т.д.
Классы со слабым сцеплением, как правило, выполняют обязанности, которые можно легко распределить между другими классами.
Пример:
Используем тот же пример, что и для предыдущего образца (см. рис. 4.13). Согласно образцу «High Cohesion», наилучшим решением также является вариант 2, поскольку при этом класс RegistrationController делегирует обязанность создания нового объекта класса Shedule классу Student, и у самого класса RegistrationController будет на одну обязанность меньше (т.е. его сцепление будет сильнее).
Следствия:
Как правило, класс с сильным сцеплением содержит сравнительно небольшое число методов, которые функционально тесно связаны между собой, и не выполняет слишком много функций. Он взаимодействует с другими классами для выполнения более сложных задач. Высокая степень однотипной функциональности в сочетании с небольшим числом операций упрощают поддержку и модификацию класса, а также возможность его повторного использования.
Образец High Cohesion, как и другие понятия объектно-ориентированной технологии проектирования, имеет аналогию в реальном мире. Известно, что человек, выполняющий большое число разнородных обязанностей (особенно тех, которые можно легко распределить между другими людьми), работает не очень эффективно. Особенно это касается менеджеров, которые не умеют распределять обязанности между своими подчиненными.
Слабая связанность и сильное сцепление — основные принципы проектирования ПО. Объектное проектирование полностью с ними согласуется, поскольку одним из его базовых принципов является модульность.
Однако существуют ситуации, когда слабое сцепление оказывается оправданным. Одна из таких ситуаций возникает в том случае, когда обязанности или код группируются в одном классе или компоненте для упрощения его поддержки одним человеком. Другой пример слабого сцепления имеет отношение к распределенным серверным объектам. Поскольку быстродействие системы определяется производительностью удаленных объектов и их взаимодействием, иногда желательно создать несколько крупных серверных объектов со слабым сцеплением, предоставляющих интерфейс многим операциям. Это приведет к уменьшению числа удаленных вызовов и, как следствие, к повышению производительности.
Набор обязанностей классов, полученный в результате их распределения, должен быть проанализирован на предмет выявления и устранения следующих проблем:
· дублирования одинаковых обязанностей в различных классах;
· противоречивых обязанностей в рамках класса;
· классов с одной обязанностью или вообще без обязанностей;
· классов, взаимодействующих с большим количеством других классов.