BOLD - инструмент реализации MDA в Delphi

         

Bold — реализация MDA в Delphi


Однако некоторые фирмы-разработчики не стали ожидать появления окончательных стандартов, поскольку основные подходы и идеи MDA оказались достаточно простыми и весьма заманчивыми. Производители программного обеспечения уже разработали несколько инструментов для реализации (может быть, пока частичной) MDA-технологии в различных средах программирования. Среди этих инструментов имеется и программный продукт для реализации MDA в Delphi. Шведская компания BoldSoft MDE Aktiebolag, активный участник консорциума OMG, создала первую версию программного продукта Bold for Delphi в 1999 году, а в 2000-м в состав Borland Enterprise Studio 6 вместе с Delphi 6 вошла доработанная и расширенная версия Bold 3. В сентябре прошлого года в состав Delphi 7 Studio Architect вошла версия 4 Bold этого продукта. В начале октября фирма Borland приобрела шведскую компанию BoldSoft, так что в настоящее время Bold является продуктом фирмы Borland.

Основные возможности Bold for Delphi:

встроенный текстовый редактор UML-моделирования для создания моделей приложения; возможность импорта и экспорта UML-моделей из Rational Rose ? CASE-средства компании Rational Software; автоматическая генерация баз данных практически для всех реляционных СУБД, существующих в настоящее время (доступных через интерфейсы BDE, ADO, dbExpress); поддержка модификации базы данных с сохранением информации (DataBase Evolution); возможность хранения базы данных в XML-документе без использования СУБД; поддержка подмножества языка UML ? OCL (Object Constraint Language); автоматическая генерация программного кода на языке Object Pascal; автоматическая генерация экранных форм для просмотра и редактирования данных; поддержка создания многозвенных приложений и тонких клиентов на базе DCOM.

Даже перечисленных основных возможностей продукта более чем достаточно для кардинального сокращения трудозатрат на создание приложений баз данных практически любой сложности. По отзывам разработчиков, применение Bold позволяет сократить время разработки приложений баз данных в 5-10 раз.

На практике использование Bold дает следующие преимущества:

полностью устраняется этап ручного создания базы данных ? все таблицы, поля, индексы, ключи генерируются автоматически в соответствии с моделью. Для использования конкретной СУБД достаточно подключить и настроить один из адаптеров баз данных, входящих в состав Bold. Есть возможность создания собственных адаптеров баз данных; модификация базы данных превращается в тривиальный процесс ? после внесения необходимых изменений в модель следует только сгенерировать новую базу данных; использование языка OCL позволяет полностью абстрагироваться от SQL-диалекта конкретной СУБД. Язык SQL становится практически ненужным и используется редко, хотя возможность его применения сохраняется;

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

Необходимо отметить, что средства автоматической генерации баз данных и даже классов приложений существовали и прежде, например Rational Rose и PowerBuilder компании Powersoft. Имеется и такой программный продукт, как Delphi RoseLink компании Ensemble Systems1, являющийся своего рода моcтом между CASE-системой Rational Rose и Delphi. Основные его функции ? генерация кода на Object Pascal и обратное проектирование. Однако генерируемый с его помощью код не содержит реализацию функциональности, а генерируются только описания ? определения классов, интерфейсов и т.д.

Bold for Dephi отнюдь не ограничивается этим, поскольку, интегрируясь в Borland Delphi, он предоставляет разработчику полный набор визуальных и невизуальных компонентов, достаточный для реализации объектного пространства (Object Space) приложения. Поэтому разработчик получает возможность работать не на уровне кода и таблиц БД, а на уровне объектов внутри этого объектного пространства.

Другими словами, используя Bold, разработчик:

не создает базу данных, а формирует модель приложения на языке UML; работает не с таблицами, полями и ключами базы данных, а с объектами созданной им модели приложения ? классами и их атрибутами; подключает визуальные компоненты для отображения данных не к таблицам БД, а к объектам модели; не пишет запросы на языке SQL, а формирует предложения на гибком и мощном диалекте языка OCL.

Как принято говорить, в этом случае разработка ведется на бизнес-уровне.

Принципиальным моментом при использовании Bold является трехуровневая схема создания приложения, которая включает уровень данных, бизнес-уровень и графический интерфейс пользователя. И в данном случае это ? не абстракция, а реальность, воплощенная в конкретные наборы компонентов Bold, с которыми имеет дело разработчик. Так, если обычно при создании приложения баз данных в Delphi визуальные компоненты подключаются к полям или таблицам БД, то при работе с Bold все они подключаются к промежуточному слою ? к объектам бизнес-уровня. Формирование бизнес-уровня приложения является одной из основных функций Bold. Другая важнейшая функция ? обеспечение взаимодействия между бизнес-уровнем и уровнем данных (СУБД), то есть объектно-реляционное отображение и взаимодействие. Такое взаимодействие включает автоматическую, прозрачную для разработчика, трансляцию OCL в операторы SQL, выполнение операций с таблицами БД и т.д. (подробнее обо всем этом будет рассказано в следующих частях статьи).

И наконец, основное отличие Bold от упомянутых выше CASE-средств состоит в том, что Bold работает не только на этапе разработки приложения, но и на этапе его исполнения. Именно это качество позволяет называть Bold инструментом реализации MDA. Любое CASE-средство, сколь бы совершенным оно ни было, предназначено для реализации только этапов проектирования и моделирования. Оно, конечно, может включать также возможности генерации кода и генерации базы данных, но после запуска приложения CASE-система уже не функционирует, ее «присутствие» на этом этапе по сути уже не ощущается. Функционирование же Bold коренным образом отличается от функционирования других CASE-средств: сохраняя модель приложения в исполняемом файле, Bold на этапе выполнения приложения использует эту модель для управления бизнес-уровнем, для контроля целостности объектного пространства, для управления взаимодействием бизнес-уровня с уровнем данных и графическим интерфейсом.

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

Резюмируя вышесказанное, можно дать следующее определение этому программному продукту: Bold for Delphi ? это, с одной стороны, среда разработки, позволяющая на этапе создания формировать объектное пространство (бизнес-уровень) и реализовывать бизнес-логику приложения, а с другой ? программная система, обеспечивающая на этапе выполнения функционирование бизнес-уровня и его интеграцию с СУБД (уровнем данных) и графическим интерфейсом пользователя.

До появления Bold существовал разрыв между средствами проектирования и моделирования, такими как Rational Rose, и RAD-системой Borland Delphi. Можно было и тогда создавать красивые схемы-модели в Rational Rose, но, переходя в среду Delphi, разработчик вынужден был реализовывать эти схемы вручную. Сейчас, после появления Bold, использование UML-редакторов, например Rational Rose (как уже говорилось, в составе Bold имеется и собственный UML-редактор, однако он функционирует только в текстовом режиме, что при создании больших моделей не всегда удобно), стало неотъемлемым этапом разработки, от которого напрямую зависит поведение и функциональные возможности создаваемого приложения.

Включение Bold в состав Delphi позволяет говорить, что из RAD-средства (RAD, Rapid Application Development ? быстрая разработка приложений) Delphi превращается в интегрированную среду разработки, поддерживающую полный жизненный цикл создания приложений (Application Lifecycle Management, ALM).



Инсталляция Bold. Размещение компонентов


2. Обратите внимание на то, что Bold не входит в версию Delphi 7 Studio Enterprise.

При инсталляции Delphi 7 Studio Architect Trial Edition на экране появится заставка (рис. 1), позволяющая выбрать устанавливаемые продукты: Delphi 7, ModelMaker и собственно Bold. Продукты устанавливаются в порядке их перечисления. После установки Delphi 7 рекомендуется установить также UML-редактор Model Maker, позволяющий создавать диаграммы классов и взаимодействовать с Bold (хотя это и необязательно). Если при инсталляции Bold будет предложено выбрать состав установки, нужно пометить все компоненты. Кстати, на объем требуемого пространства на жестком диске для Bold этой версии он составляет более 140 Мбайт.

После установки Bold на палитре компонентов Delphi появятся новые закладки, в частности:

BoldHandles BoldPersistence (рис. 3) ? содержит невизуальные компоненты для взаимодействия с уровнем данных (СУБД). Уровень данных в Bold носит название Persistence Layer; BoldControls (рис. 4) ? содержит визуальные и невизуальные компоненты для создания графического интерфейса пользователя; BoldMisc (рис. 5) ? содержит прочие вспомогательные визуальные и невизуальные компоненты; Bold COM Handles (рис. 6) ? содержит невизуальные компоненты для формирования бизнес-уровней многозвенных приложений. Подобные приложения позволяют распределять функциональность между звеньями таким образом, что появляется возможность создавать так называемые тонкие клиенты баз данных, которые характеризуются минимальными требованиями с точки зрения наличия средств доступа к данным. Более подробная информация об этом будет представлена в последующих статьях; Bold COM Controls (рис. 7) ? содержит визуальные и невизуальные компоненты для формирования графического интерфейса многозвенных приложений.

Следует иметь в виду, что визуальные компоненты Bold взаимодействуют не с данными, а с объектами бизнес-уровня. По этой причине Bold имеет собственные аналоги таких визуальных компонентов, как метка (Label), сетка (Grid) и т.д., обладающие дополнительными, необходимыми для взаимодействия свойствами. Впрочем, в дальнейшем будет показано, что при желании во многих случаях можно использовать и обычные компоненты, а также компоненты сторонних производителей.

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



Язык унифицированного моделирования UML


Причиной появления Unified Modelling Language (UML) стала необходимость унифицированного подхода к описанию моделей бизнес-приложений в начале 90-х годов ХХ века. К тому времени появилось несколько десятков вариантов инструментария для создания подобных моделей, но все они были не согласованы между собой, что мешало разработке CASE-средств и вносило некоторую путаницу. Напомним читателю, что CASE-средства (Computer Aided Software Engineering ? разработка программного обеспечения с помощью компьютера, то есть автоматизированная разработка программного обеспечения) в тот период играли в основном роль графической надстройки над СУБД, позволяющей автоматически генерировать базу данных по ее графической схеме. У истоков разработки языка UML стояла компания Rational Software, разработавшая одно из первых CASE-средств ? Rational Rose. В 1995 году консорциум OMG включился в работу по стандартизации UML, затем к разработке языка активно подключились и другие компании, и, после выхода нескольких промежуточных версий, в 1997 году появилась версия UML 1.0.

В настоящее время последней стандартизованной OMG версией является UML 1.4, завершается разработка версии 2.0. Развитие UML сегодня координирует консорциум OMG, который считает разработку и продвижение этого языка своим стратегическим направлением.

Перечислим характерные свойства UML:

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

Язык UML базируется на объектно-ориентированном подходе и включает диаграмму классов для описания структуры и состава модели. Диаграмма классов является основой для формирования модели приложения и играет важнейшую роль при работе с продуктом Bold for Delphi.

