Совместное использование Delphi и CASE Rational Rose при проектировании пользовательского интерфейса

Источник: Интерфейс
Алфимов Р.В. Золотухина Е.Б.

Введение

В настоящее время Delphi является одним из наиболее популярных программных продуктов для создания информационных систем. На его основе создаются как небольшие программы, так и системы масштаба предприятия. Чем же так привлекателен Delphi с точки зрения разработчика? Прежде всего, это конечно великолепная среда визуального программирования, понятная, простая для изучения и, зачастую, не требующая знаний профессионального разработчика (которые, как известно, по крупицам накапливаются в течение многих лет и десятилетий и стоят неимоверно дорого). В среде Delphi можно создавать достаточно сложные программные системы практически с нуля, написав минимум программного кода. При этом язык, на котором пишется программа, знакомый многим (по крайней мере, в нашей стране) Object Pascal, изучается в настоящее время на младших курсах большинства отечественных технических институтов.

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

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

Но давайте вернемся к достоинствам Delphi. Если отбросить среду визуального программирования, то, что же останется? Объектная модель. А вот это уже достоинство Delphi, привлекательное с точки зрения проектировщика системы и именно объектная модель (как бы это не показалось кому-то странным) во много определяет успех среды визуального программирования. Объектная модель Delphi охватывает широкий круг задач, обеспечивая высокоуровневые (но при этом исключительно гибкие, практически без ограничений) средства организации пользовательского интерфейса, управления ресурсами операционной системы, манипулирования данными БД, поддержки стандартов открытых систем, поддержку популярных технологий (включая CORBA и COM), многоуровневую архитектуру и, наконец, Internet/Intranet технологии. Базовая архитектура может использовать элементы объектной модели Delphi (зачем заново создавать все выше перечисленное), дополнив ее необходимыми составляющими, отражающими прикладную специфику конкретной системы.

Мы используем для проектирования систем продукт Rational Rose фирмы Rational Software Corporation. Rational Rose обладает всеми необходимыми характеристиками для создания базовой архитектуры системы любого масштаба. Имея достаточный опыт программирования в среде Delphi, для нас привлекательным является использование Rational Rose и Delphi совместно, в рамках единого технологического процесса.

Целью настоящей статьи является рассмотрение совместного использования Rational Rose и Delphi и точное (разумеется, с нашей точки зрения) указание места каждого продукта в процессе разработки. Для разработчиков, мы надеемся, это позволит составить мнение о том, насколько подобная технология применима для их собственных нужд, и сэкономить время на изучении деталей.

Что мы хотим от Rational Rose и Delphi?

Методология, которой мы следуем при разработке ПО, это методология разработки программного обеспечения Rational Unified Process фирмы Rational Software Corporation. Методологияс технологической точки зрения включает в себя следующие этапы (разумеется, в рамках каждой итерации): моделирование предметной области, определение требований к системе, анализ и проектирование, реализацию (кодирование и автономную отладку), тестирование и внедрение. Ниже приведена таблица, в которой представлено то, что мы ожидаем получить при помощи Rational Rose и Delphi на каждом этапе (см. Табл. 1.).

Табл. 1. Использование Rational Rose и Delphi
на различных этапах разработки ПО

Этап

Что мы ожидаем от Rose

Что мы ожидаем от Delphi

Моделирование предметной
области

Выполняется моделирование предметной области, описывается предметная
область "как есть"

Ничего

Определение требований к системе

Определяются функциональные требования к системе, требования к интерфейсу системы.

Создается прототип пользовательского интерфейса

Анализа и проектирование

Определяются базовые компоненты архитектуры, моделируются данные, детально проектируются компоненты системы.

Элементы объектной модели Delphi включаются в базовую архитектуру. Обеспечивается однозначное соответствие элементов диаграмм классов Rose и элементов компонент Delphi.

Реализация

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

Реализуется программный код, обеспечивается однозначное соответствие проекта в Rose и Delphi. Документирование кода в Delphi отражается в Rose.

Тестирование

Модели остаются практически неизменными. Разрабатываются тестовые примеры для тестирования функций системы.

Вносятся изменения в программный код. Изменения в программном коде отражаются в коде Delphi.

Внедрение

Диаграммы размещения являются основой для внедрения ПО. На основе моделей может быть получена актуальная документация системного уровня.

Ничего.

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

