Тема 6. объектно-ориентированный подход к проектированию
Сущность объектно-ориентированного подхода
В структурном подходе к разработке ИС, рассмотренном в теме 5, риск провала проекта остается большим на всех этапах создания системы вплоть до этапа тестирования, когда можно обнаружить допущенные ошибки. В случае обнаружения ошибки необходимо вернуться на тот этап разработки, на котором была допущена ошибка, и заново пройти последующие этапы.
Альтернативой структурному подходу стали объектно-ориентированные методы разработки ИС. Данные методы использует объектную декомпозицию. Структура системы описывается в терминах классов объектов и связей между ними. Поведение системы описывается в терминах обмена сообщениями между объектами. Снижение риска провала проекта в объектно-ориентированных методах разработки ИС достигается за счет реализации технологии итерационной (спиральной) разработки.
В первой половине 90-х годов был предложен разработанный на основе наиболее популярных объектно-ориентированных методов язык объектного моделирования UML (Unified Modeling Language - унифицированный язык моделирования). Нотация (синтаксис языка) UML включает ряд графических диаграмм.
Язык UML может использоваться в режиме эскиза, проектирования или языка программирования. В режиме эскиза разработчики используют UML для обмена информацией о различных аспектах системы. В режиме проектирования можно использовать эскизы при прямой и обратной разработке. При прямой разработке диаграммы рисуются до написания кода, а при обратной разработке диаграммы строятся на основании кода, с целью лучшего понимания кода. При использовании UML в режиме языка программирования диаграммы компилируются в исполняемый код, т.е. UML становится исходным кодом.
В данной теме будут рассмотрены основные понятия UML, достаточные для его начального использования в режиме эскиза.
Диаграммы UML
UML 2.0 описывает 13 официальных типов диаграмм, перечисленных в табл. 6.1. Классификация диаграмм приведена на рис. 6.1. Допустимо присутствие элементов диаграммы одного типа в другой диаграмме.
Таблица 6.1. Официальные типы диаграмм UML
№ | Диаграмма | Назначение диаграммы |
Классов | Описывает классы и статические отношения между ними | |
Последовательность | Описывает взаимодействие между объектами (акцент на последовательность) | |
Объектов | Показывает взаимосвязи между объектами | |
Пакетов | Объединяет классы в группы | |
Развертывания | Показывает, на каком физическом оборудовании запускается та или иная часть ПО | |
Прецедентов (использования) | Определяет функциональные требования к ПО | |
Состояний (конечных автоматов) | Показывает как события изменяют объект в течение его жизни | |
Деятельности | Описывает логику процедур, бизнес-процессов и потоков работ | |
Коопераций | Описывает взаимодействие между объектами (акцент на обмене данными) | |
Составных структур | Разбивает класс на составляющие | |
Компонентов | Структура и взаимосвязи между компонентами, т.е. элементами ПО, которые независимо друг от друга можно обновить или купить | |
Обзора взаимодействий | Комбинация диаграммы последовательности и диаграммы деятельности | |
Временная | Описывает взаимодействие между объектами (акцент на временных ограничениях) |
Далее будут рассмотрены основные элементы диаграмм прецедентов, классов, последовательностей, коммуникаций, состояний, деятельности и компонентов.
Рис. 6.1. Классификация диаграмм UML
Синтаксис и семантика основных объектов UML
Рассматриваются некоторые диаграммы языка объектного моделирования UML.
Диаграммы прецедентов
Диаграммы прецедентов описывают функциональность ИС, которая будет видна пользователям системы. Прецедент - это типичное взаимодействие пользователя с системой, которое при этом:
· описывает видимую пользователем функцию;
· может представлять различные уровни детализации;
· обеспечивает достижение конкретной цели, важной для пользователя.
Прецедент обозначается на диаграмме овалом, связанным с пользователями, которых принято называть действующими лицами или актерами. Действующее лицо выполняет некоторую роль в данном прецеденте. На диаграмме изображается только одно действующее лицо, однако реальных пользователей, выступающих в данной роли по отношению к ИС, может быть много. Список всех прецедентов фактически определяет функциональные требования к ИС, которые лежат в основе разработки технического задания на создание системы.
На диаграммах прецедентов, кроме связей между действующими лицами и прецедентами, используются связи между прецедентами. Наиболее часто эти связи имеют тип «использование» или «расширение» (рис. 6.2). Связь типа «расширение» применяется, когда один прецедент подобен другому, но несет несколько большую функциональную нагрузку. Ее следует применять при описании изменений в нормальном поведении системы. Связь типа «использование» позволяет выделить некий фрагмент поведения системы и включать его в различные прецеденты без повторного описания.
На рис. 6.2 показано, что при исполнении прецедента «Сформировать заказ» возможно использование информации из предыдущего заказа, что позволит не вводить все необходимые данные. А при исполнении прецедентов «Оценить риск сделки» и «Согласовать цену» необходимо выполнить одно и то же действие - рассчитать стоимость заказа.
Рис. 6.2. Связи на диаграммах прецедентов
Прецеденты представляют собой ценный инструмент для понимании функциональных требований к системе. Первый вариант прецедентов должен составляться на ранней стадии выполнения проекта. Более подробные версии прецедентов должны появляться непосредственно перед реализацией данного прецедента.
Важно помнить, что прецеденты представляют взгляд на систему со стороны. Поэтому соответствия между прецедентами и классами внутри системы может не быть.
Несмотря на то, что в языке UML ничего не говорится о тексте прецедентов, именно текстовое содержание прецедентов является основной ценностью этой технологии.
Большая опасность прецедентов заключается в том, что разработчики делают их очень сложными и застревают на них.
Диаграммы классов
Классы – это базовые элементы любой объектно-ориентированной системы. Классы представляют собой описание совокупностей однородных объектов с присущими им свойствами - атрибутами, операциями, отношениями и семантикой.
В рамках модели каждому классу присваивается уникальное имя, отличающее его от других классов. Если в начале имени добавляется имя пакета, куда входит класс (используется составное имя), то имя класса должно быть уникальным в пакете.
Атрибут класса – это свойство класса, которое может принимать множество значений. Атрибут имеет имя и отражает некоторое свойство моделируемой сущности, общее для всех объектов данного класса. Класс может иметь произвольное количество атрибутов.
Объект – экземпляр некоторого класса.
Операция – реализация функции, которую можно запросить у любого объекта класса. Операция показывает, что можно сделать с объектом. Исполнение операции часто связано с обработкой и изменением значений атрибутов объекта, а также изменением состояния объекта.
На рис. 6.3 приведено графическое изображение класса «Заказ» в нотации UML.
Рис. 6.3. Изображение класса в UML
Синтаксис UML для атрибутов классов может быть следующий: <признак видимости> <имя атрибутах [кратность атрибута]> :
<тип> = <значение по умолчанию>
Синтаксис UML для операций классов может быть следующий: <признак видимости> <имя операции> (<список аргументов>):
<тип возвращаемого значения>
Некоторые синтаксические единицы могут отсутствовать. В отдельных программных средствах, поддерживающих UML, порядок записи параметров может быть иным.
Признак видимости указывает на возможность использования атрибута или операции другими классами. В языке UML определены три уровня видимости:
· public (общий) - любой внешний класс, который «видит» данный класс, может пользоваться его общими свойствами (обозначение - символ «+» перед именем атрибута или операции);
· protected (защищенный) - только любой потомок данного класса может пользоваться его защищенными свойствами (обозначение - символ «#» перед именем атрибута или операции);
· private (закрытый) - только данный класс может пользоваться этими свойствами (обозначение - символ «-» перед именем атрибута или операции).
Кратность атрибута означает количество объектов заданного типа, которые могут заполнять данный атрибут. Чаще всего используются следующие кратности атрибута:
· 1 - один объект;
· 0.. 1 - один или ни одного объекта;
· *– количество объектов не ограничено.
Например, на рис. 6.4 изображен класс «Клиент». Атрибуты «Имя» и «Адрес» могут быть заполнены одним объектом string, а атрибут «Заказы» может быть заполнен неограниченным числом объектов «Заказ», т.е. клиент может сделать сколько угодно заказов. Если кратность атрибута не указана, то по умолчанию подразумевается кратность «1».
Рис. 6.4. Кратность атрибутов класса
Классы в UML изображаются на диаграммах классов. Данные диаграммы позволяют описать систему в статическом состоянии, т.е. позволяют определить классы системы и различные отношения между ними.
На рис. 6.4 представлена диаграмма классов, на которой определены два отношения: обобщение и ассоциация.
Обобщение - это отношение между общей сущностью (родителем) и ее конкретным воплощением (потомком). На диаграмме, представленной на рис.6.5, родителем является класс «Клиент», а потомками данного класса являются классы «Корпоративный клиент» и «Частный клиент».
При выполнении отношения «обобщение» объекты класса-потомка наследуют атрибуты и операции класса родителя. Наследование - это правило, согласно которому один объект может приобретать свойства другого.
Операция потомка с той же сигнатурой, что и у родителя, замещает операцию родителя, это свойство называют полиморфизмом.
Класс, у которого нет родителей, но есть потомки, называется корневым классом. Класс, у которого нет потомков, называется листовым классом.
Ассоциация - это отношение, показывающее, что объекты одного типа неким образом связаны с объектами другого типа, например, «Клиент» может сделать «Заказ» (см. рис. 6.5).
Рис. 6.5. Диаграмма классов
Ассоциации может быть присвоено имя, описывающее семантику отношений. Каждая ассоциация имеет две роли, которые могут быть отражены на диаграмме (рис. 6.6). Роль ассоциации обладает свойством множественности, которое показывает, сколько соответствующих объектов может участвовать в данной связи.
Рис. 6.6 иллюстрирует модель формирования заказа. Каждый заказ может быть создан единственным клиентом (множественность роли 1).
Рис.6.6. Двунаправленная ассоциация
Каждый клиент может сделать сколько угодно заказов (множественность роли*).
Отметим, что структура классов на рис.6.6 аналогична структуре на рис. 6.4. Однако, диаграмма классов, использующая ассоциации, более наглядна.
Ассоциация на рис.6.6 является двунаправленной. Такая ассоциация показывает, что пара атрибутов связана в противоположных направлениях. В рассмотренном примере класс «Клиент» имеет атрибут «Заказы[*]:3аказ», а класс «Заказ» имеет атрибут «Заказчик[1]:Клиент». Такое же обозначение ассоциации используется в том случае, когда направление не учитывается.
Если требуется подчеркнуть направление ассоциации, то конец линии на стороне класса, являющегося типом атрибута, отмечается стрелкой. Таким образом, для обозначения двунаправленной ассоциации можно использовать линию со стрелками на обеих концах.
Ассоциация может быть однонаправленной. Например, если в классе «Клиент» убрать атрибут «Заказы[*]:3аказ», то ассоциация между классами «Клиент» и «Заказ» будет изображена стрелкой, направленной от класса «Заказ» к классу «Клиент» (рис. 6.7).
Рис.6.7. Представление атрибута в виде ассоциации
Допускается задание ассоциаций на одном классе. В этом случае оба конца ассоциации относятся к одному и тому же классу. Это означает, что с объектом некоторого класса можно связать другие объекты из того же класса.
Диаграммы классов описывают структуру ПО и составляют фундамент UML. Однако нельзя сосредотачиваться исключительно на диаграммах классов. Помня о структуре, не следует забыть о поведении. Поэтому диаграммы классов используются совместно с различными диаграммами поведения. Далее будут рассмотрены следующие диаграммы поведения: последовательностей, коммуникаций, состояний, деятельности.