Дж. Арлоу, А. Нейштадт - UML 2 и Унифицированный процесс - Практический объектно-ориентированный анализ и проектирование, страница 100
Описание файла
PDF-файл из архива "Дж. Арлоу, А. Нейштадт - UML 2 и Унифицированный процесс - Практический объектно-ориентированный анализ и проектирование", который расположен в категории "". Всё это находится в предмете "объектно-ориентированный анализ и проектирование" из 7 семестр, которые можно найти в файловом архиве МГУ им. Ломоносова. Не смотря на прямую связь этого архива с МГУ им. Ломоносова, его также можно найти и в других разделах. .
Просмотр PDF-файла онлайн
Текст 100 страницы из PDF
е. всех экземпляров его подклассов).context BankAccountinv balanceValue: баланс BankAccount должен быть >1000.0self.balance >= (1000.0)Этот инвариант наследуется двумя подклассами: CheckingAccount и DepositAccount. Для обеспечения сохранения принципа замещаемости(раздел 10.2) подклассы могут усилить инвариант, но ни в коем случае не ослабить его.Подкласс может усилить инвариант, но не ослабить его.Правила 1 и 2 могут быть выражены как инварианты класса CheckingAccount:context CheckingAccountinv balanceValue: превышение кредита на CheckingAccount не должно быть больше установленного ограниченияself.balance >= (overdraftLimit)inv maximumOverdraftLimit: превышение кредита на CheckingAccount не должно быть больше 1000.0self.overdraftLimit <= 1000.0Правило 3 может быть выражено как инвариант класса DepositAccount:context DepositAccountinv balanceValue: баланс DepositAccount должен быть нулевым или положительнымself.balance >= 0.025.10.
Подробно о типах OCLBвыражений561Обратите внимание, как оба этих класса, переопределив инварианткласса BankAccount::balance, усилили его.Ограничение, касающееся уникальности accountNumber каждого счета,можно представить как инвариант класса BankAccount:context BankAccountinv uniqueAccountNumber: у каждого BankAccount должен быть уникальный accountNumberBankAccount::allInstances( )>isUnique( account | account.accountNumber )Из рис. 25.13 видно, что у каждого BankAccount есть единственный владелец (owner) и один или более операторов (operator). Владелец – это человек (Person), которому принадлежит счет, а операторы – это люди(People), имеющие право снимать деньги и имеющие доступ к информации счета.
Существует бизнесограничение о том, что owner долженбыть также и operator. Данное ограничение может быть отражено следующим образом:context BankAccountinv ownerIsOperator: владельцем BankAccount должен быть один из его операторовself.operators>includes( self.owner )Для Person можно записать такое ограничение:context Personinv ownedAccountsSubsetOfOperatedAccounts: счета, принадлежащие Person (ownedAccount), должны быть подмножеством счетов, управляемых этим Person (operatedAccount)self.operatedAccounts>includesAll( self.ownedAccounts )При сравнении объектов в OCLвыражениях необходимо помнить, чтоони могут быть:••идентичные – каждый объект ссылается на одну и ту же область памяти (имеют идентичные объектные ссылки);эквивалентные – каждый объект имеет одинаковый набор значений атрибутов, но разные объектные ссылки.В приведенных выше OCLвыражениях мы всегда аккуратны присравнении объектов на основании их идентичности или эквивалентности соответственно.
С этим надо проявлять осторожность. Например,сравнение объектов BankAccount (сравнение на основании идентичности) не то же самое, что сравнение accountNumber этих объектов (сравнение на основании эквивалентности).25.10.2. pre:, post: и @preПредусловия и постусловия применяются к операциям. Их экземпляром контекста является экземпляр классификатора, которому принадлежат эти операции.562Глава 25. Введение в OCLpre: и post: применяются к операциям.•Предусловия определяют сущности, которые должны быть истинны перед выполнением операции.•Постусловия определяют сущности, которые должны быть истинны после выполнения операции.Вернемся к нашему примеру BankAccount на рис. 25.13 и рассмотримоперацию deposit(...), унаследованную обоими подклассами, CheckingAccount и DepositAccount, от BankAccount.
Установлено два бизнесправила.1. Сумма (amount) вклада должна быть больше нуля.2. После выполнения операции сумма должна быть добавлена в баланс (balance).Эти правила могут быть выражены кратко и точно в виде предусловийи постусловий операции BankAccount::deposit(...):context BankAccount::deposit( amount : Real ) : Realpre amountToDepositGreaterThanZero: сумма вклада должна быть больше нуляamount >0post depositSucceeded: окончательный баланс должен быть суммой исходного баланса и вкладаself.balance = self.balance@pre + amountПредусловие amountToDepositGreaterThanZero (сумма вклада больше нуля)должно быть истинным, чтобы обеспечить возможность выполненияоперации.
Оно гарантирует:•невозможность нулевых вкладов;•невозможность вкладов с отрицательным значением суммы.Постусловие depositSucceeded (вклад сделан успешно) должно быть trueпосле выполнения операции. Оно определяет увеличение исходногобаланса (balance@pre) на сумму вклада (amount) для получения окончательного баланса.attributeName@pre ссылается на значение перед выполнением операции.Обратите внимание на ключевое слово @pre.
Оно может использоваться только в постусловиях. Атрибут balance принимает одно значениедо выполнения операции и другое значение после ее выполнения. Выражение balance@pre ссылается на значение balance перед выполнениемоперации. Часто в постусловии необходимо сослаться на исходное значение чеголибо.Для полноты информации приводим ограничения, налагаемые на операцию BankAccount::withdraw(...).25.10.
Подробно о типах OCLBвыражений563context BankAccount::withdraw( amount : Real )pre amountToWithdrawGreaterThanZero: снимаемая сумма должна быть больше нуляamount >0post withdrawalSucceeded: окончательный баланс – это разность исходного баланса и снятой суммыself.balance = self.balance@preamountПрежде чем завершить обсуждение предусловий и постусловий, необходимо рассмотреть наследование. Когда подкласс переопределяетоперацию, он принимает предусловия и постусловия переопределяемой операции.
Он может только изменить их.• Переопределенная операция может только ослабить предусловие.• Переопределенная операция может только усилить постусловие.Эти ограничения гарантируют сохранение принципа замещаемости(раздел 10.2).25.10.3. body:OCL можно использовать для определения результата операции запроса.Все операции getXXX() в нашей простой модели BankAccount (рис.
25.13)являются операциями запроса.BankAccount::getBalance( ) : RealBankAccount::getOwner() : PersonBankAccount::getOperators() : Set( Person )CheckingAccount::getAvailableBalance() : RealCheckingAccount::getAvailableOverdraft() : RealOCLвыражения для операций запроса BankAccount тривиальны, и обычно их написание не должно вызывать затруднений.
Выражения приведены ниже в качестве примера:context BankAccount::getBalance( ) : Realbody:self.balancecontext BankAccount::getOwner( ) : Personbody:self.ownercontext BankAccount::getOperators() : Set(Person)body:self.operatorsОперации запроса класса CheckingAccount более интересны:context CheckingAccount::getAvailableBalance() : Realbody: можно снимать сумму, не превышающую ограничения по превышению кредитаself.balance + self.overdraftLimit564Глава 25. Введение в OCLcontext CheckingAccount::getAvailableOverdraft() : Realbody:if self.balance >= 0 then возможность превышения кредита доступна полностьюself.overdraftLimitelse возможность превышения кредита использована частичноself.balance + self.overdraftLimitendifКак видите, в этих двух операциях запроса OCL определяет, как вычисляется результат операции.
Возвращаемое значение операции –это результат вычисления OCLвыражения.25.10.4. init:OCL может использоваться для задания начального значения атрибутов. Например:context BankAccount::balanceinit:0Обычно эта возможность OCL используется в случае сложности инициализации.
Простые инициализации (как та, что приведена выше) лучшевсего размещать прямо в ячейке атрибутов класса.25.10.5. def:OCL позволяет добавлять атрибуты и операции в классификатор с помощью стереотипа «OclHelper». Они могут использоваться тольков OCLвыражениях. Добавленные атрибуты в OCL называют переменными.
Их применение во многом аналогично использованию переменных в других языках программирования. Добавленные операции называются вспомогательными операциями, потому что они «помогают»в OCLвыражениях.def: позволяет определить переменные и вспомогательные операцииклассификатора для использования в других OCLвыражениях.Переменные и вспомогательные операции используются для упрощения OCLвыражений.Рассмотрим пример.
Возьмем ограничения, определенные ранее:context CheckingAccount::getAvailableBalance() : Realbody: можно снимать сумму, не превышающую ограничения превышения кредитаbalance + overdraftLimitcontext CheckingAccount::getAvailableOverdraft() : Real25.10. Подробно о типах OCLBвыражений565body:if balance >= 0 then возможность превышения кредита доступна полностьюoverdraftLimitelse возможность превышения кредита использована частичноbalance + overdraftLimitendifМожно заметить, что операция balance + overdraftLimit присутствуетв двух выражениях. Поэтому есть смысл определить ее один раз какпеременную availableOverdraft (доступное превышение кредита), котораяможет использоваться обоими выражениями.
Для этого применяетсяоператор def:.context CheckingAccountdef:availableBalance = balance + overdraftLimitТеперь можно переписать эти два ограничения, используя введеннуюпеременную:context CheckingAccount::getAvailableBalance() : Realbody: можно снимать сумму, не превышающую ограничения превышения кредитаavailableBalancecontext CheckingAccount::getAvailableOverdraft() : Realbody:if balance >= 0 then возможность превышения кредита доступна полностьюoverdraftLimitelse возможность превышения кредита использована частичноavailableBalanceendifМожно также определить вспомогательные операции.