Для обеспечения связи между Delphi и Rose используется промежуточное ПО называемое кодогенератором. Строго говоря, задачи этого ПО не ограничиваются только генерацией кода. Прежде, чем перейти к описанию конкретного кодогенератора перечислим, что, по нашему мнению он должен обеспечивать.

Итак, кодогенератор должен:

  • иметь возможность преобразовывать классы Rational Rose в код определения классов на целевом языке, в данном случае Delphi, при этом описание, связанное с конкретным классом должно помещаться в соответствующее место программного кода;
  • для диаграммы классов поддерживать стереотипы, связанные со специфическими особенностями языка (например, стереотип unit, interface или property, соответственно определяя, что конкретный пакет - есть модуль Delphi или класс - есть интерфейс Delphi, или атрибут - есть свойство для компоненты Delphi);
  • иметь описанный, очевидный и однозначный способ отображения диаграммы классов в код Delphi, при этом отображение должно быть настраиваемым;
  • иметь возможность импорта актуальной объектной модели Delphi (желательно для различных версий библиотеки VCL);
  • поддерживать генерацию кода для создания компонент Delphi;
  • уметь правильным образом отображать типовые виды связей между классами (хотя бы обобщение, агрегацию и композицию);
  • уметь отображать в программный код кардинальность связи;
  • исходя из диаграммы компонент Rose, создавать проект Delphi, содержащий требуемые программные модули (forward engeneering);
  • на основе готового проекта Delphi строить диаграмму компонент Rose, содержащую в виде компонент все модули проекта Delphi и связанные с ними классы, полученные из Delphi в результате обратного проектирования (reverse engeneering). Диаграммы должны быть компактными и очевидными;
  • обеспечивать автоматическое согласование модели Rose и Delphi после внесения изменений в код модулей Delphi (round trip engeneering);
  • после внесения изменений в модель Rose и повторной генерации кода не уничтожать, фрагменты, написанные в среде Delphi;
  • помимо генерации кода иметь способ отображения такого важного элемента Delphi, как формы;
  • на реальных проектах (сотни классов и модулей) работать с приемлемой производительностью.

Кодогенератор Delphi от фирмы Ensemble Systems, Inc.

Компания Ensemble Systems, Inc. в настоящее время является одним из ведущих поставщиков дополнительных компонент (add ins) для Rational Rose. Эти компоненты поддерживают кодогенерацию для широкого спектра популярных систем программирования, в том числе и для Delphi. Рассмотрим работу кодогенератора Delphi в среде Rational Rose.

После установки компонента Delphi от фирмы Ensemble Systems, Inc.в среде Rational Rose появляется новый пункт меню в разделе Tools (рис. 1).

Рис. 1. Пункты меню кодогенератора Delphi

Кодогенератор носит название Rose Delphi Link (RDL). Как пользоваться RDL мы опишем в следующем разделе, когда будем рассматривать конкретный пример. Сейчас же мы сосредоточим наше внимание на основных возможностях RDL (не имея о них представления вряд ли можно использовать его эффективно).

Прежде всего, заметим, что код, создаваемый RDL не содержит реализацию (для объектной модели это, как правило, это тело метода). Когда модель обновляется из кода Delphi (reverse engeneering или round trip), модель не подгружает программный код, написанный в среде Delphi для тел методов. Изменения в модели касаются только декларативных элементов: определений классов, интерфейсов, типов, записей и т. п. Однако, при повторной генерации кода из Rose, тела методов в Delphi также остаются неизменными, а меняются только декларативные элементы. Таким образом "испортить" программный код при повторной генерации нельзя. Для отображения элементов модели в программный код RDL использует Code Generation Properties (CGP) - набор специальных таблиц, которые связываются с каждым элементом моделей Rational Rose и содержат специфическую для Delphi информацию, используемую для кодогенерации. Набор этих таблиц доступен из главного меню (пункт Tools/Options, закладка Delphi) (рис. 2).

Рис. 2. Таблица свойств CGP для операций в кодогенераторе Delphi.

Для того, что бы CGP для Delphi было доступно из спецификации необходимо установить значение поля Default Language = Delphi в закладке Notation пункта меню Tools/Options. Для упрощения работы в разделе меню Tools/Ensemble Tools появляется также закладка Delphi Property Editor, где можно настроить свойства выбранного элемента модели. Заметим, что использование CGP является типичным приемом для всех кодогенераторов от Ensemble Systems, Inc и для Rational Rose вообще. При использовании Delphi Property Editor можно, не выполняя кодогенерации, просмотреть код соответствующего элемента модели (например, класса), что часто бывает очень удобно.

