Дж. Рамбо, М. Блаха - UML 2.0 - Объектно-ориентированное моделирование и разработка (1158633), страница 81
Текст из файла (страница 81)
Ускорить эту операцию помогла бы выводимая ассоциация между Валя (Банк) и Прадасе (Обновление). 15.7.2. Изменение порядка выполнения для повышения эффективности После корректирования структуры модели классов для сокращения частого прослеживания связей можно приступать к оптимизации алгоритмов.
Одним из принципов оптимизации алгоритмов является раннее исключение не дающих результата путей из поиска. Предположим, что вам нужно найти всех сотрудников, умеющих разговаривать на японском и французском языках. Предположим, что на японском разговаривают 5 сотрудников, а на французском — 100. Тогда лучше сначала найти тех, кто разговаривает на японском, а потом проверить, говорит ли кто-нибудь из них на французском. Лучше сокращать область поиска как можно раньше. Иногда приходится изменять порядок вложенности циклов на противоположный относительно исходной спецификации.
Пример с банкоматом. Законодательство США требует от банков сообщать не только об отдельных операциях с суммами более 10 000 долларов наличными, но и о «подозрительных» операциях, которые могут быть попытками обойти ограничение. Например, две операции снятия 5000 долларов, сделанные одна сразу после другой, могут считаться подозрительными. 15.7.
Оптимизация проекта 339 Предположим, что мы не только проверяем операции с большими суммами, но и по-разному подходим к физическим и юридическим лицам. Допустим, что банк меньше доверяет физическим лицам, и установил для них более низкий порог «подозрительности» операций. Все подозрительные экземпляры класса Урссасе (Обновление) можно получить через выводимую ассоциацию (мы должны написать «подозрительная» вместо «более 10 000 долларов» для выводимой ассоциации из раздела 15.7.1), а затем выполнить прослеживание обратно к классу Ассоипс (Счет), чтобы разделить счета физических и юридических лиц.
Затем можно изучить полученные операции и определить, о каких нужно доложить куда следует. Альтернативное решение состоит в том, чтобы добавить в модель две различные выводимые ассоциации между классами Вапсс (Банк) и Урс(асе (Обновление); одна для физических лиц, а другая — для юридических. Тогда обратное прослеживание к классу Ассоипс (Счет) не потребуется. 15.7.3. Сохранение промежуточных результатов Иногда бывает полезно определить новые классы для кэширования выводимых атрибутов во избежание повторных вычислений. Кэш нужно обновлять в случае изменения любого из объектов, от которых он зависит. Существует три метода обработки таких изменений.
° Явное обновление. Проектировщик добавляет в операцию обновления исходного атрибута код, явным образом обновляющий значения выводимых атрибутов, связанных с данным атрибутом. ° Периодическое вычисление. В реальных приложениях значения часто изменяются группами. Вы можете реализовать периодическое вычисление всех выводимых атрибутов вместо обновления отдельных атрибутов при каждом изменении значений исходных атрибутов.
Периодическое вычисление проще реализовать, чем явное обновление, а потому его реализация меньше подвержена ошибкам. С другой стороны, если данные изменяются последовательно в небольшом количестве объектов, полное периодическое вычисление может быть просто неэффективным.
° Активные значения. Активным (асвте ча1це) называется значение, которое автоматически поддерживается в согласованном состоянии со значениями исходных атрибутов. Специальный механизм регистрации контролирует зависимости выводимых атрибутов от исходных атрибутов. Этот механизм отслеживает значения исходных атрибутов и обновляет значения выводимых атрибутов при любых изменениях первых. Подобные механизмы для работы с активными значениями предоставляются некоторыми языками программирования.
Пример с банкоматом. Мы можем добавить в модель класс ВизрсссоизУрс7асеСгоир (ГруппаПодозрительныхобновлений). Экземпляр этого класса может содержать несколько экземпляров Урссасе (Обновление), а экземпляр Гримасе может принадлежать нескольким ВизрсссоизУрссасебгоир. В новом классе будут храниться выводимые атрибуты, упрощающие контроль подозрительного поведения. 340 Глава 15 ° Проектирование классов Там же удобно хранить замечания и наблюдения. Экземпляр 5иялс1оизУрЫагеСгоир будет множеством экземпляров УрНаге, которые были заподозрены в попытке обойти ограничение в 10 000 долларов.
15.8. Воплощение поведения Зашитое в коде поведение неизбежно утрачивает гибкость. Его можно выполнять, но нельзя изменять во время выполнения программы. В большинстве случаев этого достаточно, потому что чаше всего ваши потребности будут сводиться именно к выполнению поведения. Однако если вам нужно сохранять, передавать или изменять поведение во время выполнения программы, необходимо прибегнуть к методу воплощения поведения (герйсаг1оп).
Воплощение — это превращение в объект сущности, изначально объектом не являвшейся. Поведение обычно соответствует этому описанию. Обычно поведение не относится к тому, чем вы можете манипулировать. Если вы воплотите поведение, вы сможете сохранять его, передавать другим операциям и модифицировать. Воплощение усложняет систему, но позволяет сделать ее значительно более гибкой. Чтобы воплотить поведение, нужно закодировать его в объект, а во время выполнения — декодировать. Правда, это может создать значительную дополнительную нагрузку на систему (а может и не создать).
Если кодирование вызывает процедуры высшего уровня, все расходы сведутся к нескольким лишним ссылкам. Если же все поведение кодируется на другом языке, его приходится интерпретировать, что на порядок медленнее выполнения компилированного кода. Если время выполнения закодированного поведения составляет незначительную часть общего времени выполнения системы, накладные расходы на кодирование можно считать несущественными.
Воплощение рассматривается в упражнении 4.16 (глава 4). Там говорится о том, что рецепт какого-либо блюда можно рассматривать как последовательность операций или как данные в модели классов. В работе [Оапипа-951 перечисляются несколько образцов (рагсегпз), позволяющих воплотить поведение. К ним относится кодирование конечного автомата в виде таблицы с интерпретатором времени выполнения (образец 5гаге), кодирование последовательности запросов в виде параметризованных объектов команд (образец Саттона), параметризация процедуры в терминах используемой ею операции (образец 5ггагеяу). Эти методы бгяли придуманы уже давно, но язык образцов удобен для их описания и для оценки их преимушеств и недостатков. Например, образец 5ггаге1Э использовался во времена языка ЕОВТВАХ для таких целей, как передача функции подпрограмме интегрирования.
В этом языке не было способов гарантировать точное соответствие переданной функции определенным требованиям, поэтому программист легко мог допустить ошибку. Кодируя передаваемую функцию в виде экземпляра класса функций, вы получаете одновременно возможность расширения, обеспечиваемую полиморфизмом, и в то же время можете задавать сигнатуры целого семейства функций. В этом примере объектно-ориентированная технология позволяет сделать решение более ясным по сравнению с более ранними технологиями. 15.9. Корректировка иерархии наследования 341 Пример с банкоматом. Мы уже использовали воплощение в нашем примере.
Транзакцию можно рассматривать как действие: снятие денег, взнос или трансфер. Мы сделали транзакцию классом, чтобы иметь возможность описывать ее. Функциональность, которая нам нужна, легко может быть получена прослеживанием модели классов. 15.9. Корректировка иерархии наследования Осуществляя проектирование классов, вы можете корректировать определения классов и операций в целях улучшения согласованности иерархии наследования.
Для этого есть несколько методов: ° реорганизация классов и операций; ° абстрагирование общего поведения из групп классов; ° использование делегирования для совместного использования поведения в тех случаях, когда наследование неприемлемо по семантическим соображениям. 15.9.1. Реорганизация классов и операций Иногда несколько классов определяют одинаковое поведение, так что легко обеспечить наследование этого поведения от общего предка, но чаше всего операции в разных классах являются лишь похожими, но не идентичными. Корректируя определения этих операций, вы можете свести схему к наследованию от одной операции. Перед тем как прибегать к наследованию, нужно обеспечить соответствие операций. Все операции должны иметь одинаковую сигнатуру, то есть одинаковое количество и тнп аргументов и результатов.
Кроме того, операции должны иметь одинаковую семантику. Чтобы сделать наследование более удобным, вы можете использовать следующие приемы. ° Операции с необязательными аргументами. Можно добиться согласованности сигнатур, добавив к операции необязательные аргументы. Например, операция с6аго для черно-белого дисплея не требует указания цвета, но она может принимать этот параметр и игнорировать его для обеспечения согласованности с цветными дисплеями.