В рамках UML существует и развивается формальный язык для текстового описания условий, накладываемых на классы модели. Он получил название OCL (Object Constraint Language ? язык объектных ограничений). OCL также играет чрезвычайно важную роль при практическом использовании MDA в Delphi (описанию OCL будет посвящена одна из частей данного цикла).



в настоящее время сообществом ведущих



в настоящее время сообществом ведущих мировых производителей программного обеспечения активно разрабатывается и продвигается технология MDA, в основе которой лежит принцип создания приложений, управляемых моделью. Поведение таких приложений определяется заложенными в модель правилами, и, при изменении модели, поведение MDA-приложений изменяется без изменения программного кода приложения. Код приложений и база данных для MDA-приложений генерируются автоматически в соответствии с моделью; в основе создания модели приложения лежит язык унифицированного моделирования UML, позволяющий в графической наглядной форме формировать состав и структуру модели и налагать определенные условия и ограничения посредством подмножества UML ? формального языка OCL; компания BoldSoft MDE AB, не дожидаясь окончания процесса стандартизации технологии MDA, разработала программный продукт ? Bold for Delphi, предназначенный для реализации MDA в среде Delphi. В настоящее время Bold является продуктом фирмы Borland и входит в состав Borland Delphi 7 Studio Architect; использование Bold позволяет разработчику сконцентрироваться на логике работы приложения (бизнес-уровне), абстрагируясь в достаточной степени от специфики используемой СУБД. Bold обеспечивает создание объектного пространства на этапе разработки, функционирование бизнес-уровня на этапе эксплуатации, автоматически интегрируя бизнес-уровень с СУБД и графическим интерфейсом пользователя. Кроме того, мы кратко рассмотрели инсталляцию продукта и общую классификацию основных его компонентов. Тому, как работает Bold на практике, будет посвящена следующая часть данной статьи.
Продолжение следует.
КомпьютерПресс 2'2003

Модификация модели приложения


Посмотрим, что произойдет, если мы изменим бизнес-правило, ограничивающее количество авторов у книги единственным автором, а вместо него сформулируем следующее бизнес-правило: «каждая книга может иметь несколько авторов». Для этого запустим редактор моделей, выберем роль byAuthor и установим для нее свойство Multiplicity равным «1..*» (рис. 19).

Далее удалим файл 1.xml из рабочей папки. Запустим приложение на выполнение. Опять добавим указанных авторов с помощью первого навигатора, а с помощью второго навигатора ? книгу «12 стульев». Кликнем дважды на названии книги и убедимся, что автоформа изменилась (рис. 20).

Теперь вместо одного окошка для имени автора, как на рис. 18, мы обнаружим форму, позволяющую назначать данной книге произвольное число авторов. Перетащим последовательно обоих авторов на автоформу ? и теперь у книги «12 стульев» имеются в наличии оба автора.

Только что мы с вами наблюдали на практике характерную и основную черту MDA-приложений, а именно: поведение MDA-приложения определяется не кодом приложения, а UML-моделью. Мы не исправили ни строчки кода (да и кода-то, строго говоря, нет, по крайней мере, написанного нами), но получили новую функциональность нашей программы. Почему? Потому что мы изменили модель приложения и этого оказалось вполне достаточно для изменения поведения приложения.

Продолжим изучение свойств созданного приложения. Добавим нового автора ? Драйзер. Добавим во вторую таблицу книги ? «Американская трагедия», «Гений», «Финансист». Кликнем дважды на имени автора Драйзер, откроем закладку writes на появившейся форме автора и перетащим с помощью мыши эти три книги из главной формы на форму автора (рис. 21).

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

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

Попробуем изменить ситуацию. Сформулируем измененное ранее бизнес-правило немного иначе: «каждая книга должна быть написана по крайней мере одним автором». Таким образом, мы говорим, что не должно существовать книг, у которых отсутствует хотя бы один автор.

Для реализации этого правила снова обратимся к нашей модели, выберем роль ассоциации writes и изменим значение параметра Delete Action с <Default> на Cascade (рис. 22).

Снова запустим наше приложение: добавим автора ? Драйзер, которого мы удалили в прошлый раз, назначим ему уже известным способом три книги ? «Американская трагедия», «Гений» и «Финансист». А теперь попытаемся снова удалить автора из главной формы и убедимся, что после его удаления из правого списка книг также исчезли и написанные им книги. Опять мы увидели, что изменение в модели приложения непосредственно сказывается на его поведении.



Подведение итогов


Оценим, уже с новой позиции, функциональность созданного приложения. Мы построили с точки зрения прикладных возможностей классическое приложение для работы с локальной базой данных, которая содержит связи типа «многие-ко-многим». При этом:

не создавалась собственно база данных, а создавалась модель; не создавались таблицы и поля, первичные и вторичные ключи и индексы, а создавались классы, содержащие атрибуты, и ассоциации, содержащие роли; не создавались связи типа «главный—подчиненный» и «многие-ко-многим», а назначались размерности ролей; не использовался язык SQL; не программировались формы для ввода и редактирования данных, а были созданы автоматически; не программировался интерфейс drag&drop.

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

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

Стоит также отметить, что мы пошли не самым оптимальным путем, когда использовали встроенный в Bold редактор моделей, который, к сожалению, не является графическим. Как будет рассказано в дальнейшем, использование графических UML-редакторов может существенно облегчить и еще более ускорить работу по созданию и модификации модели приложений.



Работа с приложением


Казалось бы, ничего особенного мы не получили. Создали, пусть и необычным способом, вполне обычную форму для ввода и редактирования данных по авторам. (Кстати, почему-то при этом мы не сделали форму ввода для названий книг, на что, видимо, уже обратил внимание проницательный читатель.) Но первое впечатление в данном случае обманчиво. Чтобы начать знакомство с «магией» Bold, добавим к нашему приложению один программный модуль: допишем в объявление Uses нашего модуля Unit1 модуль с названием BoldAFPDefault и запустим приложение на исполнение.

Введем в список авторов несколько значений (см. рис. 13). Теперь выберем автора Драйзер в таблице и кликнем дважды мышью по соответствующему значению, после чего откроется новое окно. Мы не создавали эту форму ? за нас все сделал Bold. Форма имеет несколько закладок, одна из которых называется writes. Перейдя на эту закладку, мы обнаружим форму для ввода названий книг. Если, не закрывая новой формы, перейти на другого автора и опять кликнуть дважды на имени автора, то появится еще одна новая форма для ввода книг, написанных эти автором, а затем повторить все действия с третьим автором. Таким образом вы можете ввести названия книг, написанных всеми тремя авторами (рис. 15).

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

Проницательный читатель без труда обнаружит, что название writes закладки на автоформе есть не что иное, как название соответствующей роли ассоциации в нашей модели. А где же в таком случае название второй роли? Для того чтобы увидеть его, выберем какую-нибудь книгу на автоформе и дважды кликнем на ее названии (рис. 16). При этом появится новая форма, на которой мы увидим название книги, а под ней ? серое поле с именем автора, слева от которого расположен заголовок byAuthor ? это и есть вторая роль нашей ассоциации.

Учитывая, что мы практически не писали кода, не программировали события drag&drop мыши и не создавали формы для ввода названий книг, можно констатировать, что полученное приложение обладает очень неплохой функциональностью.

Однако будем двигаться дальше. Чтобы видеть более полную картинку происходящего, добавим на главную форму визуальные компоненты BoldGrid2 и BoldNavigator2 с закладки BoldControls для отображения списка книг и управления им. Для получения списка книг из бизнес-уровня нам понадобится также второй компонент BoldListHandle2 со страницы BoldHandles палитры компонентов. В инспекторе объектов установим значение свойства RootHandle этого компонента равным BoldSystemHandle1 (его можно ввести вручную или выбрать из выпадающего списка); значение свойства Expression установим равным OCL-выражению Book.allinstances. Свойству BoldHandle визуальных компонентов BoldGrid2 и BoldNavigator2 присвоим значение BoldListHandle2, после этого кликнем правой кнопкой мыши на компоненте BoldGrid2 и выберем пункт Create Default Columns, то есть создадим столбцы по умолчанию. В результате у компонента BoldGrid2 появится заголовок столбца btitle (рис. 17).

Конечно, вы уже поняли, что названия столбцов aname и btitle в таблицах BoldGrid1 и BoldGrid2 Bold автоматически выбирает из назначенных нами атрибутов в классах Author и Book, когда мы создаем столбцы по умолчанию. Но это, естественно, не означает, что мы не можем настроить таблицы BoldGrid по-другому (например, присвоить им русскоязычные названия) ? просто сейчас мы выбираем наиболее простой и быстрый путь.

Запустим наше усовершенствованное приложение на выполнение. Добавим двух авторов ? Ильф и Петров ? с помощью навигатора. Добавим с помощью второго навигатора книгу «12 стульев». Кликнем дважды на названии этой книги (рис. 18). Перетащим с помощью мыши автора Ильф на автоформу на серое поле с именем автора. Мы увидим, что книге «12 стульев» был присвоен автор Ильф. Перетащим автора Петров на то же место и увидим, что автором книги стал Петров, а Ильф исчез. Мы с вами знаем, что данную книгу на самом деле написали оба автора, но при создании модели мы ввели бизнес-правило: «у каждой книги должен быть только один автор». Поэтому наше приложение, функционируя в рамках заданной модели, не позволяет добавить второго автора.




На практике показано, что MDA-приложение организовано в виде «трехслойного пирога» и даже самое простейшее такое приложение содержит три уровня: уровень данных, бизнес-уровень и прикладной уровень (графический интерфейс). Продемонстрировано, что графический интерфейс обращается к данным через посредника ? бизнес-уровень, для чего существуют специальные невизуальные компоненты. Показано, что, с одной стороны, функционирование MDA-приложений невозможно без создания модели, а с другой ? что поведение приложения определяется этой моделью не абстрактно, а совершенно конкретно. Даже на таком простом приложении продемонстрированы преимущества использования MDA-технологии. Экстраполируя рассмотренный простой пример на корпоративные информационные системы, содержащие сотни классов и тысячи атрибутов, вы можете уже сейчас представить, что описываемая технология позволяет на порядок повысить эффективность их разработки и сопровождения.
КомпьютерПресс 4'2003

Создание бизнес-уровня


На панели компонентов Delphi выберем закладку <BoldHandles>. Поместим на форму следующие три компонента с закладки <BoldHandles>:

BoldModel1 (компонент, обеспечивающий хранение модели); BoldSystemHandle1 (основной компонент ? описатель объектного пространства); BoldSystemTypeInfoHandle1 (основной компонент ? описатель типов модели).