Теперь рассмотрим, как отображаются RDL в программный код конкретные типовые приемы проектирования

1. Наследование от класса и реализация интерфейса

Преобразуется в код:

type SampleClass1 = class (BaseClass, SampleInterface)
{...}
end;

2. Ассоциативные связи с ролями и различной кардинальностью связи

Преобразуется в код:

type SampleClass3 = class 
private
ArrayRole1 : array of SupplierClass2;
ArrayRole2 : array [1..10] of SupplierClass5;
ArrayRole3 : array [SampleRange] of SupplierClass3;
ArrayRole4 : TItems;
end;

Заметим, что для представления ролей с кардинальностью связи не равной 1 используются массивы (либо фиксированной длины, либо динамические). Константа SampleRange в примере должна быть определена в свойстве Array_Range для роли ArrayRole. Обратите внимание, что для Role4 в коде определен не массив, а тип TItems, который должен представлять коллекцию.

3. Агрегация и композиция

Преобразуется в код:

SampleClass1 = class
Public
A : SampleClass2;
B : SampleClass3;
C : array of SampleClass4;
D : array of SampleClass5;
end;

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

4. Стереотипы для типовых элементов программного кода Delphi RDL имеет несколько стереотипов для представления типовых элементов программного кода Delphi: указателей, массивов, файлов, ссылок на класс и т.п. Правда, на наш взгляд, эти элементы малоупотребительны при высокоуровневом проектировании объектной модели. В заключение краткого описания особенностей RDL отметим следующее. Важным элементом проектирования является документация в спецификации для соответствующего элемента модели. RDL обеспечивает ее передачу в программный код. Так для операций (методов класса Delphi) значение поля documentation в спецификации вставляется в код перед определением метода. И обратно, комментарии в программном коде Delphi могут быть преобразованы в поля documentation в спецификации элементов модели Rose.

Что не умеет RDL

Ранее мы определили, что, по нашему мнению, должен обеспечивать кодогенератор Delphi. В целом RDL охватывает все перечисленные возможности, за исключением, пожалуй, одного: он не позволяет создавать формы. Вы может представить себе среду Delphi без форм? Мы, к сожалению, тоже. Основная парадигма визуального программирования в среде Delphi состоит в задании значений соответствующих свойств (значений атрибутов классов) и написании кода обработчиков событий. И здесь, к сожалению, RDL нам не помощник. Но, действительно ли это столь серьезное ограничение? Здесь могут существовать различные мнения.

Один из путей таков. Проектируется пользовательский интерфейс в среде Delphi (а где это сделать быстрее и проще?) и выполняется преобразование программного кода в модели Rational Rose. Несмотря на то, что формы получаются достаточно громоздкими, их можно "причесать", а главное, не отображать в них несущественные детали . В Rational Rose проектируется, собственно, объектная модель, модель данных, компонентная модель, т. е. архитектурно существенные элементы. В сочетании с моделью пользовательского интерфейса системы они образуют, ту структуру системы, которая может быть отслежена средствами управления конфигурациями, включается в документацию, легко анализируется на предмет наличия принципиальных ошибок и является основой для функционального тестирования, т. е. может быть использована на любом этапе жизненного цикла (ЖЦ) разработки ПО. RDL при этом обеспечивает полное согласование моделей и программного кода в течение всего ЖЦ ПО. Мы стараемся придерживаться именно такого подхода.

Пример совместного использования Delphi и Rational Rose

К сожалению, вряд ли возможно в рамках небольшой статьи продемонстрировать полноценный пример реального приложения. Однако это и не требуется. Возвращаясь к тому месту статьи, где мы описывали, что ожидаем от Rose и Delphi на каждом этапе разработки, мы отметили, что важным для нас при проектировании является создание базовой архитектуры, в данном случае, с включением элементов объектной модели Delphi. Вот здесь мы и продемонстрируем возможности RDL.

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

Рис. 3. Функциональная диаграмма системы

На диаграмме отражены три действующих лица: администратор, прибор, врач. Функции системы, связанные с прибором, мы рассматривать не будем. В отношении прибора для нас существенно, что показатель получается с определенной периодичностью, и система предоставляет интерфейс для его сохранения в БД. Все оставшиеся функции системы связаны с пользовательским интерфейсом и обеспечением хранения информации в БД или ее выборкой.

