Оценить:
 Рейтинг: 0

Проектирование на UML. Сборник задач

Год написания книги
2017
<< 1 2 3 4 5 6 7 >>
На страницу:
6 из 7
Настройки чтения
Размер шрифта
Высота строк
Поля

б. Добавьте в модель описание действий по инициализации модуля. Метод initPlugin проверяет, обрабатывает ли модуль события графического интерфейса вызовом isUIHandled. Если обрабатывает, то регистрирует модуль в качестве слушателя событий addListener в классе PlayerUIPresenter.

3.8. Взаимодействие выбора этажа SelectFloor содержит линию жизни кабины, представленной экземпляром активного класса Cabin, линию жизни floor экземпляра класса кнопки этажа FloorButton с селектором «1», и линию жизни класса Algorithm. Взаимодействие начинается с синхронного вызова кабиной операции нажатия кнопки isPressed на линии floor. Операция возвращает логическое значение «истина», если кнопка нажата. Затем экземпляр класса Cabin вызывает операцию selectFloor у алгоритма на линии в данном взаимодействии.

а. Используя оператор цикла, покажите, что проверяется нажатие кнопок всех этажей. Переменную цикла, содержащую номер кнопки этажа, объявите как атрибут взаимодействия.

б. Уточните взаимодействие, добавив вызовы операции указания алгоритму этажей, кнопки которых нажаты.

в. Пусть взаимодействие описывает поведение кооперации, линии жизни соответствуют ролям в этой кооперации. Каким образом необходимо изменить взаимодействие, если кооперация владеет ролью с линией жизни алгоритма?

г. (*) Приведите по одному примеру разрешенной и неразрешенной траекторий в данном взаимодействии.

3.9. Пользовательский интерфейс мультимедиа проигрывателя PlayerView сообщает ev контроллеру UIPresenter о начале проигрывания элемента списка воспроизведения playEntry. Контроллер: 1) рассылает это сообщение всем своим слушателям собственной операцией raiseEvent; 2) получает от управляющего компонента Engine тип контента по имени name выбранного элемента item события ev вызовом getContentType; 3) по типу контента получает медиапоток вызовами getAudioStream или getVideoStream; 4) переводит интерфейс в состояние проигрывания либо видео, либо аудио вызовом setPlaybackMode и указывает медиапоток операцией setMediaStream; 5) запускает воспроизведение операцией play контроллера.

а. Добавьте в модель возможность параллельной обработки сообщений в raiseEvent так, что операция обработки handleEvent вызывается асинхронно у каждого зарегистрированного слушателя типа IUIListener. Для отображения в модели используйте два анонимных слушателя.

б. Уточните взаимодействие при обработке события запуска проигрывания песни модулем lyricsPlugin, зарегистрированным в качестве слушателя событий UIPresenter. Модуль определяет тип контента элемента, передаваемый в сообщении о запуске. Для аудиоконтента создает запрос о тексте песни, вызывая собственный метод makeRequest. Затем модуль асинхронно вызывает операцию dispatchRequest класса NetController, передавая в параметрах запрос и себя как обработчика ответа. Получив ответ от сервера, NetController передает processResponse его обработчику. Модуль вызывает displayPage у UIPresenter и передает полученную HTML-страницу с текстом песни