Эти компоненты реализуют основу объектного пространства (Object Space) нашего приложения. Чтобы правильно функционировать, они должны быть связаны между собой и настроены так, как это будет описано ниже.

Для компонента BoldSystemTypeInfoHandle1 в инспекторе объектов следует установить свойство BoldModel равным BoldModel1 (оно появится в выпадающем списке). Кроме того, установим свойство UseGeneratedCod равным False (рис. 1). Такая установка означает, что генерация кода для классов модели производиться не будет.

Для компонента BoldSystemHandle1 в инспекторе объектов установим свойство SystemTypeInfoHandle равным BoldSystemTypeInfoHandle1 (оно также появится в выпадающем списке). А свойство AutoActivate установим равным True (рис. 2). Таким образом обеспечивается активизация объектного пространства по первому требованию.

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



Создание графического интерфейса


Итак, к настоящему моменту мы создали основу бизнес-уровня, то есть модель приложения. Дошла очередь до графического интерфейса.

Сразу стоит напомнить об одном важном обстоятельстве, упомянутом в первой части статьи. При работе с Bold следует привыкнуть к наличию бизнес-уровня в вашем приложении, который существует не абстрактно, а заставляет нас использовать специальные компоненты для доступа к каким-либо структурам или данным. Эти компоненты не являются визуальными, а служат своеобразными трансляторами и реализаторами запросов, которые посылает графический уровень к бизнес-уровню для получения от последнего необходимой информации. Впоследствии мы убедимся, что наличие бизнес-уровня обеспечивает чрезвычайную гибкость и удобство, а сейчас используем один из таких невизуальных компонентов для поддержки нашего интерфейса. Перейдем на закладку BoldHandles и поместим на форму компонент BoldListHandle1. В инспекторе объектов установим значение свойства RootHandle равным BoldSystemHandle1 (его можно ввести вручную или выбрать из выпадающего списка).

Для свойства Expression введем выражение Author.allinstances (рис. 11). Кстати, это выражение представляет собой запрос к бизнес-уровню на языке OCL (Object Constraint Language), который в данном случае означает: «хочу получить все экземпляры класса Author». Подробнее об OCL мы поговорим далее.

Теперь создадим собственно графический интерфейс, для чего на закладке BoldControls имеется довольно много компонентов. Мы выберем два из них ? BoldGrid и BoldNavigator, которые являются аналогами соответствующих компонентов доступа к данным со страницы Data Controls. Свойству BoldHandle обоих визуальных компонентов присвоим значение BoldListHandle1, после этого кликнем правой кнопкой мыши на компоненте BoldGrid1 и выберем пункт Create Default Columns (создать столбцы по умолчанию). В результате у компонента BoldGrid1 появится заголовок столбца aname (рис. 12).

Вот и все: мы создали наше первое ? очень простое ? приложение и можем его запустить на выполнение.

Можно также добавлять авторов (рис. 13), удалять или редактировать их. Но, как легко убедиться, после закрытия приложения и его повторного запуска все введенные данные исчезают. Это происходит потому, что наше приложение пока не содержит уровня данных (Persistence Layer).



Создание модели приложения


рис. 3), позволяющего создавать UML-модели (в текстовом режиме), а также обеспечивающего реализацию основных функциональных возможностей Bold на этапе разработки приложения ? таких как экспорт и импорт моделей из других редакторов, модификация, верификация и тонкая настройка моделей, генерация баз данных и кода. На настоящем этапе мы используем его для создания модели нашего простого приложения.

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

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

Таким образом, после некоторой дальнейшей конкретизации неформально будущую модель приложения можно описать следующим набором бизнес-правил:

описываемая предметная область включает множество авторов и множество книг; автор однозначно идентифицируется текстовым атрибутом ? именем; книга однозначно описывается текстовым атрибутом ? названием; автор может написать много книг; книга может быть написана только одним автором.

Назначение UML-редактора ? преобразовать неформальное описание бизнес-правил в формальную модель на языке UML (рис. 3).

Теперь можно приступить к созданию модели. Правой кнопкой мыши кликнем на пункте LogicalView в верхней части левой панели редактора и во всплывающем меню выберем пункт NewClass (создание нового класса). Проделаем эту операцию еще два раза (рис. 4).

Новые классы по умолчанию получили имена NewClass, NewClass_1, NewClass_2. Для удобства дальнейшей работы переименуем их. Для этого в левой панели редактора выберем курсором мыши пункт NewClass, перейдем в правую панель редактора и введем в поле Name имя нашего класса ? Author. Второму классу присвоим имя Book, а третьему ? имя AuthorBook. После этого у нас должна получиться модель, представленная на рис. 5.

Теперь создадим атрибуты наших классов. Автор книги, как мы договорились раньше, описывается в нашей модели своим именем, а книга ? названием. Следовательно, класс Author будет иметь один атрибут ? назовем его aname, класс Book будет иметь также единственный атрибут, которому дадим название btitle. Класс AuthorBook пока трогать не будем. Для создания атрибутов выберем в левой панели редактора нужный класс, кликнем правой кнопкой мыши и из всплывающего меню выберем пункт New Attribute. Создадим по одному новому атрибуту для классов Author и Book, а затем раскроем дерево модели на левой панели редактора, как показано на рис. 6.

По умолчанию новые атрибуты получили имена (каждый в своем классе) ? NewAttribute. Переименование атрибутов осуществляется так же, как и переименование классов (рис. 7).

Теперь вспомним о третьем классе, созданном нами, ? AuthorBook. В принципе, как будет показано в дальнейшем, для такой простой модели, как наша, совсем необязательно создавать этот класс вручную ? это можно сделать автоматически. Но на данном этапе этот класс будет полезен для иллюстрации возможностей описываемой технологии. Смысл создания этого класса ? обеспечение связи между авторами и книгами, поэтому AuthorBook является не обычным классом, а носителем для ассоциации между классами Author и Book. Однако прежде чем определять этот класс в качестве носителя ассоциации, необходимо создать саму ассоциацию. Для этого поступаем так же, как и при создании новых классов: выбираем пункт LogicalView в дереве модели на левой панели редактора, после чего нажимаем правую кнопку мыши, но из всплывающего меню теперь выбираем пункт New Association, затем раскрываем дерево модели (рис. 8).

В правой панели редактора в окошке с именем класса мы видим, что имя класса ? носителя для новой ассоциации (ей автоматически присвоено имя NewAssociation) отсутствует (<none>). Из выпадающего списка в этом окошке назначим для класса ассоциации имя ранее созданного нами класса ? AuthorBook. Далее в дереве модели мы видим, что созданная ассоциация имеет два подпункта: AssociationEnd0 и AssociationEnd1, представляющие собой автоматически созданные названия для ролей нашей ассоциации. Определим эти роли: выделим роль ассоциации AssociationEnd0, в правой панели редактора введем в поле Name имя роли byAuthor, а в поле Class выберем из выпадающего списка класс Author; установим значение поля Multiplicity в «1..1» и снимем флажок Embed (рис. 9).

Затем выделим роль ассоциации AssociationEnd1, в правой панели редактора введем в поле Name имя роли writes, а в поле Class выберем из выпадающего списка класс Book. Далее установим значение поля Multiplicity в «1..*» и снимем флажок Embed (рис. 10).

Теперь немного порассуждаем, что именно мы только что сделали с ролями нашей ассоциации и почему. Как говорилось выше, в нашей модели принято упрощающее предположение о том, что книга может быть написана только одним автором. Именно по этой причине мы установили свойство Multiplicity у роли byAuthor в значение «1..1» (см. рис. 9), то есть один и только один (автор). Однако наша модель по умолчанию допускает, что автор может написать много книг, и поэтому на другом конце нашей ассоциации writes свойству Multiplicity назначено значение «1..*» (см. рис. 10), другими словами, одна, две.. много (книг). Теперь осталось только понять, почему «1..1» относится именно к автору, а «1..*» ? к книгам. Но ведь эту привязку сделали мы сами, когда назначали классы для ролей!



Создание уровня данных


Чтобы не отвлекаться сейчас на создание базы данных, на настройки псевдонимов и прочих вещей, для построения уровня данных используем очень удобное средство, встроенное в Bold, ? хранение данных в XML-документе. Для этого с закладки BoldPersistence поместим на форму компонент BoldPersistenceHandleFileXML1 (рис. 14).

Для настройки компонента в инспекторе объектов просто установим значение его свойства BoldModel равным BoldModel1, а свойства FileName (имени файла) ? например 1.xml (рис. 14). Кроме того, для компонента BoldSystemHandle1 установим в инспекторе объектов значение свойства PersistenceHandle равным имени компонента BoldPersistenceHandleFileXML1.

Чтобы наше приложение сохраняло свои данные, в процедуру обработки события OnClose нашей формы следует ввести одну строку кода:

procedure TForm1.FormClose(Sender: TObject; var Action: TCloseAction); begin BoldSystemHandle1.UpdateDatabase; end;

Теперь можно убедиться, что наше приложение приобрело способность сохранять данные. Пришло время подробнее изучить его возможности.



Borland MDA


Как уже говорилось, компания BoldSoft была приобретена фирмой Borland и в последнее время название продукта Bold for Delphi все чаще заменяется на Borland MDA. Более того, предыдущие версии Bold for Delphi в настоящее время недоступны для разработчиков, и поэтому единственным продуктом реализации MDA в Delphi сейчас является Borland Delphi 7 Studio Architect (существует также возможность обновления версии Borland Delphi 7 Studio Enterprise). Все текущие и последующие обновления Borland MDA осуществляет Borland (недавно вышла последняя обновленная версия Bold for Delphi 4.0.0.21, доступная на Web-сайте компании Borland зарегистрированным пользователям).

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

Однако необходимо отметить, что на пути практического овладения технологией Borland MDA разработчик может столкнуться с некоторыми трудностями.

Во-первых, Borland MDA ? это сложная и объемная программная система. В простом примере, рассмотренном в предыдущей части статьи, из всего арсенала ее возможностей был использован только весьма незначительный процент. На самом деле Borland MDA включает около 1700 новых классов, содержащих тысячи атрибутов и методов. Достаточно сказать, что встроенная справка по продукту насчитывает порядка 10 тыс. статей.

Во-вторых, в настоящее время технической информации о Borland MDA явно недостаточно. Несмотря на большой объем встроенной справки, она, к сожалению, весьма лаконична. Практически единственным полезным источником конкретной информации о продукте в настоящее время являются Интернет-конференции на новостном сервере Borland (<forums.borland.com>), где размещены две основные группы новостей по Borland MDA: borland.public.delphi.modeldrivenarchitecture.general и borland.public.delphi.modeldrivenarchitecture.thirdpary. Кроме того, полезная коллекция ссылок по данной теме собрана на сайте www.boldbox.com. Остается надеяться, что в дальнейшем ситуация изменится к лучшему.

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

