Мы поможем в написании ваших работ!



ЗНАЕТЕ ЛИ ВЫ?

Разработка интерфейсов программных систем

Поиск

Интерфейсы, типы и роли

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

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

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

Почти все современные языки программирования, в том числе Java и CORBA IDL, поддерживают концепцию интерфейсов. Интерфейсы важны не только для отделения спецификации от реализации класса или компонента, но и для внешнего описания пакета или подсистемы в случае увеличения размеров системы. Графическое представление интерфейсов в языке UML показано на рис. 3.1. Такая нотация позволяет раздельно визуализировать описание абстракции и ее реализацию.

 

Рис. 3.1. Интерфейсы

 

Типом (Туре) называют стереотип класса, используемый для определения области значений объектов вместе с применимыми к ним операциями (но не методами). Роль (Role)-это поведение сущности в данном контексте. Графически интерфейс изображается в виде кружочка; в развернутой форме его можно представить как стереотипный класс, чтобы раскрыть операции и другие свойства. У любого интерфейса должно быть имя, отличающее его от остальных. Имя интерфейса представляет собой текстовую строку. Взятое само по себе, оно называется простым. Составное имя образуется путем добавления в его начало имени пакета, в который входит данный интерфейс. Имя интерфейса должно быть уникальным внутри объемлющего пакета. При изображении интерфейса можно ограничиться только его именем, как показано на рис. 3.2.

Рис. 3.2. Простые и составные имена

 

Имя интерфейса может состоять из любого числа букв, цифр и некоторых знаков препинания (за исключением таких, как двоеточия, которые применяются для отделения имени интерфейса от имени объемлющего пакета). Имя может занимать несколько строк. Обычно для именования интерфейсов используют одно или несколько коротких существительных, взятых из словаря моделируемой системы. Чтобы отличить интерфейс от класса, принято добавлять к его имени начальную букву I, например IUnknown или ISpelling. Те же правила применяются и к типам. Чтобы отличить тип от интерфейса или класса, принято начинать его имя с буквы Т, например TNatural или TCharacter.

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

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

 

Рис. 3.3. Операции

 

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

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

На языке UML вы можете связать с интерфейсом значительно больше информации, чтобы сделать его понятнее. Прежде всего, можно описать предусловия и постусловия для каждой операции, а также инварианты для класса или компонента в целом. Таким образом, клиент сумеет понять, что и как делает интерфейс, без необходимости изучать его реализацию. Если вы хотите формально описать семантику, воспользуйтесь языком OCL. Кроме того, к интерфейсу можно присоединить автомат и использовать его для специфицирования корректной частичной упорядоченности операций. Наконец, с ним допустимо связать кооперации, описывающие ожидаемое поведение интерфейса с помощью последовательности диаграмм взаимодействия.

Класс может реализовывать несколько интерфейсов. Любой экземпляр данного класса должен поддерживать их все, так как интерфейс определяет условия контракта, и все соответствующие ему абстракции обязаны соблюдать эти условия. Тем не менее, в конкретном контексте экземпляр может предоставлять только те интерфейсы, которые соответствуют ситуации. Это означает, что каждый интерфейс определяет роль, которую играет объект. Роль, таким образом, - это именованное поведение некоторой сущности в конкретном контексте, или, иными словами, - лицо, которым абстракция обращена к миру.

Рассмотрим, например, экземпляр класса Человек. В зависимости от контекста экземпляр этого класса может играть роль Матери, Налогоплательщика, Работника, Покупателя, Менеджера, Летчика, Певца и т.д. Следовательно, объект предъявляет миру ту или иную «личину», и взаимодействующие с ним клиенты ожидают от него соответствующего поведения. Например, экземпляр класса Человек в роли Менеджера обладает не таким набором свойств, какой был бы у него в роли Матери. На языке UML роль, которую одна абстракция играет по отношению к другой, можно описать, дополнив соответствующую концевую точку ассоциации именем интерфейса. Например, на рис. 3.4 показан интерфейс Работник, определение которого включает три операции.

 

Рис. 3.4. Роли

 

Между классами Человек и Компания существует ассоциация, в контексте которой Человек играет роль е, относящуюся к типу Работник. В другой ассоциации этот класс может быть «обращен к миру иным лицом». При наличии явного типа роль, которую играет Человек, - это не просто слово, понятное для читателя, изучающего диаграмму. В UML это означает, что класс Человек играет для класса Компания роль Работника, и в данном контексте для Компании будут видимы и существенны только свойства, определенные данной ролью. Диаграмма классов, подобная приведенной выше, полезна для моделирования статического связывания абстракции с ее интерфейсом.

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

В качестве примера на рис. 3.5 показаны роли, которые класс Человек может играть в контексте системы управления человеческими ресурсами.

 

Рис. 3.5. Моделирование статических типов

 

Из этой диаграммы явствует, что экземпляры класса Человек могут относиться к одному из трех типов - Кандидат, Работник и Пенсионер. Динамическая природа типа Человека изображена на рис. 3.6.

 

