Построение диаграмм системных процессов и диаграмм последовательностей экранных форм

Результаты перехода от модели бизнес-процессов к модели системных процессов представлены на рис. 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, как и другие понятия объектно-ори­ентированной технологии проектирования, имеет аналогию в ре­альном мире. Известно, что человек, выполняющий большое число разнородных обязанностей (особенно тех, которые можно легко распределить между другими людьми), работает не очень эффективно. Особенно это касается менеджеров, которые не умеют распределять обязанности между своими подчиненными.

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

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

Набор обязанностей классов, полученный в результате их распределения, должен быть проанализирован на предмет выяв­ления и устранения следующих проблем:

· дублирования одинаковых обязанностей в различных классах;

· противоречивых обязанностей в рамках класса;

· классов с одной обязанностью или вообще без обязанностей;

· классов, взаимодействующих с большим количеством дру­гих классов.