- •Проектирование информационных систем
- •Вопрос 1. Обязанности, методы, взаимодействия
- •Вопрос 2. Шаблоны
- •Information Expert
- •Шаблон Information Expert
- •Шаблон Creator
- •Шаблон Low Coupling
- •Шаблон High Cohesion
- •Шаблон Controller
- •Вопрос 3. Реализация прецедентов
- •Пример: Реализация прецедентов для данной итерации разработки pos системы тт
- •Проектное решение: makeNewSale
- •Выбор класса-контроллера
- •Проектное решение: enterItem
- •Проектное решение: endSale
- •Проектное решение: makePayment
- •Проектное решение: startup
- •Проектное решение: store-create
- •Подключение уровня интерфейса пользователя к уровню предметной области
Проектное решение: endSale
Системная операция endSale выполняется при нажатии кассиром кнопки, свидетельствующем о завершении продажи. Ниже приведено полное описание этой операции.
ОП 3: endSale
Операция
|
endSale() |
Ссылки
|
Прецеденты: Оформление продажи
|
Предусловия
|
Инициирована продажа |
Постусловия
|
|
Выбор класса-контроллера
Для начала необходимо назначить обязанность, связанную с обработкой сообщения системной операции endSale. В соответствии с шаблоном Controller, в качестве контроллера будем использовать классRegister, как и для системной операцииenterltem.
Установка значения атрибута Sale.isComplete
Единственным постусловием в описании системной операции endSale является следующее:
Атрибут Sale.isCompleteпринял значениеtrue(модификация атрибута).
Если задача не сводится к созданию объекта или выбору контроллера (а в данном случае так оно и есть), то первым шаблоном, который необходимо применить для ее решения, является шаблон Expert.
Какой класс должен отвечать за установку атрибута isComplete объекта Sale равным значению true?
Согласно шаблону Expert, эту обязанность следует возложить на классSale, поскольку он владеет атрибутом isComplete. Тогда классRegisterбудет отправлять объектуSaleсообщениеbecomeComplete, требующее установки этого атрибута в значениеtrue.
Обозначения UML для ограничений, комментариев и описаний алгоритмов
Заметим, что на рис. 3.4 показано сообщение becomeComplete без детализации работы метода becomeComplete (в данном случае выполняются тривиальные действия). Иногда в UMLдля описания алгоритма или метода используются дополнительные текстовые пояснения.
Рисунок 3.4 – Завершение продажи
Для подобных целей в UML предусмотрены обозначения ограничений (constraints) ипримечаний(notes). Ограничение вUML– это некоторая семантически значимая информация, относящаяся к элементу модели. Ограничения в UML представляются в виде текстовых комментариев, заключенных в фигурные скобки, например {х>20}. В тексте ограничений можно использовать любой неформальный или формальный язык. Кроме того, для описания ограничений можно применять специально включенный в UML языкOCL(ObjectConstraintLanguage).
ПримечаниевUML– это комментарий, не имеющий семантического значения, например, указывающий дату создания или автора.
Примечания всегда отображаются в блоках примечаний(notebox) – блоках с "завернутым уголком".
Ограничения можно изображать в виде текстовых фрагментов, заключенных в фигурные скобки. Однако длинные тексты ограничений можно размещать в "блоках ограничений", аналогичных блокам примечаний. Чтобы отличить блок ограничения от блока примечания, его текст помещают в фигурные скобки.
На рис. 3.5 показаны оба типа обозначений, принятых для ограничений. Заметим, что простые ограничения (заключенные в фигурные скобки без помещения в блок) содержат логическое выражение, которое должно выполняться (классическое понятие ограничения из логики). А в блоке ограничений приводится реализация метода на языке Java. ВUMLдля обозначения ограничений можно использовать оба стиля.
Рисунок 3.5 – Ограничения и примечания
Вычисление общей стоимости покупки
Рассмотрим фрагмент прецедента Оформление продажи.
Основной успешный сценарий (или основной процесс)
Покупатель подходит к кассовому аппарату POS-системы с выбранными товарами.
Кассир открывает новую продажу.
Кассир вводит идентификатор товара.
Система записывает наименование товара и выдает его описание, цену и общую "стоимость. Цена вычисляется на основе набора правил.
Кассир повторяет действия, описанные в п.п. 3-4, для каждого наименования товара.
Система вычисляет общую стоимость покупки с налогом.
В соответствии с этим описанием, в п. 5 вычисляется общая стоимость товара. Согласно шаблону Model-ViewSeparation, на данном этапе не следует заботиться о том, как будет отображаться общая стоимость покупки. Необходимо лишь удостовериться, что это значение известно. Заметим, что нельзя указать класс, которому значение известно в данный момент, поэтому необходимо предусмотреть взаимодействие между объектами, обеспечивающее выполнение данного требования, и построить соответствующую диаграмму.
Как обычно, если не ставится задача выбора контроллера и создания новых объектов (а в данном случае это именно так), следует применить шаблон Expert.
Достаточно очевидно, что сам объект Saleдолжен отвечать за вычисление общей стоимости покупки, однако для чистоты эксперимента проведем следующий анализ:
Сформулируем обязанность.
Какой класс должен отвечать за вычисление общей стоимости покупки?
Подытожим требуемую информацию.
Общая стоимость покупки равна сумме стоимостей каждого из покупаемых товаров.
Стоимость каждого из покупаемых товаров равна произведению количества единиц покупаемого товара и цены этого товара.
Выпишем информацию, необходимую для выполнения данной процедуры, и классы, обладающие этой информацией.
Информация, необходимая для вычисления общей стоимости покупки |
Классы-эксперты
|
ProductSpecification.price
|
ProductSpecification
|
SalesLineItem.quantity
|
SalesLineItem
|
Все значения SalesLineItemдля текущей продажиsale
|
Sale
|
Продолжим детальный анализ.
Какой класс должен отвечать за вычисление общей стоимости продажи Sale?Согласно шаблонуExpert, это должен быть классSale, поскольку он обладает информацией обо всех экземплярах SalesLineItem, стоимость которых суммируется при вычислении общей стоимости. Следовательно, классSaleбудет отвечать за вычисление общей стоимости, и эта обязанность будет реализована в виде методаgetTotal.
Для вычисления общей стоимости покупки Saleнеобходимо знать стоимость каждого покупаемого товара SalesLineItem.Какой класс должен отвечать за вычисление стоимости SalesLineItem? Согласно шаблонуExpert, это должен быть классSalesLineItem, поскольку ему известно количество покупаемые единиц товара и спецификация этого товараProductSpecification. Следовательно, обязанность вычисления стоимости каждого товара, реализованная в виде методаgetSubtotal, должна возлагаться на класс SalesLineItem.
Для вычисления стоимости каждого товара SalesLineItem необходимо знать цену товара со спецификацией ProductSpecification.Кто должен отвечать за предоставление цены товара со спецификацией ProductSpecification?Согласно шаблонуExpert, это должен быть классProductSpecification, поскольку он инкапсулирует цену товара в качестве своего атрибута. Следовательно, эта обязанность, реализованная в виде операцииgetPrice, возлагается на классProductSpecification.
Хотя в данном конкретном случае проведенный анализ выглядит тривиальным, а степень детализации избыточной, такую же стратегию следует применять и в более сложных ситуациях. Освоив эти принципы, вы сможете легко распределить обязанности.
Проектное решение Sale-getTotal
Основываясь на приведенных рассуждениях, можно построить диаграмму взаимодействия, иллюстрирующую процесс передачи сообщения getTotalобъектуSale. Первым на этой диаграмме является сообщение getTotal, однако это не системное событие. Отсюда следует вывод:Не каждая диаграмма взаимодействия начинается с сообщения о системном событии. Она может начинаться с любого сообщения, для которого необходимо показать виды взаимодействия между объектами.
Диаграмма взаимодействия представлена на рис. 3.6. Сначала объекту Saleпередается сообщение getTotal. Затем объектSaleотправляет сообщениеgetSubtotalкаждому связанному с ним экземпляруSalesLineItem. В свою очередь, каждый экземпляр SalesLineItem отправляет сообщение getPrice связанному с ним объектуProductSpecification.
Рисунок 3.6 – Диаграмма взаимодействия для метода Sale – getTotal
Поскольку арифметические действия обычно не изображаются с помощью сообщений, их можно проиллюстрировать путем добавления на диаграмму дополнительной информации в виде ограничений или описаний алгоритма.
Какой класс должен передавать сообщение getTotal объекту Sale?Скорее всего, это должен быть объект уровня представления, например объектJFrameJava.
Рис. 3.7 иллюстрирует использование примечаний и ограничений при описании операций getTotalи getSubtotal.
Рисунок 3.7 – Использование примечаний и ограничений