Далее в этой и в последующих частях статьи будут рассмотрены (с возможной степенью детальности, ограниченной рамками журнальных публикаций) основы Borland MDA. И начнем, в полном соответствии с названием технологии — Model Driven Architecture, с модели приложения.



Основы создания диаграммы классов


Диаграмма классов является основным источником платформенно-независимой информации (PIM) для формирования модели приложения в Borland MDA. Она занимает центральное место в объектно-ориентированном анализе и проектировании (ООАП) программных систем. Диаграмма классов описывает статическую структуру системы, то есть состав элементов (классов), состав их атрибутов и операций, а также связи между классами (отношения). В ней не содержится информация о развитии системы во времени.

В основе диаграммы классов лежит понятие класса. Не углубляясь сейчас в детали, будем считать, что понятие класса знакомо разработчикам, использующим методологию объектно-ориентированного программирования. Итак, класс изображается в UML-модели в виде прямоугольника, разделенного на две или три части (рис. 1). В верхней части отображается имя класса — это обязательный параметр. Во второй сверху части отображаются атрибуты класса, возможно — с указанием их типа и значения по умолчанию. В нижней части класса отображаются названия операций и, возможно, списки аргументов и тип возвращаемого результата. Атрибутов и операций у класса может быть несколько. С точки зрения программиста атрибуты и операции аналогичны соответственно свойствам и методам в объектно-ориентированном программировании (ООП). Класс, который не может иметь ни одного объекта (экземпляра), является абстрактным. В этом случае его название отображается курсивом.

Отношения (relationship) между классами в UML сводятся к четырем базовым типам:

• зависимость (dependency);

• ассоциация (association);

• обобщение (generalization);

• реализация (realization).

Рассмотрим сейчас только два из них — ассоциацию и обобщение.

Ассоциация указывает на наличие некоторой связи между классами, например, «отдел—сотрудники». Она отображается сплошной линией (рис. 2). Линия ассоциации может соединять два (бинарная ассоциация) или более (N-ассоциация) классов. В последнем случае место соединения нескольких ассоциаций обозначается ромбом (на рис. 2 представлена бинарная ассоциация). Ассоциация может иметь имя, в этом случае оно располагается над линией ассоциации (на рис. 2 имя отсутствует). Концам линии ассоциации — ролям — даются названия. В данном случае ассоциация обладает ролями «Включает» и «Работает в». Кроме того, концы линии ассоциации имеют обозначения размерности, которые указывают на кратность отношения. Так, из рис. 2 можно сделать следующие выводы относительно описываемой модели (то есть восстановить заложенные в нее бизнес-правила):

• каждый отдел включает одного или несколько сотрудников (размерность «1..n»);

• каждый сотрудник работает только в одном отделе (размерность «1»).

Легко заметить кажущуюся аналогию между ассоциацией в UML и реляционными отношениями типа «один ко многим» и «многие ко многим» в СУБД. Однако далеко эту аналогию провести не удастся. Во-первых, в реляционной БД связь «многие ко многим» не может соединять две таблицы — для этого обязательно требуется еще одна промежуточная таблица. В UML же это вполне допустимо. Во-вторых, кратность в UML в принципе может быть любой, в том числе и нулевой. Так, если бы мы на конце ассоциации, указывающей на сотрудника, написали «0..n», то это означало бы, что могут существовать отделы, не имеющие ни одного сотрудника. А если бы мы задали кратность «15..50», то это говорило бы о том, что численность сотрудников в отделе не может быть меньше 15 и больше 50.

Нельзя не упомянуть и еще об одном важном варианте использования ассоциации. Рассмотрим UML-модель, изображенную на рис. 3. В ней оба конца ассоциации подключены к одному и тому же классу и определяют следующие бизнес-правила:

• каждый сотрудник может находиться в подчинении только у одного сотрудника (например, в подчинении у руководителя) либо не подчиняться ни одному из сотрудников (если он сам является руководителем);

• каждый сотрудник может руководить несколькими сотрудниками (если он является руководителем) либо не руководить ни одним (если он является рядовым сотрудником).

Использование ассоциаций в таком варианте нередко встречается при создании моделей приложений.

Вторым типом рассматриваемых отношений является обобщение, или генерализация. Данный тип отношения указывает, что между классами существует связь типа «предок—потомок», аналогичная отношению наследования в ООП. Такая связь отображается линией со стрелкой в форме пустого треугольника, причем треугольник-стрелка указывает на «предка», то есть на родительский класс. Так, на рис. 4 показано отношение обобщения между родительским классом «Человек» и дочерним классом «Гражданин». При этом необходимо учитывать, что все атрибуты класса-родителя автоматически принадлежат и классу-потомку, хотя в нем не отображаются. Поэтому класс «Гражданин», кроме представленных в нем атрибутов «Гражданство» и «Номер удостоверения личности», будет включать и атрибуты «Имя», «Вес» и «Рост». Отношения обобщения довольно часто используются при построении моделей, при этом в качестве класса-родителя нередко выступает какой-нибудь абстрактный класс.

Итак, мы ознакомились с базовыми понятиями, используемыми при построении диаграмм классов. В дальнейшем мы поговорим и о некоторых других возможностях и свойствах UML.



Роль модели в Bold


• определяет состав и тип классов и атрибутов классов;

• фиксирует наличие связей между классами, определяет тип этих связей и их размерность;

• определяет условия и ограничения, накладываемые на классы и их атрибуты; такие условия формируются на диалекте языка OCL, встроенного в Bold;

• содержит информацию для адаптации к среде разработки Delphi в виде набора специальных тэг-параметров;

• содержит информацию для адаптации к СУБД — также в виде набора специальных тэг-параметров.

В Bold, таким образом, отсутствует четкое разделение между PIM (Platform Independent Model)- и PSM (Platform Specific Model)-моделями MDA (см. первую часть статьи), а вся необходимая информация содержится в одной общей модели. Функции PSM-модели в основном выполняет набор тэг-параметров (tagged values), которые будут описаны ниже. Кроме того, такие функции могут выполнять и некоторые компоненты Bold, являющиеся адаптерами СУБД (вопросам взаимодействия Borland MDA и СУБД будет посвящена отдельная часть данной статьи).

Bold использует модель для реализации следующих основных функций:

1. Генерация кода. Под генерацией кода понимается автоматическое создание модулей описаний (*.inc-файлов) и функциональных модулей (*.pas-файлов) на языке Object Pascal, содержащих полную реализацию классов модели приложения. Строго говоря, сам по себе Bold не нуждается в генерации кода. Как мы уже видели на примере простого приложения и увидим в дальнейшем, можно создавать достаточно серьезные приложения, вообще не используя генерацию кода. Однако в некоторых случаях она бывает необходимой. Общая стратегия здесь выглядит примерно так: если поддерживаемых Bold возможностей языка OCL недостаточно для реализации, например, желаемых методов или вычисляемых атрибутов на бизнес-уровне, то разработчик вправе опуститься на уровень программного кода. Кроме того, генерация кода необходима, если классы модели содержат операции. Генерацию кода можно произвести из встроенного редактора модели (Model Editor) на этапе разработки приложения. Кроме генерации кода, Bold обеспечивает и возможность генерации интерфейсов, необходимых для функционирования распределенных DCOM-приложений.

2. Генерация схемы базы данных. Структура базы данных (то есть набор описаний таблиц, полей, индексов и ключей) может быть сгенерирована автоматически как из встроенного редактора модели на этапе разработки, так и программно во время выполнения приложения. Bold также поддерживает синхронизацию структуры базы данных с изменяющейся во времени моделью приложения (Model Evolution — эволюция модели), при этом сохраняется уже имеющаяся в БД информация. Такая возможность в Bold носит специальное название — эволюция базы данных (DataBase Evolution). В дальнейшем эти вопросы мы рассмотрим подробнее. Необходимо иметь в виду, что между составом классов модели и составом таблиц генерируемой базы данных нет взаимно-однозначного соответствия. Во-первых, Bold использует ряд таблиц БД для собственных нужд и создает их автоматически. Во-вторых, не все классы модели требуют сохранения информации объектов в БД (persistent class), а могут быть транзиентными (transient) классами, кроме того, даже в persistent-классах модели часто присутствуют вычисляемые (derived) атрибуты, которые не сохраняются в базе данных. И в-третьих, в ряде случаев принципиально невозможно в реляционной БД реализовать некоторые виды отношений (см. следующий раздел).

3. Интерпретация модели во время выполнения для управления поведением приложения. Вся информация о модели сохраняется в компоненте TBoldModel и на этапе выполнения приложения используется для управления объектным пространством, для контроля его целостности, а также для управления взаимодействием бизнес-уровня с уровнем данных и графическим интерфейсом. Объектное пространство (Object Spase) в Borland MDA является экземпляром модели по аналогии с тем, как объект является экземпляром класса в ООП. Управление каждым объектным пространством обеспечивается компонентом TBoldSystemHandle. Информацию о типах этот компонент получает из компонента TBoldSystemTypeInfoHandle.

В основе создания модели приложения лежит унифицированный язык моделирования (UML), а более конкретно — диаграмма классов. Понимание основ создания диаграммы классов является необходимым условием практического применения MDA. Для полного понимания диаграмм классов необходимо знание UML, систематическое описание которого выходит за рамки данной публикации, однако, с учетом того обстоятельства, что для понимания основ работы с Bold вполне достаточно начальных сведений о диаграмме классов, ниже очень кратко описаны базовые элементы и правила, на основе которых можно будет в дальнейшем формировать модели приложений.



Тэг-параметры (tagged values)


Появление тэг-параметров не случайно. Если UML-модель можно рассматривать как платформенно-независимую PIM-модель, то совокупность тэг-параметров можно считать элементом платформенно-зависимой PSM-модели. Будучи по этой причине связанными с PIM, тэг-параметры классифицируются по принадлежности к элементам иерархической структуры модели. Таким образом, существуют отдельные наборы тэг-параметров для следующих элементов иерархии модели:

• модель в целом;

• класс;

• ассоциация;

• атрибут;

• роль;

• операция.

Тэг-параметры можно также классифицировать и по функциональной принадлежности:

• общие;

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

• используемые для отображения на уровне данных (Persistence Mapping);

• используемые для описания принадлежности к уровню данных (Persistence).

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

Bold включает несколько десятков тэг-параметров. Мы рассмотрим их, когда речь пойдет о технологии разработки моделей приложений для Bold в UML-редакторах. Этой теме будет посвящена следующая часть данной публикации.

КомпьютерПресс 6'2003



Экспорт модели из встроенного редактора в Rational Rose


