Джим Арлоу, Айла Нейштадт - UML 2 и Унифицированный процесс. Практический объектно-ориентированный анализ и проектирование (1037782), страница 103
Текст из файла (страница 103)
Дополнительные вопросы25.12.4. OclMessageOCLсообщения могут использоваться только в постусловиях.OCLсообщения могут использоваться только в постусловиях. Они позволяют делать следующее:•подтвердить отправку сообщения;•подтвердить возвращение сообщения;•получить возвращаемое значение сообщения;•вернуть коллекцию сообщений, отправленных объекту.В OCL каждый вызов операции или отправка сигнала – это экземплярOclMessage.
Он имеет набор операций, приведенный в табл. 25.17.Таблица 25.17Операция OclMessageСемантикаaMessage.isOperationCall() : BooleanВозвращает true, если сообщение представляет вызов операции.aMessage.isSignalSent() : BooleanВозвращает true, если сообщение представляет отправку сигнала.aMessage.hasReturned() : BooleanВозвращает true, если сообщение было вызовом операции, которая вернула значение.aMessage.result() : TВозвращает результат вызванной операции;T представляет тип возвращаемого значенияЕсть также две операции, применяемые к сообщениям. Они приведены в табл. 25.18.Таблица 25.18Оператор сообщения ИмяСемантикаanObject^aMessage()has sentВозвращает true, если aMessage() был отправлен в anObjectМожет использоваться только в постусловияхanObject^^aMessage()get messagesВозвращает Sequence сообщений aMessage(), посланных в anObjectЕсли сообщение имеет параметры, с операторами has sent (послан) и getmessages (получить сообщения) может использоваться специальныйсинтаксис.
Это позволяет задавать фактические параметры или только типы параметров. Синтаксис описан в табл. 25.19.Для изучения сообщений в OCL мы используем шаблон Observer (наблюдатель), полностью описанный в книге [Gamma 1].578Глава 25. Введение в OCLТаблица 25.19has sent с параметрамиСемантикаanObject^aMessage( 1, 2 )Возвращает true, если aMessage(...) послано в anObject с параметрами, имеющими значения 1 и 2.anObject^aMessage( ?:Integer,?:Integer )Возвращает true, если aMessage(...) послано в anObject с параметрами типа Integer.get messages с параметрами СемантикаanObject^^aMessage( 1, 2 )Возвращает Sequence всех сообщений, посланных вanObject с параметрами, имеющими значения 1 и 2.anObject^^aMessage( ?:Integer, Возвращает Sequence всех сообщений, посланных?:Integer )в anObject с параметрами типа Integer.Простой пример применения шаблона Observer показан на рис. 25.24.Семантика этого шаблона проста: субъект (Subject) имеет нуль или более наблюдателей (Observer).
При изменении Subject вызывается его операция notify() (уведомить), которая в свою очередь вызывает операциюupdate() (обновить) каждого прикрепленного к ней Observer. Примеромобычного использования этого шаблона может быть обновление экрана при изменении базовых бизнесобъектов.Subject+attach( o : Observer )+detach( o : Observer )+notify()Observer0..*subjects0..*observers+attach( s : Subject )+detach( s : Subject )+update( s : Subject )Рис. 25.24. Пример применения шаблона ObserverСемантика операций Subject представлена в табл.
25.20.Таблица 25.20Операция SubjectСемантикаattach( o : Observer )Присоединяет объект Observer.detach( o : Observer )Отсоединяет объект Observer.notify()Вызывает операцию update() каждого объекта Observer –вызывается, когда Subject меняется и желает уведомитьобъекты Observer об этом изменении.Рассмотрим возможные постусловия для операций Subject, которыемогут использовать сообщения.Согласно табл. 25.20 постусловие Subject::notify() состоит в том, что Observer::update() был вызван для каждого присоединенного Observer.
Наязыке OCL это может быть выражено следующим образом:context Subject::notify( )25.13. Что мы узнали579post: каждый наблюдатель должен быть уведомлен через вызов update()self.observers.forAll( observer | observer^update() )В данном постусловии происходит перебор всех observers в Set и проверка получения ими сообщения update(). Оператор ^ – это оператор «hassent». Он возвращает true, если указанное сообщение было посланооперацией.
Он может использоваться только в постусловиях.Если сообщение синхронное (вы знаете, что оно вернется), можно проверять возвращаемое значение сообщения:context Subject::notify( )post: возвращаемое значение update( ) должно быть true для каждого наблюдателяself.observers.forAll( observer |observer^update().hasReturned() impliesobserver^update().result())25.13. Что мы узналиВ этом введении в OCL мы узнали следующее:• OCL – стандартное расширение UML.
Он может:• определять запросы;• определять ограничения;• определять тело операции запроса;• определять бизнесправила во время разработки модели.• OCL не язык действий для UML. Он не может:• менять значения элемента модели;• определять тело операции (кроме операций запроса);• выполнять операции (кроме операций запроса);• динамически определять бизнесправила.• OCLвыражения.• Состоят из:• контекста пакета (необязательно) – определяет пространствоимен для OCLвыражения;• контекста выражения (обязательно) – определяет экземплярконтекста для выражения;• одного или более выражений.• Контекст выражения может быть определен явно или путем размещения OCLвыражения в примечании к элементу модели.580Глава 25.
Введение в OCL••Экземпляр контекста – образец экземпляра контекста выражения:• OCLвыражения записываются в рамках экземпляра контекста.Типы OCLвыражений.• inv: – инвариант:• применяется к классификаторам;• экземпляр контекста – экземпляр классификатора;• инвариант должен быть true для всех экземпляров классификатора.• pre: – предусловие операции:• применяется к операциям;• экземпляр контекста – экземпляр классификатора, которомупринадлежит операция;• предусловие должно выполняться для обеспечения возможности выполнения операции.• post: – постусловие операции:• применяется к операциям;• экземпляр контекста – экземпляр классификатора, которомупринадлежит операция;• постусловие должно быть истинным после выполнения операции;• ключевое слово result обозначает результат операции;• feature@pre возвращает значение свойства (feature) до выполнения операции:• @pre может использоваться только в постусловиях;• OclMessage может использоваться только в постусловиях.• body: – определяет тело операции:• применяется к операциям запроса;• экземпляр контекста – экземпляр классификатора, которомупринадлежит операция.• init: – задает начальное значение:• применяется к атрибутам или концам ассоциаций;• экземпляр контекста – атрибут или конец ассоциации.• def: – добавляет атрибуты и операции в классификатор с помощью стереотипа «OclHelper»:• применяется к классификатору;• экземпляр контекста – экземпляр классификатора;• добавляет атрибуты и операции в классификатор с помощьюстереотипа «OclHelper»:• может использоваться только в OCLвыражениях.25.13.
Что мы узнали••••581let – определяет локальную переменную:• применяется к OCLвыражению;• экземпляр контекста OCLвыражения.• derive: – определяет производное значение:• применяется к атрибутам или концам ассоциаций;• экземпляр контекста – экземпляр классификатора, которомупринадлежит операция.Комментарии:• /* многострочные */• однострочныеСтаршинство операций:• ::• @pre• .• >• not ^ ^^• */• +• if then else endif• > < <= >=• = <>• and or xor• impliesСистема типов OCL.• OclAny:• супертип всех типов OCL и типов UMLмодели.• OclType:• подкласс OclAny;• перечисление всех типов ассоциированной UMLмодели.• OclState:• подкласс OclAny;• перечисление всех состояний ассоциированной UMLмодели.• OclVoid:• тип «null» в OCL – имеет единственный экземпляр под названием OclUndefined.• OclMessage – используется для:• подтверждения отправки сообщения;582Глава 25.
Введение в OCL••••••• подтверждения возвращения сообщения;• получения возвращаемого значения сообщения;• возвращения коллекции сообщений, отправленных объекту.• Примитивные типы OCL:• Boolean;• Integer;• Real;• String.• Tuples – структурированный тип:• Tuple { имяЧасти1:типЧасти1 = значение1, имяЧасти2:типЧасти2 = значение2, ... }Инфиксные операторы – для их добавления в типы UML просто определяется операция с соответствующей сигнатурой, например=(параметр) : Boolean.Коллекции:• Set – { unordered, unique } (применяется по умолчанию)• OrderedSet – { ordered, unique }• Bag – { unordered, nonunique }• Sequence – { ordered, nonunique }Операции над коллекциями должны инициироваться с помощьюоператора –>.Итерационные операции:• коллекция–> <операцияИтератора>(<переменнаяИтератора>:<Тип> | <выражениеИтератора>);• <переменнаяИтератора> и <Тип> необязательны.Навигация в рамках экземпляра контекста:• self – организует доступ к экземпляру контекста;• оператор «точка» – организует доступ к возможностям экземпляра контекста.Навигация по ассоциациям:• self – организует доступ к экземпляру контекста;• имя роли – обозначает объект или набор объектов на конце ассоциации;• оператор «точка» – перегружен:• self.roleName:• кратность 1 – обеспечивается доступ к объекту на концеассоциации;• кратность >1 – обеспечивается доступ к коллекции на конце ассоциации;25.13.