Файл: Лаб. занятие № 9+.doc

ВНИМАНИЕ! Если данный файл нарушает Ваши авторские права, то обязательно сообщите нам.

Федеральное государственное бюджетное образовательное учреждение

высшего профессионального образования

«Пермская государственная сельскохозяйственная академия

имени академика Д.Н. Прянишникова»














ПРОЕКТИРОВАНИЕ ИНФОРМАЦИОННЫХ СИСТЕМ

направление 230700 «Прикладная информатика»




Лабораторное занятие № 9


Тема: МОДЕЛЬ РЕАЛИЗАЦИИ: СОЗДАНИЕ ПРИЛОЖЕНИЯ


Учебные вопросы:

  1. Программирование и процесс разработки.

  2. Преобразование результатов проектирования в программный код.

  3. Подключение уровня интерфейса пользователя к уровню предметной области














Вопрос 1. Программирование и процесс разработки

Выбор языка программирования

Рассматриваемые примеры написаны на языке Java. Такой выбор объясняется популярностью и широким распространением этого языка. Однако автор не выделя­ет язык Java среди других языков. Языки С#, Visual Basic, C++, Smalltalk, Python и многие другие тоже удовлетворяют принципам объектного проектирования и могут использоваться для преобразования разработанной модели в исходный код.


Выполнение предварительного проектирования совсем не означает, что в процес­се программирования нельзя выполнять макетирование и проектирование. Современные средства разработки предоставляют прекрасную среду для быстрого изучения альтернативных подходов, а некоторые из них (или даже многие) по­зволяют сочетать процессы проектирования и программирования.

Однако некоторые разработчики считают, что до начала этапа программи­рования желательно разработать базовые визуальные модели. Это особенно по­лезно тем разработчикам, которые обладают "визуальным стилем мышления" и лучше воспринимают информацию, представленную в виде диаграмм.

Написание кода на объектно-ориентированном языке программирования, наподобие Java или С#, не относится к процессу анализа или проектирования системы – это конечная цель проектирования. Артефакты, создаваемые в кон­тексте RUP в рамках модели проектирования, предоставляют часть информации, необходимой для генерирования кода.

Преимущество объектно-ориентированного подхода к анализу, проектированию и программированию в рамках RUP состоит в том, что он обеспечивает полный цикл разработки системы – от формулировки требований до программной реализации. Артефакты последовательно трансформируются в артефакты следующей стадии раз­работки, постепенно обеспечивая превращение системы в работающее приложение.

Внесение изменений на стадии реализации

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

Тем не менее, процесс программирования не сводится к примитивной гене­рации кода. Совсем наоборот: результаты, полученные на стадии проектирова­ния, оказываются далеко не совершенными. В процессе программирования и тестирования наверняка потребуется внести многочисленные изменения, а также выявить и разрешить возникшие проблемы.


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

Модификация кода и итеративный процесс

Преимущество итеративного и инкрементального процесса разработки за­ключается в том, что результаты предыдущей итерации могут служить началь­ными данными для последующей итерации (рис.1.1). Таким образом, резуль­таты последовательного анализа и проектирования непрерывно совершенствуют­ся на последующих итерациях разработки. Например, если код, созданный на итерации N, отклоняется от результатов проектирования этой итерации (что почти наверняка произойдет), то проектные решения, основанные на этой реали­зации, могут использоваться в качестве входных данных для моделей анализа и проектирования итерации N+1.

Рисунок 1.1 – Влияние программной реализации на процесс проек­тирования

последующих итераций

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

Изменение кода, CASE-средства и обратное проектирование

Очень желательно, чтобы диаграммы, полученные на стадии проектирова­ния, были полуавтоматически обновлены и отражали изменения, внесенные на соответствующей стадии кодирования. В идеале это делается с использованием CASE-средств (например, CaseBerry), с помощью которых можно считывать исходный код и автомати­чески генерировать, например, диаграммы пакетов, классов и последовательно­стей. Это пример обратного проектирования (reverse engineering), когда логиче­ские модели генерируются на основе исходного (или даже исполняемого) кода.


Вопрос 2. Преобразование результатов проектирования в программный код


Реализация на объектно-ориентированном языке программирования требует на­писания исходного кода для:

  • определений классов и интерфейсов;

  • методов.

В последующих подпунктах обсуждается генерация таких определений на языке Java (как типичный случай).