После настройки модели во встроенном редакторе есть возможность экспортировать ее в Rational Rose. Для этого, как и при импорте, необходимо настроить компонент BoldUMLRoseLink на имя файла модели и экспортировать модель путем нажатия на крайнюю левую кнопку со стрелкой на панели инструментов (рис. 4) или задать в меню <File->Export via Link>. В результате при необходимости произойдет автоматический запуск приложения Rational Rose.

Заметим, что Bold может сохранять и загружать информацию о модели не только в файлах формата Rational Rose (*.mdl), но и в собственном формате (*.bld), в формате XMI, а также в формате ModelMaker (*.mpb). Для использования этих возможностей необходимо из меню встроенного редактора задать File->Open File или File->Save File as…



Настройка Rational Rose


Перед созданием модели в редакторе Rational Rose необходимо обеспечить его предварительную настройку для работы с Borland MDA. Для начала следует убедиться в наличии Bold for Delphi в составе активных расширений (Add-In) Rational Rose. Для этого посредством меню Add-Ins->Add-In Manager… нужно вызвать окно менеджера расширений (рис. 1) и, при необходимости, активизировать пункт Bold for Delphi.

Для настройки под конкретную версию Bold for Delphi используется так называемый файл свойств (Properties Files), именуемый BfD.pty, который создается при инсталляции Bold for Delphi в папке <…\Program Files\Boldsoft\BfDR40D7Arch\Rose\>.

Для его использования необходимо выбрать в Rational Rose пункты меню Tools->Model Properties->Update…, а затем ? вышеуказанный файл. После этого необходимо перейти в окно настроек модели (Tools->Model Properties->Edit), выбрать закладку Bold, далее выбрать из ниспадающего списка параметр Project и установить его свойство (самое нижнее в списке параметров) с названием PTYVersion равным новому значению (на рис. 2 номер версии модели 6.4 соответствует последнему обновлению продукта).

На этом этап настройки Rational Rose закончен. При каждом обновлении версии Bold for Delphi эту настройку следует повторять.



Настройка тэг-параметров модели в Rational Rose


Вернемся в Rational Rose и несколько видоизменим нашу модель, а именно — будем использовать русскоязычные названия классов, атрибутов и ролей (рис. 5).

Сохраним диаграмму классов в файле, например в librus.mdl. Теперь приступим к настройке модели. Для этого воспользуемся некоторыми тэг-параметрами модели, доступ к которым обеспечивается непосредственно из редактора Rational Rose. Кликнем дважды по классу «Автор», перейдем на закладку Bold и модифицируем следующие тэг-параметры (рис. 6):

• DelphiName ? присвоим значение TAuthor; этот тэг-параметр отвечает за преобразование имени класса модели в идентификатор класса, используемый в среде Delphi;

• ExpressionName ? присвоим значение Author; этот тэг-параметр отвечает за преобразование имени класса модели в имя объекта, используемое для обозначения класса в выражениях на языке OCL;

• TableName ? присвоим значение Author; этот тэг-параметр отвечает за преобразование имени класса модели в имя таблицы СУБД, используемой для хранения информации об объектах данного класса.

По умолчанию три вышеуказанных тэг-параметра имели вид T<Name>, <Name>, <Name> соответственно, что означает подстановку вместо <Name> имени класса модели. При этом в нашем случае генерировались бы русскоязычные идентификаторы, что, например, для идентификатора класса в Delphi является недопустимым.

Для решения проблемы автоматического преобразования имен модели из национальных кодировок в составе Bold имеются специальные средства, активизация которых управляется тэг-параметром проекта NationalCharConversion (рис. 2). Однако для их задействования в общем случае придется перекомпилировать исходные тексты Bold. Возможны и другие способы решения этой проблемы, например средствами Rational Rose — путем написания специального скрипта на языке BasicScript3. Естественно, в диаграмме классов можно также использовать только англоязычные имена, тогда редактирование вышеописанных тэг-параметров не потребуется.

Аналогично настроим тэг-параметры в спецификации класса «Книга» и присвоим им следующие значения:

• DelphiName ? присвоим значение TBook;

• ExpressionName ? присвоим значение Book;

• TableName ? присвоим значение Book.

Теперь перейдем к настройке ассоциации. Вызовем ее спецификацию, перейдем на закладку BoldA и изменим значение тэг-параметров следующим образом (рис. 7):

• ColumnName ? присвоим значение Napisal; этот тэг-параметр задействуется Borland MDA в случае единичной кратности роли для обозначения названия столбца таблицы БД;

• ExpressionName ? присвоим значение Napisal;

• DelphiName ? присвоим значение Napisal;

• Embed ? присвоим значение False; этот тэг-параметр определяет «встраивание» роли отношения в класс. Встраиваться могут только роли с единичной кратностью. Для понимания этого проведем аналогию с реляционными СУБД, где в таблицах, связанных отношением «один-ко-многим», в подчиненной таблице должно содержаться («встраиваться») ключевое поле, связанное с уникальным ключом мастер-таблицы. Если два класса связаны ассоциацией, обе роли которой имеют кратность больше 1, то, независимо от значения тэг-параметра embed, Bold обеспечит создание дополнительного связующего класса, как мы уже убедились. Поэтому в данном случае мы могли и не изменять значение этого параметра;

• DeleteAction ? присвоим значение Cascade; с этим тэг-параметром мы уже имели дело, когда создавали простое приложение. Он отвечает за правила удаления подчиненных объектов при удалении главного.

Аналогично изменим значения тэг-параметров и для второй роли нашей ассоциации (рис. 8). Кроме того, в спецификации ассоциации перейдем на закладку Bold и изменим тэг-параметр LinkClassName на значение LinkNapisalNapisana для обозначения имени класса ассоциации.

Теперь сохраним модель, вернемся в наше приложение Delphi, изменим свойство FileName компонента BoldUMLRoseLink1 на имя файла новой модели librus.mdl и произведем импорт. После этого проверим корректность модели (меню Tools->Consistency Check) и убедимся (рис. 9), что среда Borland MDA восприняла все сделанные изменения. При этом названия всех классов и атрибутов остались русскоязычными, хотя на панели дополнительных параметров (она может быть вызвана в Bold-редакторе по нажатии Ctrl+A) мы увидим измененные нами значения.

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



Настройка тэг-параметров модели во встроенном UML-редакторе


Для настройки тэг-параметров модели во встроенном редакторе Borland MDA следует выделить в дереве модели необходимый элемент (класс, атрибут, ассоциацию, роль) и выбрать в меню <Tools->Edit tagged values> (или просто нажать комбинацию клавиш <Ctrl+T>). При этом появится окно редактора параметров, на закладке <Bold> которого представлены все тэг-параметры, относящиеся к выбранному элементу модели (рис. 10). Для редактирования конкретного параметра необходимо выделить его в списке параметров и ввести новое значение в правом окне тэг-редактора. Кроме того, в тэг-редакторе можно удалять тэг-параметры или добавлять новые (пользовательские) параметры. Значения тэг-параметров доступны как во время проектирования приложения, так и программно, во время его выполнения.

Как уже говорилось, наборы тэг-параметров привязаны к уровням иерархической структуры модели и для каждого уровня этой структуры имеется собственный набор таких параметров. В табл. 1 приведено краткое описание функционального назначения некоторых из них. Ряд параметров (DelphiName, ExpressionName и т.д.) был описан выше и в таблице не приводится.

Ряд тэг-параметров предназначен для настройки самого верхнего уровня иерархии — уровня модели. Некоторые из них представлены в табл. 2.



Rational Rose как средство разработки моделей приложений для Borland MDA


В предыдущей части были рассмотрены основные функции модели приложения в Borland MDA, а также кратко описаны элементы диаграммы классов UML. Настоящая статья посвящена практической разработке модели MDA-приложения в графических UML-редакторах на примере CASE-системы Rational Rose. Следует отметить, что после включения в версию 4 Bold for Delphi полной поддержки функций импорта и экспорта модели в формате XMI (XML Metadata Interchange — язык обмена метаданными XML) появилась возможность разрабатывать модели приложений для Borland MDA в любом UML-редакторе, поддерживающем этот формат (например, в PowerBuilder компании Sybase). Кроме того, в состав Delphi 7 Studio входит инструмент ModelMaker, в который также включены развитые средства UML-моделирования и некоторые средства интеграции с Bold. Тем не менее с большой долей вероятности можно утверждать, что на данный момент именно Rational Rose остается наиболее удобным средством разработки UML-моделей для Borland MDA. Дело в том, что в качестве инструмента создания модели для Bold CASE-система Rational Rose занимает особое место среди других программных средств, обладающих графическим UML-редактором. Взаимодействие с Rational Rose заложено в Borland MDA начиная с ранних версий продукта Bold for Delphi, причем сделано это довольно основательно. Такое взаимодействие реализуется посредством технологии COM (Component Object Model — модель компонентных объектов). Подробное описание COM приводится во многих источниках, например в [1].

С позиции COM Rational Rose является сервером автоматизации, выполняющим запросы клиента (контроллера) — среды разработки Borland MDA. Благодаря такому тесному механизму взаимодействия обеспечиваются следующие полезные функциональные возможности:

• автоматический запуск Rational Rose по запросу из среды Delphi;

• импорт UML-моделей и тэг-параметров из Rational Rose в Bold;

• экспорт UML-моделей и тэг-параметров из Bold в Rational Rose;

• доступ к тэг-параметрам Bold при разработке модели в Rational Rose;

• адаптация Rational Rose к конкретным версиям Bold.

Перечисленные функции позволяют на практике объединить удобные выразительные средства графического интерфейса Rational Rose с возможностью реализации тонкой настройки модели приложения в среде Borland MDA.




В данной статье мы ознакомились с основами создания модели приложения в графическом UML-редакторе Rational Rose. Вполне очевидно, что при создании больших моделей графическое представление, безусловно, будет более наглядным по сравнению с текстовым описанием. Кроме того, как мы убедились, при импорте модели автоматически происходит ее болдификация, что также позволяет не задумываться при проектировании о второстепенных элементах. И наконец, простота доступа к тэг-параметрам Borland MDA из Rational Rose обеспечивает необходимую гибкость при настройках модели приложения. Эти преимущества позволяют предположить, что в следующих версиях в состав Borland MDA войдут собственные графические средства для создания моделей приложений. А мы будем двигаться дальше, и в следующей части статьи перейдем к рассмотрению основного уровня функционирования Borland MDA — объектного пространства.
Литература:
1. Елманова Н., Трепалин С., Тенцер А. Delphi 6 и технология COM. СПб: Питер, 2002.
2. Леоненков А. UML. СПб: БХВ-Петербург, 2001.
Примеры, обсуждаемые в статье, можно найти здесь
КомпьютерПресс 6'2003


Создание модели в Rational Rose1 и ее импорт в Borland MDA