Рис. 3.6. Моделирование динамических типов

 

В этом фрагменте диаграммы взаимодействия объект р (Человек) меняет роль Кандидата на Работника.

Пакеты

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

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

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

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

Рис. 3.7. Пакеты

 

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

 

Рис. 3.8. Простой и расширенный пакеты

 

Но, как и в случае с классами, вы можете дополнять пакеты помеченными значениями или дополнительными разделами, чтобы показать детали. Имя пакета может состоять из любого числа букв, цифр и некоторых знаков препинания (за исключением таких, как двоеточия, которые применяются для отделения имени пакета от имени объемлющего пакета). Оно может занимать несколько строк. Обычно для именования пакетов используют одно или несколько коротких существительных, взятых из словаря модели. Пакет может владеть другими элементами, в том числе классами, интерфейсами, компонентами, узлами, кооперациями, диаграммами и даже другими пакетами. Владение - это композитное отношение, означающее, что элемент объявлен внутри пакета. Если пакет удаляется, то уничтожается и принадлежащий ему элемент. Элемент может принадлежать только одному пакету. Пакет определяет свое пространство имен; это значит, что элементы одного вида должны иметь имена, уникальные в контексте объемлющего пакета. Например, в одном пакете не может быть двух классов Queue, но может быть один класс Queue в пакете Р1, а другой - в пакете Р2.

Элементы различного вида могут иметь одинаковые имена в пределах пакета. Так, допустимо наличие класса Timer и компонента Timer. Однако на практике, во избежание недоразумений, лучше всем элементам давать уникальные имена в пакете. Пакету могут принадлежать другие пакеты, а значит, позволительно осуществить иерархическую декомпозицию модели. Лучше избегать слишком глубокой вложенности пакетов - два-три уровня являются пределом. В случае необходимости для организации пакетов стоит использовать импортирование, а не вложенность. Описанная семантика владения или принадлежности делает пакеты важным механизмом масштабирования системы. Без них пришлось бы создавать большие плоские модели, все элементы которой должны иметь уникальные имена. Такие конструкции были бы совершенно неуправляемы, особенно если входящие в модель классы и другие элементы созданы различными коллективами. Пакеты позволяют контролировать элементы системы, даже если они разрабатываются в разном темпе. Как показано на рис. 3.9, содержание пакета можно представить графически или в текстовом виде.

 

Рис. 3.9. Элементы, принадлежащие пакету

 

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

По умолчанию такие элементы являются открытыми, то есть видимы для всех элементов, содержащихся в любом пакете, импортирующем данный. Защищенные элементы видимы только для потомков, а закрытые вообще невидимы вне своего пакета. Видимость принадлежащих пакету элементов обозначается с помощью символа видимости перед именем этого элемента. Для открытых элементов используется символ + (плюс). Все открытые части пакета составляют его интерфейс. Для имен защищенных элементов используют символ # (диез), а для закрытых добавляют символ - (минус). Напомним, что защищенные элементы будут видны только для пакетов, наследующих данному, а закрытые вообще не видны вне пакета, в котором объявлены. Пакеты, связанные с некоторым пакетом отношениями зависимости со стереотипом friend, могут «видеть» все элементы данного пакета, независимо от объявленной для них видимости.

Предположим, у вас есть два класса одного уровня А и В, расположенных ря­дом друг с другом. А может «видеть» В и наоборот, то есть любой из них может зависеть от другого. Два таких класса составляют стандартную систему, и для них не надо задавать никаких пакетов. Допустим теперь, что у вас имеется несколько сотен равноправных классов. Размер «паутины» отношений, которую вы можете соткать между ними, не поддается воображению. Более того, столь огромную неорганизованную группу классов просто невозможно воспринять в ее целостности.

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

Упаковывая абстракции в семантически осмысленные блоки и контролируя доступ к ним с помощью импорта, вы можете управлять сложностью систем, насчитывающих множество абстракций. Фактически в рассмотренной ситуации применяются два стереотипа - import и access, - и оба они показывают, что исходный пакет имеет доступ к элементам целевого. Стереотип import добавляет содержимое целевого пакета в пространство имен исходного. Таким образом, возникает вероятность конфликта имен, которой необходимо избегать, если вы хотите, чтобы модель была хорошо оформлена. Стереотип access не изменяет пространство имен цели, поэтому содержащиеся в исходном пакете имена необходимо квалифицировать. Чаще используют стереотип import.

Экземпляры

Термины «экземпляр» и «объект» в большинстве случаев являются синонимами и часто бывают взаимозаменяемы. Экземпляром называется конкретная материализация абстракции, к которой может быть применен определенный набор операций и которая обладает состоянием для сохранения результатов этих операций. Экземпляры используют для моделирования конкретных сущностей реального мира, или прототипов. Почти все строительные блоки UML вовлечены в дихотомию «класс/объект». Например, бывают прецеденты и экземпляры прецедентов, узлы и экземпляры узлов, ассоциации и экземпляры ассоциаций и т.д.