Создание определений классов на основе диаграмм классов

Коротко можно сказать, что на диаграммах классов отображаются имена классов и интерфейсов, суперклассов, сигнатуры методов и простые атрибуты классов. Этого вполне достаточно для создания базового определения класса на объектно-ориентированном языке программирования. Ниже будет рассмотрен процесс до­бавления информации об интерфейсе и пространстве имен (или пакете), а также других данных.


Определение класса с методами и простыми атрибутами

Как видно из рис. 2.1, преобразование диаграммы классов в базовые определения атрибутов (простые экземпляры переменных-членов на Java) и сигнатуры методов для определения класса SalesLineItem на языке Java выполняется очень просто.

Рисунок 2.1 – Класс SalesLineItem на языке Java

Обратите внимание на добавление конструктора SalesLineItem {. . .}. Это сделано на основании того, что в диаграмме взаимодействия для системной опе­рации enterItem объекту SalesLineItem передается сообщение create (spec, qty). При переходе к языку Java это означает необходимость использования конструктора с двумя указанными параметрами. Метод create зачастую исклю­чается из диаграммы классов, поскольку он является стандартным и имеет не­сколько интерпретаций, зависящих от используемого языка программирования.

Добавление атрибутов-ссылок

Атрибут-ссылка (reference attribute)это атрибут, ссылающийся на дру­гой сложный объект, а не на простой тип, такой как String, Number и т.д. (На диаграмме классов атрибуты-ссылки представлены ассоциациями и свя­занным с ними направлением перемещения).

Например, класс SalesLineItem имеет ассоциацию, направленную к классу productSpecification. Обычно эта ассоциация интерпретируется как атрибут-ссылка класса SalesLineItem, ссылающаяся на экземпляр ProductSpecification (рис. 2.2).

Рисунок 2.2 – Добавление атрибутов ссылок

На языке Java это означает добавление поля, ссылающегося на экземпляр ProductSpecification.

(Обратите внимание, что атрибуты-ссылки классов зачастую косвенно присут­ствуют, а не явно определяются на диаграмме классов).

Например, хотя в определение класса SalesLineItem на языке Java был до­бавлен экземпляр переменной, указывающей на экземпляр ProductSpecification, на диаграмме классов в разделе атрибутов явно объявленный атрибут отсут­ствует. Это объясняется предполагаемой видимостью атрибута, задаваемой ассоциацией и ее направлением. На стадии генерации кода эта ассоциация явно определяется как атрибут.

Атрибуты-ссылки и имена ролей

Рассмотрим имена ролей на статической структурной диаграмме. Каждый конец линии ассоциации называется ролью. Если говорить кратко, имя роли (role name) – это имя, идентифицирующее роль и обеспечивающее некоторый семантический контекст, которой иллюстрирует его природу.

Если имя роли присутствует на диаграмме классов, то при генерации кода его нужно использовать в качестве основы имени атрибута-ссылки (рис. 2.3).

Рисунок 2.3 – Имена ролей можно использовать для генерации имен экземпляров переменных

Отображение атрибутов

На примере класса Sale можно удостовериться в неоднозначности отобра­жения атрибутов диаграммы проектирования в исходный код. На рис. 2.4 по­казаны возможные проблемы, связанные с таким преобразованием.

Рисунок 2.4 – Преобразование в исходный код на языке Java атри­бутов даты и времени

Создание методов на основе диаграмм взаимодействия


На диаграммах взаимодействия представлены сообщения, которые передаются в ответ на вызов метода. Последовательность этих сообщений преобразуется в се­рию операторов в определении метода. Для иллюстрации определения метода enterItem на языке Java можно использовать диаграмму взаимодействия сис­темной операции enterItem (рис. 2.5).



Рисунок 2.5 – Диаграмма взаимодействия для системной операции enterItem

В приведенном примере будет использован класс Register. Его определе­ние на языке Java представлено на рис. 2.6.

Метод Register- -enterItem

Сообщение enterItem передается экземпляру объекта Register. Следова­тельно, метод enterItem определяется в этом классе.

Сообщение 1. Для получения объекта ProductSpecification объекту ProductCatalog передается сообщение getSpecification.

Рисунок 2.6 – Класс Register

Сообщение 2. Объекту Sale передается сообщение sale.makeLineItem(spec, qty).