Во второй части этой статьи2 было продемонстрировано создание модели приложения средствами встроенного в Bold текстового UML-редактора. На примере аналогичной модели посмотрим, как данная процедура реализуется с помощью UML-редактора Rational Rose. Для этого создадим простую диаграмму классов, состоящую из двух классов и одной ассоциации. Сохраним созданную модель в файле, например в lib.mdl (рис. 3).

Далее перейдем в среду Delphi и создадим простой проект, состоящий из одной формы. С закладки <BoldHandles> поместим на форму компоненты BoldModel1,

BoldSystemHandle1, BoldSystemTypeInfoHandle1 и настроим их аналогично рассмотренному ранее простому приложению. С закладки <BoldMisc> поместим на форму компонент BoldUMLRoseLink (он предназначен для связи с моделью RationalRose) и установим в его свойстве FileName имя файла сохраненной нами модели — lib.mdl.

Теперь все готово для импорта модели Rational Rose в среду Borland MDA. Для этого, кликнув дважды по компоненту BoldModel1, откроем встроенный UML-редактор Bold и запустим импорт, нажав на вторую справа иконку со стрелкой в панели инструментов (рис. 4).

После запроса о подтверждении будет произведен импорт в среду Borland MDA. Корректность импортированной модели можно проверить, задав из главного меню Tools->Consistency Check. Теперь самое время проиллюстрировать преимущества, которые дает взаимодействие Rational Rose и Borland MDA. На рис. 4 в дереве объектов выделены рамками два объекта: ассоциация и класс с названием writesbyAuthor, при этом класс был создан автоматически. Когда в предыдущем примере мы генерировали модель приложения в Bold-редакторе, мы были вынуждены создавать такой класс для нашей ассоциации «вручную». Теперь же можно убедиться, что взаимодействие Borland MDA и Rational Rose настолько интеллектуально, что не ограничивается собственно передачей информации об элементах модели (классах, атрибутах, ассоциациях). В нашем случае при импорте был автоматически добавлен указанный новый класс. Это объясняется тем, что оба конца нашей ассоциации имеют кратность ролей «1..n» (см. ниже). Если заменить в модели кратность хотя бы одной роли на «1» и снова произвести импорт, то можно легко убедиться, что промежуточный класс исчезнет. Таким образом, Borland MDA, как уже говорилось, в ряде случаев способен самостоятельно добавлять в модель необходимые элементы. Подобная операция носит название «болдификация модели» — boldification, а обратная ей — unboldification. При необходимости в Bold-редакторе можно увидеть как болдифицированную, так и исходную модель — для этого достаточно задать в меню Tools->Boldify Model или Tools->Unboldify Model соответственно. Чтобы понять, для чего нужна болдификация модели, вспомним, что объекты модели Borland MDA сохраняет в реляционных базах данных, где существуют определенные ограничения — в нашем случае два класса объединены отношением «многие-ко-многим», поэтому для сохранения объектов этих классов в реляционных СУБД необходимо наличие дополнительной связующей таблицы. И если представить модель, содержащую десятки и сотни классов, то станет понятно, что неоспоримым преимуществом использования программного взаимодействия Borland MDA и Rational Rose является то, что все подобные связующие таблицы (точнее, классы для ассоциаций), присутствующие в отношениях «многие-ко-многим», будут сгенерированы автоматически и при создании модели об этом заботиться не нужно. То есть при импорте автоматически производится болдификация модели. Отметим, что принудительно болдифицировать модель можно и из встроенного текстового UML-редактора. В этом легко убедиться, если произвести в нем следующие действия:

• удалить класс writesbyAuthor из модели;

• проверить корректность модели (меню Tools->Consistency Check), получив при этом сообщение об ошибке;

• отменить болдификацию (меню Tools-Unboldify Model);

• сделать болдификацию (меню Tools-Boldify Model).

В результате удаленный нами дополнительный класс ассоциации writesbyAuthor создастся вновь и модель снова станет корректной.



Функции Object Space


Перечислим основные функции бизнес-уровня в Borland MDA:

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

• взаимодействие с уровнем представления, обработка внешних событий от пользователя;

• взаимодействие с уровнем данных, обработка внешних событий от СУБД.

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

Для обеспечения таких функций в Borland MDA включены специальные классы-носители информации модели, а также классы, реализующие управление элементами объектного пространства и осуществляющие обработку событий, происходящих в системе. Для иллюстрации решаемых на этом уровне системных задач рассмотрим вопрос контроля и управления жизненным циклом объектов во время работы приложения. При запуске MDA-приложения часть объектов загружается с уровня данных в объектное пространство (необходимость загрузки того или иного объекта может задавать либо разработчик на этапе создания приложения, либо пользователь во время его выполнения — эти вопросы будут освещены в последующих частях цикла). При этом часть объектов остается не загруженной в память, однако приложение считает, что они тем не менее существуют, поскольку не были удалены во время прошлых сеансов работы. Таким образом, формируется совокупность объектов в памяти и объектов в БД, которая образует так называемое концептуальное объектное пространство. Если при этом происходит удаление объекта, он все равно остается в памяти и в БД, пока не будет вызван метод UpdateDatabase. До момента вызова этого метода удаленный объект помечается системой как удаленный и не будет существовать в концептуальном объектном пространстве, став недоступным для использования. Для управления такими ситуациями Borland MDA имеет специальные средства, так называемые машины состояния (State Machines). Подробнее о них мы поговорим в дальнейшем — при описании взаимодействия бизнес-уровня и уровня данных.



Описатели (Handles)


Описатели Borland MDA подразделяются на два основных типа: корневые (root) и производные (rooted). На рис. 3 основные корневые описатели выделены сиреневым цветом, а производные — зеленым.

Корневые описатели являются, как легко догадаться по их названию, первичными источниками информации об объектном пространстве, в то время как любой производный описатель обязательно обладает свойством RootHandle (корневой описатель). В качестве значения этого свойства не обязательно должен выступать корневой описатель, то есть производные описатели могут объединяться в цепочки; при этом указанное свойство «RootHandle» последующего члена цепочки указывает на предыдущий член. Однако у первого члена такой цепочки это свойство должно указывать на корневой описатель.

Демонстрация и практические примеры работы с описателями требуют знания основ языка OCL (Object Constraint Language — язык объектных ограничений), который является одним из самых мощных средств Borland MDA. Основам использования OCL для работы с объектным пространством будет посвящена следующая часть этой статьи.

КомпьютерПресс 9'2003



Основные классы


У внутренних классов предком является класс TObject, а у внешних — класс TComponent.

Фрагмент иерархии внутренних классов представлен на рис. 2.

Кратко опишем некоторые из них.

TBoldMemoryManagedObject ? класс-родоначальник этой иерархии классов. Его появление обусловлено тем, что Borland MDA имеет собственный менеджер памяти.

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

Класс TBoldSubscribableObject предоставляет очень важный для Borland MDA механизм подписки на события. Практически любые компоненты Borland MDA, в том числе визуальные, способны выступать в качестве источников определенных событий, на которые можно «подписаться», а по их наступлении автоматически исполнить заранее заданные реакции — обработчики событий. Механизм подписки эффективно используется самой средой Borland MDA, в частности при работе с вычисляемыми (derived) атрибутами и ассоциациями. Этот механизм также доступен и разработчику, предоставляя уникальные возможности по управлению работой приложения в событийно-организованной программной системе.

Класс TBoldElement является важнейшим в представленной иерархии и служит центральным звеном в описании объектного пространства, являясь суперклассом для всех его элементов. Это универсальный класс, способный представлять либо значение, либо собственно объект, либо метаинформацию (информацию о типе). Класс TBoldElement имеет три потомка для представления указанных трех видов представляемых элементов — TBoldValueSetValue (представление значений), TboldDomainElement (представление объектов) и TBoldMetaObject (представление информации о типах).

Класс TBoldSystem представляет объектное пространство в целом, то есть обладает информацией обо всех экземплярах элементов модели приложения.

Класс TBoldObject представляет объект объектного пространства Borland MDA. При генерации кода все пользовательские классы являются потомками TBoldObject. Все объекты в объектном пространстве также являются потомками этого класса либо дочерними по отношению к его потомкам.

Все члены, входящие в состав любого объекта Borland MDA (например, атрибуты), принадлежат к классу TBoldMember. Однако этот класс служит и для других целей, а также имеет самостоятельное значение, порождая, например, такой класс, как TBoldList, который, в свою очередь, является родителем важного класса TBoldObjectList. Как следует из названия, этот класс служит для представления списка объектов.

Чтобы вышеописанная иерархия внутренних классов Borland MDA не выглядела абстрактной схемой, оторванной от реальности, полезно остановиться на классе TBoldObjectList поподробнее и показать на его примере, как на практике реализовать программный доступ к элементам объектного пространства из приложения во время его выполнения. Каждый экземпляр класса TBoldObjectList представляет собой список объектов (экземпляров) определенного класса модели приложения. Здесь можно провести некоторую грубую аналогию с базой данных: список объектов класса TBoldObjectList, состоящий из объектов (на самом деле из указателей на объекты), можно рассматривать как таблицу БД, состоящую из записей. При этом каждый объект в списке имеет набор атрибутов, а каждая запись в таблице БД имеет набор полей.

Вспомним теперь наш пример с приложением — библиотечным каталогом из 4-й части данного цикла — и поставим следующую задачу: программно, в процессе работы приложения, получить фамилию первого автора в каталоге. Напомним, что в нашей модели присутствует класс с названием (Expression Name) «Avtor». Для доступа к списку всех объектов класса «Avtor» используем следующее выражение:

BoldSystemHandle1.System.ClassByExpressionName[‘Avtor’];

Здесь BoldSystemHandle1 ? компонент Borland MDA, отвечающий за управление объектным пространством, System ? свойство этого компонента типа TBoldSystem (см. выше и рис. 1), ClassByExpressionName ? метод класса TBoldSystem, возвращающий выражение типа TBoldObjectList (в данном случае ? список всех объектов-экземпляров класса «Avtor» модели).

Класс TBoldObjectList имеет свойство BoldObjects[i] — типа TBoldObject, указывает на объект в списке с порядковым номером i (при этом первый объект в списке имеет номер 0). В свою очередь, класс TBoldObject обладает свойством BoldMemberByExpressionName[‘имя_члена’], позволяющим получить доступ к заданному атрибуту (члену класса). Теперь мы можем сформировать полное выражение-оператор для решения нашей задачи:

BoldSystemHandle1.System.ClassByExpressionName[‘avtor’].BoldObjects[0].BoldMemberByExpressionName[‘fio’].AsString;