В основу системы мы закладываем следующие архитектурные решения:

  • пользовательский интерфейс (GUI) системы строится на основе объектной модели Delphi;
  • интерфейс с СУБД строится на основе объектной модели Delphi;
  • в качестве СУБД используется реляционная СУБД.

При проектировании системы мы должны определить классы для представления пользовательского интерфейса (boundary classes), управляющие классы, реализующие логику работы системы (control classes) и классы-сущности для отображения структуры хранения информации (entity classes).

Классы - сущности, спроектированные нами, представлены на рис. 4.

Рис 4. Классы - сущности системы

Из объектной модели классов - сущностей мы получили физическую модель данных для реляционной СУБД и обеспечили ее генерацию для конкретной СУБД. Подробности того, как это можно сделать в среде Rational Rose, здесь мы опускаем.

Поскольку мы планируем построение GUI на основе объектной модели Delphi, разумно предположить, что классы для представления пользовательского интерфейса (boundary classes ) мы можем получить при прототипировании пользовательского интерфейса в среде Delphi. Проектируются классы пользовательского интерфейса (boundary classes) для окна представленного на рис. 5.

Рис. 5. Внешний вид главного окна системы

Рис. 6. Окно согласования моделей Rational Rose и Delphi

Это окно является основным при согласовании объектных моделей Delphi и Rose и при его использовании реализуется любая из трех технологий совместной работы - прямое проектирование, обратное проектирование и согласование (round trip). Левая панель на экране содержит дерево проекта в Rational Rose (в части Component View). Правая панель отображает дерево проекта в Delphi. Для обновления информации о проектах требуется нажать кнопку Refresh, а для выполнения согласования моделей в ту или иную сторону (из Rational Rose в Delphi или из Delphi в Rational Rose) кнопки Update All. Для удобства работы рассогласованные элементы в моделях помечены восклицательным знаком. Для выбора требуемого проекта в Delphi следует воспользоваться главным меню окна.

Мы выполнили согласование моделей при помощи данного окна и при этом получили следующее:

  1. Каждому модулю проекта в Delphi сопоставлен компонент со стереотипом <Unit> в разделе Component View дерева проекта Rose. Нашему проекту patient.dpr сопоставлен компонент со стереотипом <Program>.

  2. Для каждого модуля Delphi в разделе Logical View образовался пакет со стереотипом <Unit>, а внутри пакета содержится диаграмма классов, соответствующая данному модулю. У нас получился один такой модуль - main. Рядом в дереве проекта находится ссылка на файл main.pas и единственным щелчком мыши мы можем перейти к нему в среде Delphi и посмотреть на внешний вид формы. Это принципиально важно, поскольку какими бы изобразительными возможностями не обладал язык UML, внешний вид формы с его использованием описать затруднительно (да и зачем)!!! Фактически мы обеспечиваем представление модуля в двух срезах: с точки зрения внешнего представления интерфейса пользователя и с точки зрения объектной модели. На наш взгляд, отсутствие одного из этих срезов давало бы не полную картину.

Диаграмма классов для модуля main представлена на рис. 7.

Рис. 7. Диаграмма классов для модуля main

На диаграмме классов мы убрали атрибуты и операции для всех классов объектной модели Delphi (поскольку этих атрибутов и операций в каждом классе несколько десятков - диаграмма в таком случае стала бы необозримой). Диаграмма наглядным образом демонстрирует, какие именно классы объектной модели Delphi используются для представления элементов пользовательского интерфейса и что именно они представляют. Из представления модели сразу же следует исключить TGroupBox и TLabel как архитектурно несущественные элементы. Диаграмма классов для формы табличного редактирования представлена на рис. 8.

Рис. 8. Диаграмма классов для формы табличного редактирования

Кроме главного окна нам также потребуется интерфейс (GUI) для ведения БД пациентов, типов показателей и единиц измерения. Мы планируем использовать для этого типовую форму табличного редактирования на основе стандартных компонент Delphi. Нарисуем эту форму в Delphi и преобразуем в модель Rational Rose (рис. 9).

Рис. 9. Табличная форма редактирования.

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

Рис. 10. Справочник типов наблюдений

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