Подводя итоги, можно еще раз повторить, что каждое сообщение из после­довательности внутри метода, как показано на диаграмме взаимодействия, пре­образуется в оператор метода на языке Java.

Полученный метод enterItem и его связь с диаграммой взаимодействия представлены на рис. 2.7.

Рисунок 2.7 – Метод enterItem

Классы-контейнеры в программном коде

Зачастую для объекта необходимо обеспечить видимость группы других объектов. Обычно это следует непосредственно из значения кратности, указанного на диаграмме классов. Оно может превышать единицу. Например, для объекта Sale необходимо обеспечить видимость группы экземпляров класса SalesLineItem (рис. 2.8).

Рисунок 2.8 – Добавление контейнера

В объектно-ориентированных языках программирования такие взаимосвязи в основном реализуются с помощью промежуточного контейнера или коллекции объектов. В классе, с которым связано единичное значение кратности, определя­ется атрибут-ссылка, содержащий указатель на экземпляр контейнера/коллекции. А в самом контейнере содержатся экземпляры класса, для которого значение кратности превышает единицу.

Например, в библиотеках Java имеются такие контейнерные классы, как ArrayList и HashMap, реализующие интерфейсы List и Map, соответственно. При использовании класса ArrayList в классе Sale можно определить атрибут, указывающий на упорядоченный список экземпляров SalesLineItem.

Выбор подходящего контейнерного класса определяется реальными требованиями. Если планируется применять поиск по ключу, то лучше воспользоваться классом Map; при организации расширяемого упорядоченного списка потребуется класс List и т.д.

Исключения и обработка ошибок

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


В языке UML для обозначения исключений используются асинхронные сообщения на диаграммах взаимодействия.

Метод Sale- -makeLineItem

В качестве заключительного примера рассмотрим метод makeLineItem класса Sale, который может быть описан на основе анализа диаграммы взаимодействия системной операции enterItem. Фрагмент диаграммы взаимодействия и соответствующий метод на языке Java представлены на рис. 2.9.


Рисунок 2.9 – Метод Sale-makeLineItem


Вопрос 3. Подключение уровня интерфейса пользователя к уровню предметной области


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

Основные проектные решения, обеспечивающие видимость объектов уровня Предметной области для объектов уровня пользовательского интерфейса, сводят­ся к следующему.

  • Инициализирующая программа (например, метод main Java) создает и объ­екты уровня пользовательского интерфейса, и объект предметной области, а затем передает этот объект на уровень интерфейса пользователя.

  • Объект пользовательского интерфейса получает объект предметной области из стандартного источника, например, от объекта-фабрики, отвечающего за создание объектов предметной области.

Следующий фрагмент кода демонстрирует пример использования перво­го подхода.

Будучи связанным с экземпляром объекта Register (выступающим в дан­ном приложении в роли внешнего контроллера), объект уровня пользовательско­го интерфейса может направить ему сообщение о системном событии, такое как enterItem или endSale (рис. 3.1).

Рисунок 3.1 – Связь уровней предметной области и пользовательского интерфейса

Для передачи сообщения enterItem необходимо иметь диалоговое окно, в котором будет отображаться общая стоимость каждого товара. При этом можно использовать несколько проектных решений:

  • Добавить объекту Register метод getTotal. Тогда с уровня пользователь­ского интерфейса объекту Register будет передаваться сообщение getTotal, а этот объект, в свою очередь, перенаправит это сообщение объ­екту Sale. Преимуществом такого подхода является низкая степень связы­вания между уровнями пользовательского интерфейса и предметной облас­ти – пользовательскому интерфейсу известен лишь один объект Register. Однако при этом "раздувается" интерфейс объекта Register, что приводит к слабой степени зацепления этого объекта.

  • Интерфейс пользователя запрашивает ссылку на текущий объект Sale, а затем при необходимости вычисления общей стоимости (или для получения любой другой информации о продаже) он передает сообщение напрямую объекту Sale. Такое проектное решение повышает степень связывания между уровнями поль­зовательского интерфейса и предметной области. Однако, как указывалось при рассмотрении шаблона GRASP Low Coupling, высокая степень связывания сама по себе не является проблемой. Проблема возникает при связывании с неустой­чивыми объектами. Объект Sale можно считать устойчивым, поскольку он яв­ляется неотъемлемой частью проектного решения. Следовательно, связывание с этим объектом не составляет проблемы.