Читатель может самостоятельно проверить работоспособность данного выражения на практике, поместив приведенный текст оператора в обработчик какого-нибудь события и присвоив его значение тексту какой-нибудь метки (Label), а также поэкспериментировать с ним для чтения либо для изменения других атрибутов или объектов.

Таким образом, рассмотренный пример дает возможность сделать следующие важные выводы:

• каждому классу модели соответствует свой объект-экземпляр класса TBoldObjectList объектного пространства;

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

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

Возвращаясь к иерархии внутренних классов (см. рис. 2), стоит обратить внимание на класс TBoldAttribute, являющийся родительским классом (суперклассом) для нескольких классов, представляющих атрибуты различных типов — строковых (TBAString), даты (TBADate), битовых массивов BLOB (TBABlob) и т.д. Таким образом, мы видим, что Borland MDA имеет свои типы данных — аналоги стандартных Delphi-типов. И это не случайно, поскольку Borland MDA представляет собой своего рода систему в системе, то есть самостоятельную программную систему, функционирующую в рамках определенной операционной системы (в настоящее время Windows) и обладающую собственным менеджером памяти, собственным развитым механизмом генерации и обработки событий, а также другими подобными свойствами.

При желании разработчик может создать и зарегистрировать новый MDA-тип данных, воспользовавшись мастером создания атрибутов (в меню Delphi выбрать Bold > Attribute Wizard…).

Теперь кратко рассмотрим иерархию внешних классов (рис. 3).

Все внешние классы имеют в качестве родительского класс TComponent. Это, естественно, означает, что большинство таких классов мы увидим на палитре компонентов среды разработки Delphi. Если внутренние классы можно рассматривать как своего рода «скелет», поддерживающий сложный «организм» объектного пространства, то внешние классы скорее являются своеобразными «адаптерами-переходниками» к уровню представления и уровню данных, а также основными инструментами разработчика Borland MDA-приложений. Уровни представления и данных мы рассмотрим в последующих частях статьи более детально. Сейчас лишь обратим внимание на тот факт, что большинство внешних классов содержит термин «Handle», значение которого в контексте нашего рассмотрения целесообразно перевести как «описатель».



Формирование OCL-запросов к Object Space


4 , но удобнее воспользоваться OCL-редактором, встроенным в Borland MDA. Для его активации кликнем дважды в инспекторе объектов на свойстве <Expression>, при этом откроется окно редактора (рис. 4).

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

Поскольку нас сейчас интересуют авторы, кликнем дважды в навигационном окне по элементу Avtor — окно редактора изменится (рис. 5): в верхнем окне появилось выражение «Avtor»; нижнее окошко сообщает нам, что синтаксис OCL-выражения корректен, а тип возвращаемого результата — метатип (то есть класс модели); наконец, радикально изменилось содержимое навигационного окна, теперь в нем отображается список возможных OCL-операторов, применимых к нашему выражению (значки с желтой полоской). В самом верху этого списка находится нужный нам оператор <.allInstances> (Все сущности) — в данном случае все объекты типа <Автор>, поскольку мы уже частично задали наше OCL-выражение.

Кликнув дважды по этому элементу, мы увидим картину, представленную на рис. 6. Возвращаемый теперь тип результата — нужная нам коллекция объектов типа <Автор>.

Если обратить внимание на навигационное окно, то можно увидеть характерное разнообразие отображаемых в нем элементов. Здесь присутствуют ассоциации и их роли (значки с зеленой полоской), но не все, а только связанные с классом <Автор>. Также имеются атрибуты класса (значки с синей полоской) — в данном случае единственный атрибут «ФИО» класса <Автор>. И, конечно, по-прежнему присутствуют возможные OCL-операторы, с помощью которых можно «детализировать» наше выражение. Позже мы расскажем, как использовать эти богатые возможности, а сейчас отметим некоторые принципиальные моменты. Во-первых, несмотря на кажущуюся простоту, OCL-редактор является исключительно мощным средством формирования OCL-запросов. Обладая интеллектом и знаниями о модели, он динамически формирует возможные варианты последовательной детализации OCL-выражения и отображает их в навигационном окне. Во-вторых, как мы уже убедились, синтаксис OCL-выражений использует dot-нотацию, то есть его отдельные элементы отделяются точкой.

Выйдем из OCL-редактора и присвоим свойству BoldHandle компонентов BoldGrid1 и BoldNavigator1 значение ListAllAvtors. Далее правой кнопкой мыши на компоненте BoldGrid1 из всплывающего меню выберем пункт Create Default Columns и убедимся, что появился заголовок столбца «ФИО». Таким образом мы подключили визуальный компонент BoldGrid1 к объектному пространству посредством описателя списка ListAllAvtors.

Продолжим создание нашего приложения. По аналогии с настройкой списка всех авторов создадим описатель списка ListAllBook для получения списка всех книг. Это легко можно сделать самостоятельно, единственное отличие будет заключаться только в OCL-выражении, которое в данном случае будет выглядеть как «Kniga.allInstances». Список книг мы будем отображать в BoldGrid3, для чего свяжем уже известным нам способом компоненты BoldGrid3 и BoldNavigator2 c описателем списка ListAllBook.



Использование цепочек описателей


рис. 7), где каждый последующий элемент ссылается на предыдущий через свойство <Root Handle>.

Присвоим в инспекторе объектов свойству <RootHandle> описателя ListAvtorBooks значение ListAllAvtors и запустим OCL-редактор (рис. 8). Хотя мы еще не ввели никакого OCL-выражения, но в навигационном окне отображаются теперь не все элементы нашей модели, а лишь те, которые относятся к классу <Автор>.

Это и понятно, ведь в качестве корневого описателя, то есть поставщика информации, мы выбрали не все объектное пространство, а лишь один его класс.

И теперь нам осталось дважды кликнуть по названию роли «napisal» и убедиться, что тип возвращаемого результата — это коллекция объектов типа <Книга>. После подключения BoldGrid2 к описателю ListAvtorBooks можно считать, что поставленная задача решена.

Даже на таком простом примере в полной мере проявляется гибкость, предоставляемая средой Borland MDA. В следующей части статьи мы продолжим разработку нашего приложения и более детально ознакомимся с возможностями OCL.

КомпьютерПресс 11'2003



Развитие модели


1, добавив в нее дополнительные классы и ассоциации (рис. 1). Напомним, что наше приложение предназначено для работы с библиотечным каталогом, а в новую модель включены следующие классы: Страна, Издательство и Тематика.

Сформулируем основные бизнес-правила, определяемые новой моделью:

• библиотечный каталог содержит информацию об авторах, книгах, издательствах, странах и тематике книг;

• автор описывается единственным текстовым атрибутом — ФИО;

• элементы, то есть классы (Страна, Книга, Издательство, Тематика), описываются единственным текстовым атрибутом — Название;

• каждый автор может написать одну или несколько книг;

• каждая книга может быть написана одним или несколькими авторами;

• каждый автор является гражданином одной страны;

• в каждой стране может проживать несколько авторов или ни одного;

• в каждой стране может существовать несколько издательств или ни одного;

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

• каждое издательство может издать одну или несколько книг;

• каждая книга может быть издана только одним издательством;

• каждая книга может относиться только к одной тематике;

• может существовать несколько книг по одной тематике или не существовать ни одной книги по данной тематике.

Создадим модель в редакторе Rational Rose и сохраним ее в какой-нибудь папке на диске, присвоив название lib.mdl и предварительно обработав с целью преобразования русскоязычных названий классов и атрибутов в англоязычные2. Можно также воспользоваться готовой моделью3.



Создание приложения


рис. 2 диаграммой.

Теперь приступим к созданию графического интерфейса формы (рис. 3). Поместим на форму 7 визуальные компоненты BoldGrid1, BoldGrid2…BoldGrid7 (на рисунке их номера представлены красными цифрами), далее над каждым из них расставим по одной обычной метке (Label) для удобства привязки, присвоив меткам названия: Все авторы, Все книги и т.д. Под компонентами BoldGrid 1, 3, 5, 6, 7 поставим по одному компоненту BoldNavigator. А затем поместим три компонента BoldLabel (на рисунке они обведены красным), пока не настраивая их свойства (эти компоненты показаны в настроенном виде). Мы создали графический интерфейс, однако он еще не привязан к объектному пространству. Для осуществления такой привязки используем невизуальные компоненты — описатели списков BoldListHandles с палитры компонентов BoldHandles, и покажем на нашем примере, как используется язык OCL для взаимодействия графического интерфейса (уровня представления) с объектным пространством (бизнес-уровнем).



BOLD - инструмент реализации MDA в Delphi

Константин Грибачев

Borland MDA и Microsoft .NET


1, однако, с точки зрения предмета данного цикла статей, целесообразно сказать несколько слов именно об этой, последней версии нового продукта разработки компании Borland.

Принципиальным отличием версии Architect от ранее вышедших версий продукта Borland C# Builder является присутствие в ней средств разработки MDA-приложений. Из их состава важнейшим элементом является интегрированная в Borland C# Builder Architect технология ECO — Enterprise Core Objects. Читатели, ознакомившиеся с технологией Bold for Delphi, обнаружат в ECO очень много общего с Bold. И это не случайно, поскольку ECO базируется на технологии Bold.

С целью полной интеграции MDA-инструментов в среду разработки компания Borland сделала еще один весьма логичный шаг: в состав Borland C# Builder Architect теперь включен полнофункциональный редактор UML-моделей, созданный на базе продуктов TogetherSoft2. Благодаря этому Borland C# Builder Architect стал первым продуктом Borland, обеспечивающим полный жизненный цикл разработки приложений — от создания модели до генерации кода.



Доработка приложения


3, модель которого представлена на рис. 1, продемонстрируем возможности, предоставляемые поддержкой в Borland MDA языка объектных ограничений OCL, а также рассмотрим некоторые визуальные компоненты Borland MDA.

Для начала, по аналогии со списками авторов и книг, подключим визуальные компоненты BoldGrid5, BoldGrid6 и BoldGrid7 к описателям списков ListAllCountries, ListAllPublishers, ListAllThematics соответственно, то есть будем отображать в этих компонентах списки стран, издательств и тематических направлений книг (рис. 2), для начала создав в них столбцы по умолчанию (то есть столбец «Название»). Для сохранения данных запишем в обработчик события OnClose формы следующий оператор: DataModule1.BoldSystemHandle1.UpdateDatabase;

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



OCL и графический интерфейс


рис. 2).

