Дж. Рамбо, М. Блаха - UML 2.0 - Объектно-ориентированное моделирование и разработка (1158633), страница 79
Текст из файла (страница 79)
Как выбрать класс, к которому должна быть отнесена операция? Если в операции участвует только один объект, решение будет простым: нужно запросить выполнение операции у этого объекта или приказать ему выполнить ее. Если же объектов несколько, решение усложняется. Вы должны определить объект, играюший в этой операции главную роль.
Задайте себе следуюшие вопросы. ° Получатель действия. Есть лн такой объект, над которым выполняют операцию все остальные объекты? В большинстве случаев лучше связывать операцию с ее целью, а не с инициаторами. ° Запрос или обновление. Есть ли такой объект, который изменяется в ходе выполнения операции, тогда как другие объекты лишь сообшают сведения о своем состоянии? Изменяющийся объект и является целью данной операции. ° Центральный класс. Какой класс находится ближе всего к центру графа всех участвующих в операции классов и ассоциаций? Если классы и ассоциации образуют звезду вокруг одного центрального класса, этот класс является целью операции. ° Аналогия с реальным миром.
Если бы объекты существовали не в программе, а в реальном мире, какой объект вы бы толкали, перемещали или активировали, чтобы выполнить операцию? Иногда бывает трудно назначить операцию какому-либо классу, оставаясь в рамках иерархии обобщения. Операции часто приходится перемещать вверх и вниз по этой иерархии в процессе проектирования, по мере уточнения их границ.
Более того, определения самих подклассов иерархии тоже часто требуют корректировки. ззг Глава 15 ° Проектирование классов Пример с банкоматом. Рассмотрим операции варианта использования ргосет сгапзасссоп (обработка транзакции) из раздела 15.3 и попробуем назначить их различным классам. СийотекдесАтоипсΠ— получение суммы транзакции от клиента. Значение ащоппг будет храниться как атрибут объектов Урс(асе (Обновление), но мы предполагаем, что эти объекты недоступны в момент ввода суммы транзакции и создаются лишь после проведения ряда проверок. Мы будем хранить значение суммы транзакции во временном атрибуте. Ассоипг.пеп)уАтоипС(атоипС) — проверка наличия запрошенной суммы на балансе.
° ВапЬ.оег1)уАтоипс(атоипс) — проверка соответствия суммы политике банка. АТМ.оеп)уАтоипс(атоипс) — проверка наличия достаточного количества купюр в банкомате. Обратите внимание, что в нашей модели имеется несколько методов чег1(уАшонпц принадлежащих разным классам. Это удобный способ организации модели. Все методы должны иметь одинаковую сигнатуру. А ТМ.с11хЬигзерипс)з(атоипс) — выдача наличных.
АссоипЫеЬ1С(атоипС) — уменьшение суммы на банковском счете. Яесе1рг.розСТгапзасг1опΠ— печать данных о транзакции на чеке клиента. Вам может показаться, что нам следовало связать классы Сизсотег (Клиент) и Яесесрс (Чек), но модель получится более точной, если вместо этого мы свяжем классы СазЬСагс1 (БанковскаяКарта) и Яесесрс (Чек). При прослеживании модели одна банковская карта подразумевает одного клиента, но благодаря связи СазЬСагс1 и Весесрс мы можем проследить, какие экземпляры Сап1Аисйопсабоп (КартаАвторизации) и СазЬСагс1 (БанковскаяКарта)использовались во время конкретного сеанса. А ТМ.тесе1перипс1з(атоипс) — получение конверта с деньгами от клиента. Не совсем очевидно, к какому классу следует отнести этот метод. Мы могли бы назначить его классам АТМ или Сизсотег.
Мы решили назначить его классу АТМ, чтобы обеспечить симметрию с операцией АТМ. с)1зопгзерппссз. Печать штемпеля на конверте мы включили в операцию получения конверта. Ассоипс.стес)1с(атоипс) — увеличение суммы на банковском счете. СизсотегдесАссоипсΠ— эта операция подразумевает получение как исходного, так и целевого счетов.
Метод должен удовлетворять неявному ограничению: одному клиенту может принадлежать несколько счетов, и он обязан указывать только те счета, которые принадлежат лично ему. Обычно пользовательский интерфейс обеспечивает выполнение этого ограничения, потому что пользователю предоставляются для выбора только его собственные счета. 15.5.
Рекурсия вниз 333 На рис. 15А показана модель классов банкомата из главы 13 с добавленными в этом разделе операциями. ЕпузгебОп Тгапзасдоп * дагеТ|ве 1 ЕпауЗагдеп Аи!ПопхебВу Тгапазсг!оп * СазЫег Тгапаасдоп (о!де!од) * Црда1е Саащегдгабоп Еп|егедВУ 1 АТМ 0..1 авоипг мв! Ивсе!р1 сазЬОпНапд 0..1 Сазидег чеп!УСазЬСа гб чеп!удвоив! б!зпигсерипдз гесе!черипдз роз|Тгапасбоп паве 0..1 Евргоуз 1 1 з1адоп еп|р!оуе Соде Соде 0..1 СазЬСагд Сагд Аидгодзадоп 1 з!абоп Соде зепаИЧивЬег разввогд Ива Вапи Сопаогбив аббАссоип! гевочеАссоип| с!озе гззиез че|ИУВапИСобе чепгураззаогд Соде сгеа1едаыпдзАссоип! ЬапИСобе сгеагеСПеыпддссоип1 1 сгеагеСазЬСагб чеп!УАвоиы ассоип!Соде 0..1 Сизигвег Ассоип1 паве адгезз !еврАвоип1 Ьа!апсе сгедамва 0.Л ,„ де| Авоип1 де1 Ассоипг дозе чеп!УАвосп1 беЬИ с|оба Рис.
1$.4. Модель классов бан«сиате 15.5. Рекурсия вниз Мы рекомендуем применять многоуровневое упорядочение операций: операции из верхних уровней при этом вызывают операции из нижних уровней. Процесс проектирования обычно осуществляется сверху вниз — вы начинаете с самых высокоуровневых операций, а затем определяете низкоуровневые операции. Можно работать и снизу вверх, но при этом вы рискуете спроектировать операции, которые впоследствии не потребуются. Рекурсия вниз осуществляется двумя основными способами: по функциональности и по механизму.
334 Глава 15 ° Проектирование классов 15.5.1. Уровни функциональности Рекурсия по функциональности означает, что вы берете требуемую высокоуровневую функциональность и разбиваете ее на операции более низкого уровня. Это естественный способ работы, но при произвольном разбиении операции на части, плохо согласованные с классами, вы можете столкнуться с проблемами.
Чтобы избежать этого, объединяйте схожие операции и назначайте операции классам. Еше одна опасность рекурсии по функциональности заключается в том, что сама рекурсия может сильно зависеть от точной формулировки высокоуровневой функциональности. Небольшое изменение может радикально повлиять на разбиение. Чтобы предотвратить это, нужно прикреплять операции к классам и расширять их функциональность в расчете на последующее повторное использование. Операция должна быть цельной, внутренне согласованной и осмысленной, а не просто произвольной частью кода.
Аккуратно распределенные по классам операции подвержены изменениям в гораздо меньшей степени, чем свободно витающие в модели. Такой подход к функциональности основан на том, что виды ответственности системы неизбежно реализуются в ее составляющих. Пример с банкоматом. В разделе 15.3 мы рассмотрели вариант использования и разбили его на виды ответственности. В разделе 15А.4 мы распределили получившиеся операции по классам. Эти операции нас вполне устроили, но если бы они плохо согласовывались с моделью классов, нам пришлось бы переработать их. 15.5.2.
Уровни механизмов Рекурсия по механизму означает, что система строится из уровней, необходимых для обеспечения функционирования механизмов реализации. Для предоставления функциональности требуются различные механизмы хранения информации, управления последовательностью операций, координации объектов, передачи информации, выполнения вычислений и других действий. Эти механизмы не присутствуют в высокоуровневых операциях явным образом, но без них система работать не может.
Например, чтобы построить высокое здание, нужна инфраструктура поддерживающих балок, вспомогательных трубопроводов, устройств контроля качества. Все это не нужно самим пользователям, которые хотят просто иметь жилье, но это необходимо для того, чтобы сделать возможной реализацию выбранной архитектуры. Аналогичным образом компьютерная архитектура включает целый ряд универсальных механизмов, таких как структуры данных, алгоритмы и образцы.
Они могут быть связаны не с конкретной областью приложения, а с выбранным архитектурным стилем. Например, образец «субъект-представление» связывает несколько представлений с каждым субъектом. Субъект содержит семантическую информацию о некой сущности, а представление передает эту информацию пользователю в некотором формате. Существуют механизмы обновления субъектов и передачи изменений во все представления, а также обновления представления и передачи изменений в субъект.
Эта инфраструктура может обслуживать самые разные приложения. 15.6. Реорганизация 335 Однако как часть программы эта инфраструктура строится из других, более примитивных механизмов. В любой крупной системе уровни функциональности и механизмов неизбежно смешиваются. Система, спроектированная исключительно методом рекурсии по функциональности, получается хрупкой и сверхчувствительной к изменениям в требованиях. Система, созданная путем комбинирования различных механизмов, делает очень мало полезного.