Абстракция описывает идеальную суть предмета, экземпляр - его конкретную материализацию. Такое разделение на абстракцию и экземпляр обнаружится во всем, что вы моделируете. У одной абстракции может быть сколько угодно экземпляров. Для данного экземпляра всегда существует абстракция, определяющая характеристики, общие для всех подобных экземпляров. В языке UML можно представлять как абстракции, так и их экземпляры. Почти все строительные блоки этого языка, в особенности классы, узлы и прецеденты, могут быть промоделированы в терминах своей сущности или своей материализации. По большей части вы будете работать с ними как с абстракциями, но если захотите промоделировать конкретные реализации или прототипы, то придется иметь дело с экземплярами. Графическое представление экземпляров показано на рис. 3.10.

 

 

Рис. 3.10. Экземпляры

Экземпляром (Instance) называется конкретная материализация абстракции, к которой могут быть применены операции и которая может сохранять их результаты. Понятия «экземпляр» и «объект» практически синонимичны. Экземпляр изображают с подчеркнутым именем. Обычно объектом называют конкретную материализацию класса. Объекты - это экземпляры классов; можно сказать, что все объекты являются экземплярами, но не все экземпляры - объектами. Например, экземпляр ассоциации не является объектом; это просто экземпляр, также называемый связью. Впрочем, лишь самые дотошные создатели моделей обращают внимание на такие нюансы терминологии. Экземпляры не существуют сами по себе: они всегда связаны с абстракциями. На языке UML чаще всего моделируют экземпляры классов (называемые объектами), хотя бывают также экземпляры и других сущностей, таких как компоненты, узлы, прецеденты и ассоциации.

В UML экземпляр легко отличить от абстракции - для этого надо просто подчеркнуть его имя. Объект в общем случае занимает некоторое место в реальном или концептуальном мире, и им можно тем или иным способом манипулировать. Например, экземпляром узла обычно является компьютер, физически расположенный в некоем помещении; экземпляром компонента - файл, размещенный в том или ином каталоге; экземпляр записи о клиенте занимает какой-то объем в оперативной памяти компьютера. Экземпляр траектории полета самолета тоже являет собой нечто конкретное, поддающееся обработке математическими методами.

С помощью UML допустимо моделировать не только непосредственные физические экземпляры, но и менее конкретные сущности. Например, абстрактный класс по определению не может иметь непосредственных экземпляров. Разрешается, однако, моделировать косвенные экземпляры абстрактных классов, чтобы показать, как данный класс можно использовать в качестве прототипа. Строго говоря, такого объекта не существует, но с практической точки зрения он позволяет поименовать любой потенциальный экземпляр конкретного потомка этого абстрактного класса. То же самое относится и к интерфейсам. Хотя они по определению не могут иметь непосредственных экземпляров, можно смоделировать экземпляр-прототип интерфейса, который будет представлять один из потенциальных экземпляров конкретных классов, реализующих этот интерфейс. Моделируемые экземпляры помещают в диаграммы объектов, если надо показать их структурные детали, или в диаграммы взаимодействия и деятельности, если нужно визуализировать их участие в динамических ситуациях. Хотя обычно это не требуется, их можно включать и. в диаграммы классов, если надо явно показать отношения объекта и его абстракции.

Классификатор экземпляра обычно статичен. Например, если вы создадите экземпляр класса, то сам класс не будет изменяться в течение жизни объекта. Но при моделировании некоторых ситуаций, а также в некоторых языках программирования, есть возможность изменить абстракцию экземпляра. И тогда объект Гусеница способен стать объектом Бабочка. Это один и тот же объект, но реализующий различные абстракции. В процессе разработки могут возникнуть экземпляры, не связанные ни с каким классификатором и изображаемые как объекты с отсутствующими именами абстракций. Такие объекты-«сироты» можно вводить при моделировании очень неопределенного поведения, хотя в конце концов их все равно нужно будет связать с некоей абстракцией, если вы хотите приписать объекту определенную семантику (рис. 3.11).

 

Рис. 3.11. Экземпляры – именованные, анонимные, множественные и «сироты»

 

 

Каждый экземпляр должен обладать именем, отличающим его в данном контексте от остальных экземпляров. Обычно объект существует в контексте операции, компонента или узла. Имя - это текстовая строка, например t или myCustomer на том же рис. 3.11. Взятое само по себе, оно называется простым именем. Абстракция экземпляра может иметь как простое имя (скажем, Transaction), так и составное (Multimedia::AudioStream). Составное имя образуется, если к имени абстракции спереди добавить имя пакета, в котором она находится.

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

 

 

Рис. 3.12. Состояния объекта



Поделиться:


Последнее изменение этой страницы: 2017-02-08; просмотров: 641; Нарушение авторского права страницы; Мы поможем в написании вашей работы!

infopedia.su Все материалы представленные на сайте исключительно с целью ознакомления читателями и не преследуют коммерческих целей или нарушение авторских прав. Обратная связь - 3.21.244.34 (0.01 с.)