Обратите внимание, что метка BoldLabel1, как и любой другой визуальный компонент Borland MDA, имеет свойство BoldHandle. Из предыдущей статьи данного цикла нам известно, что в качестве источника данных для этого описателя целесообразно выбрать ListAllAvtors, что мы и сделаем. А в качестве OCL-выражения напишем вручную или введем во встроенном OCL-редакторе (напомним, что OCL-редактор вызывается при двойном щелчке по свойству Expression компонента ListAllAvtors) следующее выражение: «’Страна ‘+strana.nazvanie», где ‘Страна ’ — это текстовая константа, а «strana.nazvanie» — OCL-запрос для выбора страны для текущего автора и выбора атрибута «название» класса «’Страна’ — nazvanie» для отображения его на нашей форме. Как видим, это делается весьма просто. Встроенный в Borland MDA механизм обеспечит при этом автоматическое изменение текста метки при изменении текущего автора в компоненте BoldGrid1. На этом моменте стоит остановиться подробнее — как уже упоминалось ранее, одним из важных механизмов, встроенных в Borland MDA, является механизм так называемой подписки на события (subscribing). Рассмотрим работу данного механизма.

В нашем случае, связав свойство BoldHandle метки с описателем списков авторов ListAllAvtors, мы «сообщили» среде Borland MDA, что необходимо «подписать» нашу метку на события, возникающие при любых изменениях списка авторов, в том числе и на события, возникающие при переходах от одного объекта к другому при перемещении по списку авторов. Кроме того, мы сформировали OCL-запрос, который должен быть выполнен при наступлении такого события, с указанием конкретной необходимой нам информации (название страны, где проживает автор). Остальное среда Borland MDA сделает самостоятельно, то есть по наступлению события, связанного с изменениями в списке авторов, проверит, есть ли элементы, подписавшиеся на изменение этого списка, и, если таковые имеются, выполнит соответствующий OCL-запрос, а также вернет полученные данные подписанному элементу для дальнейшего использования (в данном случае — для отображения на форме). Отметим, что в данном случае «подписку» незаметно для нас «оформила» сама среда, но это совсем не обязательно. Разработчик может и самостоятельно «подписать» любой Bold-элемент на необходимое событие, воспользовавшись специальными методами класса TboldElement.

Читатель вправе спросить, что же здесь нового. Мы знаем, что при традиционной разработке приложений с базами данных можно использовать визуальный компонент TDBLabel — метку, которая автоматически отслеживает и отображает на форме содержимое указанного поля таблицы БД при перемещении по сетке. Однако в нашем классе «Автор» отсутствует атрибут «Страна» и для решения этой задачи традиционными методами нужно было бы сформировать в общем случае SQL-запрос, который бы выбирал страну из другой таблицы для конкретного автора и связать метку с этим запросом. Кроме того, необходимо было бы специально «подключать» этот запрос к сетке либо к набору данных, чтобы он выполнялся при переходах между авторами. Мы же обошлись без подобных операций.

Аналогично проделаем операции по подключению Bold-меток BoldLabel2 (для отображения названия издательства книги) и BoldLabel3 (для отображения тематики книги). В качестве источника информации для этих меток выступает описатель списка книг ListAllBooks. После запуска приложения убеждаемся, что тексты меток отслеживают перемещение по списку книг, отображаемых в компоненте BoldGrid3.



OCL и вычисляемые атрибуты


КомпьютерПресс 11'2003



OCL и вычисляемые данные


рис. 3, справа вверху). Добавление столбца осуществляется аналогично тому, как это делается в стандартном компоненте Grid. Присвоим новому столбцу название «Книг» (оно будет отображаться в заголовке столбца). Однако на этом аналогия с традиционным компонентом заканчивается — как мы видим (Рис.3, слева) , в инспекторе объектов снова присутствует уже знакомое нам свойство «Expression». Введем в него вручную или с помощью OCL-редактора выражение «knigi ->size.asString». В данном случае оно означает, что необходимо взять значение роли ассоциации класса «Тематика» с названием «книги» (см. модель на рис.1), затем получить количество элементов этой роли — оператор «->size » и, наконец, преобразовать полученное выражение в строку «.asString». Тем самым мы решили поставленную задачу.

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

И наконец, обратимся к компоненту BoldGrid5, отображающему названия стран. До этого момента в нем отображался всего один столбец, созданный по умолчанию и содержащий название страны. Предположим, что мы хотим получить дополнительную статистическую информацию по каждой стране, а именно — общее количество авторов, проживающих в этой стране, общее количество издательств, а также общее количество всех изданных в данной стране книг. Для этого добавим к сетке BoldGrid5 три новых столбца — с названиями «Авт», «Изд», «Книг». Для столбца «Авт» выражение OCL примет следующий вид: «avtory->size.asString», для столбца «Изд»: «izdatel_stva ->size.asString». Однако для последнего столбца подобное простое выражение не будет являться решением, поскольку алгоритм расчета суммарного количества книг оказывается более сложным. В самом деле, в нашей модели отсутствует ассоциация, непосредственно связывающая оба класса — «Страна» и «Книга», и это вовсе не считается недостатком модели, поскольку вся необходимая информация для решения поставленной задачи у нас есть.

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

«izdatel_stva->collect(knigi->size)->sum».

Здесь мы впервые сталкиваемся с операторами взятия коллекции «->collect» и оператором суммирования «->sum». Смысл их вполне ясен из рассмотренного примера.

Можно сказать, что во многом оператор коллекции схож с известным SQL-оператором группировки «group by». Стоит отметить, что оператор получения коллекции применяется в OCL-выражениях довольно часто. После запуска приложения можно убедиться, что оно приобрело новые, необходимые нам качества (рис. 4).

На этом мы завершаем описание основных возможностей OCL. На примере созданного приложения были продемонстрированы основные подходы к реализации взаимодействия бизнес-уровня и графического интерфейса пользователя. Мы убедились на практике, что при использовании Borland MDA эта среда обеспечивает принципиально новые возможности по формированию такого взаимодействия благодаря встроенной поддержке языка OCL. Так, любой визуальный элемент приобретает способность отображать практически любые данные, содержащиеся в объектах объектного пространства. В рассмотренном примере мы «заставили» метки и сетки отображать информацию из объектов, принадлежащих разным классам нашей модели, и даже получать новую информацию, которая непосредственно в модели не содержится (статистические данные по странам, издательствам и т.д.). Необходимо отметить, что формирование такого рода взаимодействий не ограничивается этапом разработки приложения. Любое OCL-выражение можно формировать и присваивать и во время выполнения программы, при этом OCL-запрос будет исполнен средой Borland MDA, поскольку OCL-интерпретатор включается в состав исполняемого exe-файла приложения, так же как и вся информация о модели.

Нельзя еще раз не отметить, что при создании приложения мы не писали код на языке Object Pascal, и не использовали язык SQL, но, тем не менее, смогли «завязать» все элементы нашей модели в одно целое. Использование OCL позволяет сделать приложение более платформенно-независимым, так как язык OCL сам является платформенно-независимым языком. На практике это означает, что бизнес-логика приложения, будучи один раз создана на языке OCL без кодирования на языках программирования, при переносе разработки на другую платформу полностью сохранится и может быть повторно использована. И это является еще одним преимуществом технологии Borland MDA.



Функции Persistence Layer


• сохранение элементов (объектов и ассоциаций) объектного пространства (ОП) в долговременной памяти (как правило, на жестком диске, хотя для этой цели могут использоваться и любые другие устройства хранения — дискеты, flash-диски, CD/DVD-RW и т.д. при наличии стандартного доступа к ним из приложения). При этом сохраняются только те объекты и связи, для которых в модели приложения задано свойство Persistent;

• загрузка элементов объектного пространства из долговременной памяти;

• объектно-реляционное отображение, то есть преобразование объектной UML-модели в структуру реляционной базы данных;

• генерация схемы реляционной базы данных по имеющейся объектной модели;

• преобразование OCL-выражений в операторы SQL (так называемый механизм OCL2SQL).



Подключение к СУБД


рис. 2).

Настроим добавленные компоненты, как показано на рис. 3. В компоненте IBDatabase1 зададим имя базы данных — TestDB.

Затем в инспекторе объектов настроим адаптер базы данных, в данном случае просто указав тип используемого диалекта SQL (рис. 4).

Для генерации базы данных запустим редактор моделей и из главного меню выберем подпункт Tools->Generate Database (рис. 5), после чего Bold обеспечит создание схемы БД в соответствии с нашей UML-моделью.



Структура и состав компонентов


рис. 1 представлена схема, иллюстрирующая взаимодействие объектного пространства и уровня данных. Центральным элементом, организующим подобное взаимодействие, является дескриптор уровня данных. В качестве такого дескриптора может выступать как компонент BoldPersistenceHandleFileXML, предназначенный для сохранения ОП в XML-файле (мы уже использовали этот компонент при описании создания простого приложения), так и компонент BoldPersistenceHandleDB, предназначенный для организации взаимодействия с реляционными СУБД.

Для обеспечения работы с конкретными типами СУБД в состав компонентов BMDA включены специальные компоненты — адаптеры баз данных.

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

• BoldDataBaseAdapterBDE ? обеспечивает подключение к СУБД через Borland Database Engine;

• BoldDataBaseAdapterADO ? обеспечивает подключение к СУБД через интерфейс ActiveX Data Objects(ADO);

• BoldDataBaseAdapterIB ? обеспечивает подключение к СУБД Interbase;

• BoldDataBaseAdapterDBX ? обеспечивает подключение к СУБД через интерфейс DBEXpress.

Кроме вышеперечисленных, предусмотрены адаптеры для организации взаимодействия с данными посредством SOAP (Simple Object Access Protokol), а также для СУБД DBISAM и для пакета SQLDirect. Впрочем, разработчик имеет возможность при необходимости создать собственный адаптер СУБД.



Управление взаимодействием с СУБД с помощью BoldActions


рис. 6 и 7).

Это действие предназначено для генерации схемы базы данных СУБД Interbase. В инспекторе объектов можно настроить параметры этого действия, указав свойства генерируемой базы данных (рис. 8).

Кроме того, добавим еще два действия — TBoldActivateSystemAction (активизация объектного пространства) и TBoldUpdateDBAction (обновление базы данных). Поместим на форму три кнопки, при этом каждую из них свяжем с одним из вышеуказанных действий (рис. 9), и запустим приложение на исполнение.

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



Причины повышенного внимания компании Borland



Причины повышенного внимания компании Borland к инструментарию реализации MDA-архитектуры вполне объяснимы — даже из примеров, приведенных в данном цикле статей, становится ясно, сколь значительно с применением этой технологии повышается эффективность разработки приложений, использующих базы данных. Десятки компаний — разработчиков программного обеспечения уже давно и с успехом применяют Bold for Delphi при разработке информационных систем. И, если судить по отзывам специалистов, их производительность труда при этом повышается в 10 раз.
С учетом сказанного автор выражает надежду, что данный цикл статей поможет как начинающим, так и опытным разработчикам преодолеть психологический барьер, который зачастую является основной серьезной проблемой при освоении качественно новых технологий программирования.
КомпьютерПресс 2'2004