3.10. (*) При решении основных задач, морфологический модуль ищет запрашиваемое слово в словаре языка. Таким образом, многие задачи в модуле зависят от реализации функции поиска слова в словаре. См. диаграмму на рис. 8. Для уменьшения объема, который занимает словарь, используется тип данных префиксное дерево[2 - Префиксное дерево, «Trie», http://en.wikipedia.org/wiki/Trie.]. Каждый узел дерева содержит ассоциативный массив буква – следующий узел. Таким образом, если слово есть в словаре, то в дереве есть путь, начинающийся в корне и проходящий по вершинам, соответствующим буквам слова.

а. Постройте модель кооперации поиска слова в словаре, используя роли класса Dictionary и узла дерева Node. Для моделирования префиксного дерева используйте квалифицированные соединители и булевый атрибут leaf, указывающий на конечный узел слова.

б. Добавьте в модель поведение кооперации. Актор парсер строки StringParser вызывает операцию hasWord класса Dictionary с параметром word типа String. Метод hasWord, реализующий операцию hasWord, получает корневой узел с помощью операции getRoot класса Dictionary. Получив экземпляр класса Node, метод в цикле для каждой следующей буквы слова word вызывает у этого экземпляра операцию getNextLetter с параметром c типа char – текущей буквы слова. Данная операция возвращает дочерний узел дерева. Когда буквы слова word закончились, нужно вернуть актору значение операции isLeaf последнего полученного узла Node.

в. Модифицируйте поведение. Если в какой-то момент вызов getNextLetter прерван по исключению NoSuchLetter, операция hasWord должна вернуть false.

3.11. Вариант использования просмотр каталога SearchCatalog реализован кооперацией GetAllRecords. Основной сценарий варианта использования начинается с получения контроллером приложения AC команды showRecords. AC отображает show в пользовательском интерфейсе UI сообщение «Идет запрос». AC параллельно отправляет источнику данных DataSource запрос readRecords. DataSource передает AC одну запись в параметре действия acceptRecord. Затем AC показывает запись в UI.

а. Укажите, что перед запросом записи, AC запрашивает getListSize количество записей у источника данных. Результат присваивается переменной listSize.

б. Измените модель так, чтобы источник данных передавал контроллеру listSize записей по одной, а контроллер отображал show в UI все полученные записи вместе.

в. Реализуйте альтернативный сценарий, когда источник данных не содержит записей.

г. Перечислите все необходимые соединители в кооперации GetAllRecords, укажите, какие сообщения по ним передаются. Ответ поясните.

д. (*) Какое минимальное количество экземпляров классов необходимо, чтобы выполнить описанное поведение? Ответ поясните.

ГЛАВА 2. МЕТОДЫ И ПАТТЕРНЫ ПРОЕКТИРОВАНИЯ

Парадигмы проектирования. Возникновение проектирования программного обеспечения можно связать с появлением языков высокого уровня в 60-х и 70-х годах. Проектирование возникло как дисциплина, целью которой было управление сложностью программных систем и расширение возможностей разработчиков по созданию систем большего размера предсказуемого качества.

В развитии проектирования как дисциплины выделяют несколько этапов, в каждом из которых доминировала одна из парадигм проектирования. В 70-е и 80-е такой была структурная парадигма проектирования. Ее основу составляют нисходящие декомпозиционные методы, итеративно разделяющие систему на функциональные блоки, все более понятные и простые в реализации. Примерами таких методов могут служить метод постепенного уточнения (stepwise refinement) [6], метод структурного анализа и структурного проектирования SSA/SD [6], техника структурного анализа и проектирования SADT[3 - Дэвид А. Марка, Клемент Л. МакГоуэн. Методология структурного анализа и проектирования: [Пер. с англ.] / Предисл. Д. Т. Росса. – М.: Фирма «Мета Технология». – 1993. – 240 с.; ил.]. Среди восходящих методов структурного проектирования следует отметить метод структурного проектирования Джексона [6].

Преимущественные нотации моделей в этой парадигме – это структурная схема, схема потоков данных, диаграмма сущность-связь, диаграммы IDEF.

В 80-е и 90-е преобладающими стали методы объектно-ориентированного проектирования. Основой методов является выделение общего описания групп объектов и использование этого описания в качестве абстрактного типа данных. Различные эвристики выделения общего описания и процедуры создания модели нашли выражение в различных методах анализа и проектирования. В результате объединения Objectory, OMT и OOAD был создан унифицированный процесс разработки RUP и язык моделирования UML. Во многом благодаря обсуждению принципов проектирования на страницах таких журналов как C++ Report были сформулированы эвристики повышения изменяемости и сопровождаемости систем SOLID [7]. Следует также отметить методы проектирования, основанные на выделении и группировке обязанностей RDD и связанные с ними эвристики назначения обязанностей GRASP [8]. А также методы, построенные на прямом использовании модели предметной области для построения программной системы. Позднее они нашли отражение в книге Эванса по предметно-ориентированному проектированию [5].

Сейчас объектно-ориентированные методы применяются для разработки отдельных компонент сложных систем. Методы структурного проектирования нашли применение при разработке систем обработки данных, в проектировании архитектуры систем масштаба предприятия.

Систематизация и количественный подход. Существование разных подходов к проектированию в одних и тех же отраслях ведет к необходимости их сравнения и определения предпочтительного и указания границ применимости. Инициатива по выработке базовых методов и теории программной инженерии SEMAT ставит своей целью каталогизацию методов, выработке их описания на основе нескольких базовых понятий и, таким образом, создания основ накопления данных об использовании методов для их последующего сравнения.

Распространенный подход к накоплению знаний в области проектирования – составление каталога повторно применимых приемов решения часто встречающихся задач проектирования, которое могут быть адаптированы для разных случаев – паттернов проектирования. В конце прошлого века были составлены первые каталоги паттернов. Наиболее известным является набор из двадцати двух паттернов «банды четырех» GoF [3]. В сфере высокоуровневого (архитектурного) проектирования аналогом паттернов выступают архитектурные стили [9], комбинации которых, исходя из требований к системе, составляют первоначальное архитектурное описание.

Результатом процесса проектирования являются отраженные в модели решения по реализации программной системы. Для прогнозирования нефункциональных характеристик системы, в том числе сопровождаемости, переносимости и других, вводят показатели проектировочного решения (метрики дизайна). Показатели используют для количественного описания размера системы, сложности решения, выявления недостатков и потенциально проблемных мест в системе. В данной книге рассматриваются показатели сложности проектировочного решения Чидамбера-Кемерера [10].

Применение методов. До автоматического проектирования программных систем пока еще далеко, в проектировании остается существенная доля искусства. В том числе вследствие самой сути задач проектирования, относящихся к так называемым плохо поставленным задачам (wicked problems), условия которых неполны, противоречивы, меняются со временем и в процессе решения. Тем не менее, владение базовыми методами позволяет не отвлекаться на обдумывание задач, решение которых уже известно, и, таким образом, повысить качества результата и сократить время его создания.

Рассматриваемые в сборнике методы проектирования отражают современное состояние практики разработки и проектирования на уровне компонентов и приложений. Их изучение позволит как вступить в специальность проектирования, восполнить отдельные пробелы, так и по-новому взглянуть на уже известную область.

Принципы проектирования классов и интерфейсов SOLID. Аббревиатура SOLID расшифровывается по первым буквам сокращений названий принципов проектирования классов.

Single responsibility principle (SRP), принцип ограничения обязанностей, говорит, что модуль или класс должен иметь только один набор функционально сходных обязанностей.

Open-closed principle (OCP), принцип открытости-закрытости, указывает, что класс или модуль должен быть расширяем (открыт для расширения) без внесения в него изменений (закрыт для изменения).

Liskov substitution principle (LSP), принцип подстановки (описан в статье Барбары Лисков, отсюда название), указывает правило построения иерархии типов так, что любой подтип или дочерний класс подставим вместо базового типа или класса соответственно.

Interface segregation principle (ISP), принцип разделения интерфейса, говорит, что для обозначения разных ролей, которые играет класс в разных взаимодействиях, следует использовать разные интерфейсы.

Dependency inversion principle (DIP), принцип обращения зависимостей, указывает на корректное применение принципа сокрытия информации в объектно-ориентированном подходе к проектированию, когда зависимости направлены от реализации класса к выделенным абстракциям: описаниям типов данных или интерфейса

§4. РАСШИРЕННЫЕ КЛАССЫ И ОБЪЕКТЫ

ОСНОВНЫЕ ПОНЯТИЯ

Квалификатор (qualifier) используется для разделения всех связей ассоциации на подмножества согласно уникальным ключам. Обычно в бинарной ассоциации «один-ко-многим» по ключу выделяют связи «один-к-одному».

Класс ассоциации (association class) используют, когда логическое отношение между объектами обладает сложной структурой или поведением. Класс ассоциации является одновременно и ассоциацией, и классом, поэтому может иметь свойства и операции.

Напомним, что операция – это поведенческая черта класса, которая определяется именем, набором параметров, их типами и кратностями, типом и кратностью возвращаемого значения. В дополнение к этому, можно задать ограничения на реализацию операции: предусловие (precondition), постусловие (postcondition), ограничение возвращаемого значение (body condition).

Если операция не изменяет значения свойств класса, то к операции добавляется украшение запрос (query).

Каждый параметр операции может иметь имя, тип, множественность. Параметру можно задать направление параметра (in, out, inout, return), значение по-умолчанию, ограничение на множественный параметр: упорядоченность значений (ordered), уникальность значений (unique).

Производные свойства класса (derived property) вычисляются на основе других свойств или результатов вызова операций класса или других классов модели. Способ вычисления значений свойства указывается вместе с определением самого свойства, при этом вычисление значений не должно иметь сторонних эффектов и должно быть идемпотентным (повторные вычисления дают тот же результат при неизменности остальной модели). Часто используются производные свойства, значения которых составлены из объединения union множеств значений свойств, выделяющих подмножества subsets в базовых свойствах.

Шаблонные классы (template class) по сути не являются полноценными классами, а только их заготовками, определенными с точностью до значений параметров шаблона. Шаблонным может быть не только класс, но и другие элементы модели. Операция присвоения значения параметру называется связыванием (bind). По смыслу, связывание класса с шаблонным классом с приданием значения параметру аналогично созданию класса из шаблона с указанным значением параметра и наследованием от этого класса.

Переопределение (derived) позволяет заменить определение черты классификатора в рамках его контекста переопределения (redefinition context), составляющего совокупность всех классов, обобщающих данный. При переопределении можно заменить, например, сигнатуру операции. После переопределения при обращении к новой операции в классе следует использовать новую сигнатуру. При этом наследованная переопределенная операция также доступна для использования.

Множество обобщения (generalization set) позволяет логически группировать отношения обобщения. Можно указать, что в данном множестве обобщений приведены все возможные уточнения базового класса, или что совмещение непосредственно уточняющих классов в одном экземпляре или подклассе не допускается.

Супертип (powertype) используется совместно с множеством обобщений. Супертип это классификатор, экземплярами которого являются классы-элементы множества обобщений.

Пакеты (package) позволяют группировать элементы модели под общим именем. Для обращения к элементу пакета необходимо использовать квалифицированное имя, состоящее из имени пакета и имени элемента.

Между пакетами определены отношения доступа«access», которое для элементов пакета делает доступным элементы указанного пакета без необходимости указания квалифицированного имени, и отношение импорта «import», которое аналогично доступу, но делает элементы также доступными при последующем импорте или доступе из другого пакета.
<< 1 2 3 4 5 6 7 >>
На страницу:
6 из 7