tehnologia (1018792), страница 34
Текст из файла (страница 34)
Эту проблему можно решить,если хранить и данные, и результаты в упакованном виде, распаковывая их по меренадобности. Значит, соответствующие классы должны объявлять абстрактные операцииУпаковать() и Распаковать(), которые будут реализовываться классами-подтипами взависимости от реальной структуры данных, определяемой типом задачи. Следовательно,указанные классы должны также хранить тип задачи, с которой они связаны, и содержатьоперации Определить тип задачи() и Сообщить тип Задачи().К л а с с А л г о р и т м. Объекты класса Алгоритм отвечают за реализацию методарешения задачи.
Поскольку они посылают сообщение объектам класса Задания, то,естественно, должны хранить его адрес. Кроме того, класс Алгоритм должен объявлятьабстрактную опёрацию Выполнить(). Эта операция должна переопределяться классамиАлгоритм, реализующий метод.Примечание. Возможно более удачное решение: в классе Алгоритм определить операцию Выполнить()и внутреннюю абстрактную операцию Реализовать метод(), которая вызывается из первой. Такое решениепозволит не дублировать общее поведение всех алгоритмов, например, запрос и распаковку данных, а такжеупаковку и запись результата.
Это решение не приведено, чтобы не усложнять и так достаточно сложныйпример.К л а с с Р е ш е н и е. Объект класса Решение обращается к объектам классов Заданиеи Алгоритм, следовательно, необходимо хранить их адреса. Операции Начать() и Прервать()получены из диаграмм последовательностей действий.
Операция Обработать исключение()получена оттуда же, но она должна реализовываться особым образом, так как будет получатьуправление через механизм исключений. Результаты уточнения приведены на рис. 7.20.205206Проектирование методов класса. Достаточно существенную информацию одействиях, которые должны. выполняться методами класса, можно получить, анализируядиаграммы последовательности действий. Однако алгоритмы всех сколько-нибудь сложныхметодов необходимо проработать детально. При этом можно использовать как ужеизвестные нотации (схемы алгоритмов и псевдокоды), так и диаграммы деятельностей.В § 6.5 были описаны диаграммы деятельностей, которые предлагалось использоватьв процессе уточнения спецификаций для описания вариантов использования.
Эти жедиаграммы могут использоваться и при проектировании методов обработки сообщений, втом числе и затрагивающих несколько объектов. В последнем случае целесообразно указатьвертикальными пунктирными линиями ответственности объектов соответствующих классов,что позволит проследить вызовы других объектов.Следует помнить, что в соответствии с общими правилами процедурнойдекомпозиции любую деятельность можно декомпозировать и изобразить в видедиаграммы деятельности более низкого уровня.Пример 7.8. Построить диаграмму деятельности для операции Начать() классаРешение. Анализ рис.
6.4, 7.7 -7.8 показывает, что данная деятельность затрагивает триобъекта уже детализированных классов Решение, Алгоритм и Задание. Определим зоныответственностиобъектовэтихклассов(рис.7.21):207• объект класса Решения организует обработку, т. е. инициализирует переменные (втом числе определяет тип Алгоритма), создает объект класса Алгоритм требуемого типа,активизируют обработку, а затем уничтожает объект класса Алгоритм;• объект класса Задание должен в ответ на запрос сообщить тип Алгоритма,предоставить данные и запомнить результаты;• объект класса Алгоритм отвечает за решение задачи. Полностью спроектированныеклассы реализуют на конкретном языке программирования.7.5. Компоновка программных компонентовДиаграммы компонентов применяют при проектировании физической структурыразрабатываемого программного обеспечения.
Эти диаграммы показывают, как выглядитпрограммное обеспечение на физическом уровне, т. е. из каких частей оно состоит и как этичасти связаны между собой.Диаграммы компонентов оперируют понятиями компонент и зависимость. Подкомпонентами при этом понимают физические заменяемые части программногообеспечения, которые соответствуют некоторому набору интерфейсов и обеспечивают ихреализацию. По сути дела, это отдельные файлы различных типов: исполняемые (.ехе),текстовые, графические, таблицы баз данных и т. п., составляющие разрабатываемоепрограммное обеспечение. Условные графические обозначения компонентов различныхтипов приведены на рис. 7.22.Зависимость между компонентами фиксируют, если один компонент содержитнекоторый ресурс (модуль, объект, класс и т.
д.), а другой - его использует. Качествокомпоновки оценивают по количеству и типу связей между компонентами, т.е. по степенинезависимости компонентов. На диаграмме компонентов зависимость обозначаютпунктиром со стрелкой на конце.208На рис. 7.23 в качестве примера приведена диаграмма компонентов системы решениякомбинаторно-оптимизационных задач.При компонентном подходе на диаграмме компонентов целесообразно показыватьинтерфейсы, через которые компоненты связаны между собой (рис. 7.24).209Кроме этого, на диаграмме компонентов допустимо уточнять зависимость междукомпонентами,используяобозначенияобобщения,ассоциации,композиции,агрегатирования и реализации.
Так, на рис. 7.23 и 7.24 показано, что база данных включает(отношение композиции) две таблицы.Используя нотацию UML, можно построить диаграмму компонентов практически длялюбого случая, например, для Интернет-приложения. На рис. 7.25 приведен примердиаграммы компонентов клиентской части Интернет-приложения, написанного сиспользованием Java, которое в процессе работы демонстрирует некоторый рисунок.При «сборке» исполняемых файлов диаграммы компонентов применяют дляотображения взаимосвязей файлов, содержащих исходный код. Так, на рис. 7.26 показано,что основной файл Main.cpp зависит от заголовочного файла Model.h, реализация которогонаходится в файле Model.cpp.210Для программного обеспечения с архитектурой «клиент-сервер», диаграммукомпонентов можно использовать в качестве структурной схемы, определяющейархитектуру разрабатываемого программного обеспечения, так как она позволяет показатьсвязи по управлению частей системы (компонентов).
Однако при проектировании такуюсхему необходимо уточнить, показав более подробно состав компонентов разрабатываемойсистемы.7.6. Проектирование размещения программных компонентовдля распределенных программных системПри физическом проектировании распределенных программных систем необходимоопределить наиболее оптимальный вариант размещения программных компонентов нареальном оборудовании в локальной или глобальной сетях.
Для этого используютспециальную модель UML - диаграмму размещения.Диаграмма размещения отражает физические взаимосвязи между программными иаппаратными компонентами системы. Каждой части аппаратных средств системы, например,компьютеру или датчику, на диаграмме размещения соответствует узел. Соединения узловозначают наличие в системе соответствующих коммуникационных каналов. Внутри узловуказывают размещенные на данном оборудовании программные компонентыразрабатываемой программной системы, сохраняя указанные на диаграмме компонентовотношения зависимости.С точки зрения диаграммы размещения локальная и глобальная сети - это тоже узлы,которые обладают некоторой спецификой.
На рис. 7.27 показаны условные обозначенияузлов (процессора и устройства) на диаграмме размещения.Пример 7.9. Разработать диаграмму размещения для системы учета успеваемостистудентов.Локальная сеть деканата связывает сервер деканата и компьютеры декана, егозаместителей и сотрудников деканата, отвечающих за занесение ин-211формации в базу данных. Серверную часть системы и базу данных целесообразно поместитьна сервер деканата.
На компьютерах локальной сети в этом случае будут функционироватьсоответствующие клиентские части приложения (рис. 7.28).7.7. Особенность спиральной модели разработки.Реорганизация проектаСпиральная модель жизненного цикла разработки программного обеспеченияпредполагает, что процесс разработки программной системы выполняется итерационно. Приэтом во время проектирования очередной версии может обнаружиться, что хорошопродуманная на начальных итерациях программа утратила свою изначально четкуюструктуру за счет накопившихся исправлений («заплаток»).Каждая «заплатка» в свое время ставилась, чтобы ликвидировать «небольшое»несоответствие уже реализованной части и той, что находилась в процессе реализации.Возможно также, что часть кодов при этом становилось неиспользуемой, а какие-то коды не эффективными.
Все это вместе приводит к тому, что разобраться в программе становитсядостаточно сложно. В такой ситуации необходима реорганизация программ, т. е. ихперепроекти-212рование без изменения функциональности. Своевременно выполненная реорганизацияпозволит сделать структуру программы опять четкой и понятной.Несмотря на то, что реорганизационные изменения, как правило, невелики,программисты их обычно не любят, так как придерживаются правила «работает - не трогай».Кроме того, сроки обычно ограничены, и тратить время на переделку того, что ужеотлажено, кажется нецелесообразным. Практика же показывает, что отказ от реорганизациипри накоплении исправлений приводит к усложнению программы и, соответственно,снижению ее технологичности со всеми вытекающими последствиями.Реорганизацию следует выполнять, если при расширении функциональностиобнаруживаются нарушения основных концепций проекта или код стап трудным дляпонимания.