TMainForm должен обеспечивать:

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

                Создадим в среде Rational Rose операции для реализации описанных выше функций класса TMainForm (рис. 11).

                Рис. 11. Класс TMainForm.

                Операции класса TMainForm следует разделить на две группы: расчеты и реакции на события. Операции, заканчивающиеся на Click или Change, а также FormShow - реакции на события, остальное - расчеты.

                Операции должны реализовывать следующее:

                • FillPatientList - заполнение выпадающего списка пациентов;

                • FillMeasureList - заполнение выпадающего списка единиц измерения;

                • FillObservList - заполнение выпадающего списка типов наблюдений;

                • CalcObservVal - расчет последней наблюдаемой величины;

                • ChPatientByCard - поиск пациента по номеру карты;

                • ChCardByPatient - поиск номера карты по пациенту;

                • ChMeasureByObserv - вернуть единицу измерения для заданного типа наблюднений;

                • CardValChange - реакция на изменение номера карты;

                • PatientChComboChange - реакция на выбор нового пациента в списке;

                • ObservTypeComboChange - реакция на выбор типа наблюдения;

                • GetValueButtonClick - реакция на нажатие кнопки расчета значения;

                • PatientDictClick - реакция на нажатие кнопки "Пациенты";

                • ObservTypeDictClick - реакция на нажатие кнопки "Типы наблюдений";

                • MeasureDictClick - реакция на нажатие кнопки "Единицы измерения";

                • FormShow - обработка при первом отображении формы на экране.

                  И последнее, что необходимо для завершения проектирования - управляющие классы для реализации взаимодействия с БД. Без них невозможно как наполнение БД, так и реализация расчетных операций управляющего класса TMainForm. Как и для интерфейсных классов, воспользуемся средой Delphi для проектирования управляющего класса взаимодействия с БД - TDataModule1, а затем выполним согласование моделей. Новый модуль взаимодействия с БД представлен на рис. 12.

                  Рис. 12. Организация взаимодействия с БД

                  На основе объектов QueryPatient, QueyObType, QueryMeasures и PatientDataSource, ObTypeDataSource, MeasureDataSource реализуется работа с БД пациентов, типов наблюдений и единиц измерения - стандартным для Delphi способом, основанным на использовании пары объектов классов TQuery, TdataSource и их взаимодействием с классами GUI. ObservDataSource используется для доступа к информации о сделанных наблюдениях. Для описания взаимодействия управляющих классов TDataModule1 и TMainForm следует создать несколько диаграмм взаимодействия, связанных с выполнением требуемых запросов к БД (в виду ограниченного объема статьи эти диаграммы мы опускаем).

                  Заметим, что в процессе добавления в систему новых модулей и классов и согласования моделей мы автоматически получили компонентную модель системы (рис. 13).

                  Рис. 13. Компонентная модель системы

                  Итак, подведем краткие итоги. В результате совместного использования Rational Rose и Delphi мы получили:

                    • интерфейсные и управляющие классы, организованные в пакеты;
                      • компонентную модель системы.

                        Классы - сущности и диаграммы, описывающие динамику, спроектированы в Rational Rose. В дальнейшем модели Rational Rose дают нам базу для документирования проекта, отслеживания его состояния и организации функционального тестирования. Проект, полученный в Delphi, в свою очередь, является основой для выполнения реализации. В процессе реализации проводится периодическое согласование проекта в Delphi с моделью Rational Rose на основе технологии round trip, что позволяет поддерживать модели в актуальном состоянии и плавно осуществлять их эволюцию в соответствии с изменившимися требованиями к системе.

                        Заключение

                        В заключение мы хотим обратить внимание на те этапы, где по нашему мнению совместное использование Delphi и Rational Rose наиболее привлекательно с технологической точки зрения.

                        Во первых, это создание прототипа пользовательского интерфейса. Быстрое создание форм в среде Delphi позволяет также быстро получить и модель интерфейсных классов в Rose, а на ее основе выделить принципиальные архитектурные моменты (например, общность поведения, типовые элементы GUI, избыточность), а также сопоставить интерфейсные классы с функциональными требованиями к системе.

                        Во вторых, это создание управляющих классов в моделях Rational Rose с последующей генерацией кода в Delphi. Управляющие классы представляются в среде Rational Rose при использовании UML более очевидным образом (в Delphi они могут быть размыты среди значительных по объему интерфейсных классов).

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


                        Страница сайта http://test.interface.ru
                        Оригинал находится по адресу http://test.interface.ru/home.asp?artId=4826