СТАТЬЯ |
06.12.02
|
© Кэри Дженсен (Cary Jensen) , Jensen Data Systems, Inc.
Bold for Delphi - это объектно-ориентированная среда разработки приложений, которая получила широкое признание, использует общепринятые стандарты и позволяет разработчикам быстро создавать и сопровождать бизнес-приложения. Возможно, Bold for Delphi подходит не всем разработчикам, однако в области проектирования и сопровождения приложений эта среда разработки является крупным шагом вперёд далеко за пределы основанной на компонентах архитектуры большинства Delphi-приложений. Современному разработчику Bold for Delphi даёт инструменты, которые относятся к следующему этапу развития средств разработки бизнес-приложений. Имеется также версия для C++Builder (Bold for C++).
Краеугольный камень проектирования приложений - диаграммы классов универсального языка моделирования UML (Unified Modeling Language) 1.3. Это одна из главных характеристик Bold for Delphi. Стандарты языка UML, предназначенного для объектно-ориентированного проектирования и анализа, выработала группа OMG (Object Management Group), ведущая организация в области стандартов разработки объектно-ориентированного программного обеспечения для предприятий. Модели классов на указанных диаграммах встраиваются в приложение и используются компонентами Bold for Delphi для управления поведением приложения.
Используемые в Bold for Delphi модели классов UML можно создавать различными способами. Большинство работающих с Bold for Delphi разработчиков используют Rational Rose (http://www.interface.ru/rational/rosemain.htm), средство разработки UML компании Rational Software Corporation. Модели UML также могут быть полностью описаны в Bold for Delphi с использованием редактора моделей Bold UML Model Editor, редактора компонентов, связанного с компонентом TBoldModel, хотя этот подход не столь нагляден, как в Rose. Компания BoldSoft также объявила о планах поддержки других средств разработки, включая ModelMaker. Кроме того, Bold поддерживает импорт моделей, описанных с использованием XMI - стандарта обмена метаданными XML. К моменту публикации этого обзора уже должна быть поддержка экспорта информации о модели в формат XMI.
Помимо поддержки моделей классов UML, Bold for Delphi широко использует версию 1.1 языка выражений OCL (Object Constraint Language, язык ограничений объектов), похожего на язык SQL, но созданного специально для навигации по объектам и получения данных из объектов. Например, многочисленные компоненты Bold содержат свойство Expression, с помощью которого команды языка OCL могут определять, как эти компоненты должны обрабатывать свои данные. Кроме того, редактор свойства Expression в OCL позволяет просто и быстро создавать и проверять выражения OCL.
"Такое сочетание стандартных технологий сделало Bold for Delphi лидером следующей волны средств разработки программного обеспечения", - поясняет Хенрик Джонделл (Henrik Jondell), генеральный и коммерческий директор компании BoldSoft. Продукт Bold for Delphi завоевал 11-й ежегодный приз Software Development Productivity Award журнала Software Development Magazine. Компания Borland включила Bold for Delphi, наряду с Rational Rose, в свой мощный продукт под названием Borland Enterprise Studio for Windows.
В основе Bold for Delphi лежит архитектура нового поколения, которую точнее всего можно назвать управляемой моделью (MDA, model-driven architecture). Используя архитектуру MDA, разработчик творит на более высоком уровне, чем большинство использующих Delphi разработчиков. В частности, большинство Delphi-разработчиков проектируют на основе компонентов, являющихся многократно используемыми объектами, которые связаны между собой свойствами и формируют приложение. Преимуществом объектно-ориентированной разработки на основе компонентов является многократное использование объектов, а её недостатком - слабое внимание к взаимодействию объектов в приложении. "Что ещё хуже, - замечает Джонас Хогстрём (Jonas Hogstrom), главный разработчик компании BoldSoft. - Используемая в Delphi модель компонентов, не имеет ничего общего с объектами домена и бизнес-объектами. Обычно объекты Delphi - это компоненты графического интерфейса пользователя, такие как TDBEdit или TDataSet, которые не являются бизнес-объектами в том смысле, как объект TPerson."
Архитектура MDA, которая является расширением объектно-ориентированной разработки, определяет отношения между объектами и их взаимодействие. В Bold это описывается с помощью модели классов UML. Рассмотрим эту модель в Rational Rose на рис. 1. Эта модель определяет абстрактный класс с именем Actor и единственным свойством assets (активы). Конкретные классы Person и Organization являются ответвлениями класса Actor. Есть также третий класс с именем Family (Семья). На этой диаграмме классов также есть две ассоциации: members (члены) и familyMembers (члены семьи). Каждое лицо (Person) может быть членом нескольких организаций, либо не входить ни в одну из организаций, а организация может состоять из любого количество членов. Таким же образом и лицо может принадлежать к какой-либо семье, либо не принадлежать ни к какой семье, а семья может состоять из любого, в том числе нулевого количества членов.
Рис. 1. Диаграмма классов в Rational Rose.
После импорта этой модели в редактор моделей Bold UML Model Editor, классы, их члены и ассоциации становятся частью приложения. Если диаграмму классов (модель) назвать People, то в редакторе Bold UML Model Editor эта модель будет выглядеть так, как показано на рис. 2.
Рис. 2. Модель классов, импортированная в редактор моделей Bold UML Model Editor.
После импорта модели, обнаруженные на диаграмме классов определения, используются рядом компонентов Bold, редакторами компонентов и свойств, что помогает разработчику при разработке приложения. Последующие изменения исходной модели можно импортировать, обновив декларации (объявления и описания) и поведение связанных компонентов Bold.
Разработка приложений в Bold for Delphi требует от большинства Delphi-разработчиков существенного смещения парадигмы. "Для типичного Delphi-разработчика себе бизнес-объекты обычно представлены строкой TDataSet, - говорит Ян Норден (Jan Norden), главный архитектор ПО компании BoldSoft. - Такой подход редко соответствует реальной модели, лежащей в основе приложения".
В отличие от Delphi-разработчиков, Bold-разработчики работают с классами, которые прямо соответствуют импортированной модели классов. Delphi-объявления этих классов, которые являются истинными бизнес-объектами, генерируются в редакторе Bold UML Model Editor. Внутренние классы Bold используют данные этих бизнес-объектов для всех операций чтения и записи в базе данных. "При таком подходе программисты могут работать непосредственно в контексте своих моделей классов, не сопоставляя их структурам базы данных", - поясняет Норден. Поэтому при программировании с помощью Bold становятся реальностью бизнес-объекты, о которых часто говорят, но редко применяют в Delphi-приложениях.
Показанный на распечатке код является частью раздела интерфейс кода, генерированного редактором Bold UML Model Editor для диаграммы классов, показанной на рис. 1. Но Bold for Delphi - это не просто генератор кода. Генерирование кода является частью значительно более динамичного процесса. Как уже говорилось, модель классов становится частью приложения (она хранится как свойство компонента TBoldModel) и используется сгенерированными классами для управления их поведением.
Применяющие Bold разработчики обычно не взаимодействуют в компонентами TDataSet напрямую (хотя Bold не всегда спасает от этого), что очень непривычно большинству Delphi-разработчиков. Сгенерированные в Bold бизнес-объекты используются вспомогательными классами, которые отвечают за чтение и запись в базе данных. В контексте Bold это можно назвать хранением объектов. Если данные бизнес-объектов (свойства объектов) должны храниться, то один из классов Bold сохраняет эти данные, записывая их в базу данных.
С точки зрения модели, запись в базу данных - это всего лишь подробность реализации. Когда объектно-ориентированные базы данных станут более распространёнными, возможно, в базу данных будут записываться сами объекты, а не их данные. Но и существующий пока доступ к базе данных почти "прозрачен", то есть незаметен для разработчика. Приложение загружает, инициализирует и убирает объекты по мере необходимости. Если данные объектов должны быть сохранены, то они записываются в базу данных (хотя это обычно инициируется явным вызовом метода TBoldSystemHandle.UpdateDatabase).
В текущей версии Bold редактор Bold UML Model Editor отвечает за создание структур в используемой приложением базе данных. Если Bold UML Model Designer выбрать команду меню Tools | Generate Database, то Bold создаст все таблицы, необходимые для хранения метаданных и объектов. Bold уже поддерживает большинство баз данных, с которыми может работать ADO, BDE и InterBase Express. Кроме того, компания BoldSoft близка к реализации поддержки баз данных dbExpress, DBISAM, Advantage Database Server и SQLDirect. Если вы импортируете обновленную модель, и вашу базу данных нужно обновить, чтобы внести изменения, можно выбрать команду меню Tools | Evolve Database, чтобы обновить базу данных без потери существующих данных (хотя, как всегда, перед тем, как сделать изменения, нужно сделать резервную копию данных).
Пока Bold не имеет механизма для слияния существующих данных в хранилище данных бизнес-объектов, то есть Bold for Delphi пока лучше подходит для разработки новых приложений, но неудобна тем разработчикам, которые хотят обновить существующие приложения, чтобы использовать систему Bold. Правда, старший архитектор Ян Норден сообщил, что одним из приоритетов компании BoldSoft является создание механизма отображения существующих структур баз данных в систему Bold.
Как это часто бывает при использовании систем разработки приложений, для перехода к Bold for Delphi необходим ряд условий. Во-первых, использующие Bold for Delphi разработчики должны хорошо разбираться в объектно-ориентированной разработке приложений. Недостаточно просто устанавливать свойства. Здесь основную роль играют объекты, поэтому очень важно понимать их определения и использование.
Во-вторых, для создания приложений с помощью Bold for Delphi необходимо понимание языка UML хотя бы на том уровне, который необходим для понимания диаграмм классов. Проектирование приложений с помощью Bold for Delphi начинается с диаграмм классов UML. Чтобы разобраться в этом, нужно прочесть несколько хороших книг по UML или закончить соответствующие курсы. Поскольку язык UML широко используется для объектно-ориентированного проектирования и анализа, многое разработчики уже удовлетворяют указанному требованию, а остальные приобретут полезные знания.
В-третьих, использующие Bold for Delphi разработчики должны познакомиться с OCL, языком выражений на основе объектов, который служит для доступа к объектам и получению их данных. Как известно, компания BoldSoft участвует в подготовке следующей, второй версии языка OCL. (Сведения о текущем состоянии языка OCL см. по адресу http://www.klasse.nl/ocl/index.html.)
В-четвёртых, и это, пожалуй, самое трудное для большинства разработчиков, при разработке с помощью Bold for Delphi необходимо использовать большое количество компонентов Bold. При разработке приложений с помощью Bold можно использовать многие стандартные компонентов Delphi, но кроме них необходимо использовать множество компонентов Bold. Как минимум, требуются компоненты TBoldModel, TBoldSystemHandle и TBoldSystemTypeInfo. Кроме того, для доступа к базе данных (чтобы хранить в ней объекты) необходим хотя бы один из компонентов TBoldPersistenceHandle, например, TBoldPersistenceHandleBDE или TBoldPersistenceHandleADO. Они позволяют созданными с помощью Bold приложениям записывать в базу данных данные бизнес-объектов. А для удобного доступа к моделям, созданным с помощью Rational Rose, необходим компонент TBoldUMLRoseLink. Пример минимальной конфигурации показан на рис. 3.
Рис. 3. Схема DataModule с важнейшими компонентами Bold.
Но это ещё не всё. Разработчики, применяющие Bold for Delphi, используют ряд дополнительных компонентов Bold. Например, графические интерфейсы создаются с использованием элементов управления Bold. Многие элементы управления в Delphi, которые служат для получения информации из базы данных, имеют двойников в Bold, например, TBoldEdit, TBoldGrid, TBoldNavigator, TBoldCheckBox. Часто используются компоненты Bold TBoldListHandle, TBoldFilter, TBoldComparer, TBoldVariableHandle и TBoldDataSet. Эти компоненты находятся на страницах палитры компонентов Bold (см. рис. 4).
Рис. 4. Страницы палитры компонентов Bold.
Компоненты Bold взаимодействуют с моделью классов и поддерживают выражения языка OCL. Кроме того, многие компоненты, особенно компоненты графического интерфейса, поддерживают подписки, используя модель издатель-подписчик. Подписки позволяют одному объекту (обычно объекту графического интерфейса) объявлять интерес в значениях, представленных другим объектом (обычно бизнес-объектами). Если один объект подписывается на другой, то первый (подписчик) информируется об изменениях данных второго (издателя), получая возможность пересчитывать свое выражение OCL. Подписки широко используются в Bold, особенно при проектировании графического интерфейса пользователя.
На рис. 4 две страницы палитры связаны с функциями COM. Bold for Delphi можно использовать для создания сетевых распределенных приложений на основе диаграмм классов UML, при этом поддерживаются такие технологии как XML, COM, HTTP и SOAP.
Как бы ни был хорош продукт Bold for Delphi, он всё же подходит не для всех разработчиков, применяющих инструментарий Delphi. Bold for Delphi, как и всякая инструментальная система, требует существенных познаний в технологии. Как уже было указано выше, для использования Bold for Delphi необходим ряд условий, в том числе минимальный уровень понимания некоторых технологий. Bold for Delphi трудно освоить даже опытным разработчикам, которые уже хорошо знают языки UML и OCL.
Другая важная характеристика Bold for Delphi - широкое использование объектов, как бизнес-объектов, с которыми взаимодействует написанный вами код, так и с их вспомогательными классами. Если ваш код должен работать с большим количеством объектов одновременно, то и в памяти будет удерживать множество объектов. Это может снизить быстродействие и увеличить технические требования к клиентским рабочим станциям.
Другое препятствие к внедрению Bold for Delphi - недостаток документации. Bold for Delphi поставляется со встроенной справочной системой, которая по своей природе содержит лишь ограниченный объём информации. На многих страницах справки есть ссылки, которые ведут на страницы, предлагающие отправить в компанию BoldSoft запрос на получение дополнительной информации. Такая справка бесполезна для разработчиков, пытающихся использовать незнакомый им компонент.
Это не означает, что компания BoldSoft не поддерживает свой продукт. Встроенная справка всё-таки содержит немало полезной информации. А дополнительную и самую свежую информацию по использованию компонентов Bold for Delphi можно получить от группы новостей BoldSoft . Кроме того, компания BoldSoft предлагает услуги по обучению использованию Bold for Delphi. И, наконец, Энтони Ричардсон (Anthony Richardson) написал ряд статей, посвящённых использованию Bold for Delphi. Эти статьи поставляются вместе с продуктом, их также можно найти на веб-сайте компании BoldSoft.
Bold for Delphi - впечатляющая система для разработки приложений, которая использует стандартные технологии и управляемую моделью архитектуру. И хотя освоение Bold for Delphi требует много времени и терпения, но преимущества, которые получат решившиеся освоить её компании, стоят того - повышение производительности и управляемости, более точное соответствие приложений проектным спецификациям.
type
{ Предварительные объявления всех классов. }
TPeopleClassesRoot = class;
TPeopleClassesRootList = class;
TActor = class;
TActorList = class;
TFamily = class;
TFamilyList = class;
TMemberShip = class;
TMemberShipList = class;
TOrganization = class;
TOrganizationList = class;
TPerson = class;
TPersonList = class;
TPeopleClassesRoot = class(TBoldObject)
private
protected
public
end;
TActor = class(TPeopleClassesRoot)
private
function _Get_M_assets: TBACurrency;
function _Getassets: Currency;
procedure _Setassets(NewValue: Currency);
protected
public
property M_assets: TBACurrency read _Get_M_assets;
property assets: Currency
read _Getassets write _Setassets;
end;
TFamily = class(TPeopleClassesRoot)
private
function _Get_M_familyName: TBAString;
function _GetfamilyName: string;
procedure _SetfamilyName(NewValue: string);
function _Get_M_isNoble: TBABoolean;
function _GetisNoble: Boolean;
procedure _SetisNoble(NewValue: Boolean);
function _GetfamilyMembers: TPersonList;
protected
public
property M_familyName: TBAString
read _Get_M_familyName;
property M_isNoble: TBABoolean read _Get_M_isNoble;
property M_familyMembers: TPersonList
read _GetfamilyMembers;
property familyName: string
read _GetfamilyName write _SetfamilyName;
property isNoble: Boolean
read _GetisNoble write _SetisNoble;
property familyMembers: TPersonList
read _GetfamilyMembers;
end;
TMemberShip = class(TPeopleClassesRoot)
private
function _GetOrganizations: TOrganization;
function _Get_M_Organizations: TBoldObjectReference;
function _Getmembers: TPerson;
function _Get_M_members: TBoldObjectReference;
protected
public
property M_Organizations: TBoldObjectReference
read _Get_M_Organizations;
property M_members: TBoldObjectReference
read _Get_M_members;
property Organizations: TOrganization
read _GetOrganizations;
property members: TPerson read _Getmembers;
end;
TOrganization = class(TActor)
private
function _Get_M_name: TBAString;
function _Getname: string;
procedure _Setname(NewValue: string);
function _Getmembers: TPersonList;
function _GetMemberShip: TMemberShipList;
protected
public
property M_name: TBAString read _Get_M_name;
property M_members: TPersonList read _Getmembers;
property M_MemberShip: TMemberShipList
read _GetMemberShip;
property name: string read _Getname write _Setname;
property members: TPersonList read _Getmembers;
property MemberShip: TMemberShipList
read _GetMemberShip;
end;
TPerson = class(TActor)
private
function _Get_M_givenName: TBAString;
function _GetgivenName: string;
procedure _SetgivenName(NewValue: string);
function _Get_M_dateOfBirth: TBADate;
function _GetdateOfBirth: TDate;
procedure _SetdateOfBirth(NewValue: TDate);
function _Get_M_age: TBAInteger;
function _Getage: Integer;
function _GetOrganizations: TOrganizationList;
function _GetMemberShip: TMemberShipList;
function _GetFamily: TFamily;
function _Get_M_Family: TBoldObjectReference;
procedure _SetFamily(value: TFamily);
protected
procedure _age_DeriveAndSubscribe(
DerivedObject: TObject; Subscriber: TBoldSubscriber);
virtual;
function GetDeriveMethodForMember(Member: TBoldMember):
TBoldDeriveAndResubscribe; override;
function GetReverseDeriveMethodForMember(
Member: TBoldMember): TBoldReverseDerive; override;
public
function olderFamilyMembers: Integer;
property M_givenName: TBAString read _Get_M_givenName;
property M_dateOfBirth: TBADate
read _Get_M_dateOfBirth;
property M_age: TBAInteger read _Get_M_age;
property M_Organizations: TOrganizationList
read _GetOrganizations;
property M_MemberShip: TMemberShipList
read _GetMemberShip;
property M_Family: TBoldObjectReference
read _Get_M_Family;
property givenName: string
read _GetgivenName write _SetgivenName;
property dateOfBirth: TDate
read _GetdateOfBirth write _SetdateOfBirth;
property age: Integer read _Getage;
property Organizations: TOrganizationList
read _GetOrganizations;
property MemberShip: TMemberShipList
read _GetMemberShip;
property Family: TFamily
read _GetFamily write _SetFamily;
end;
TPeopleClassesRootList = class(TBoldObjectList)
protected
function GetBoldObject(index: Integer):
TPeopleClassesRoot;
procedure SetBoldObject(index: Integer;
NewObject: TPeopleClassesRoot);
public
function Includes(anObject: TPeopleClassesRoot):
Boolean;
function IndexOf(anObject: TPeopleClassesRoot):
Integer;
procedure Add(NewObject: TPeopleClassesRoot);
function AddNew: TPeopleClassesRoot;
procedure Insert(index: Integer;
NewObject: TPeopleClassesRoot);
property BoldObjects[index: Integer]:
TPeopleClassesRoot read GetBoldObject
write SetBoldObject; default;
end;
TActorList = class(TPeopleClassesRootList)
protected
function GetBoldObject(index: Integer): TActor;
procedure SetBoldObject(index: Integer;
NewObject: TActor);
public
function Includes(anObject: TActor): Boolean;
function IndexOf(anObject: TActor): Integer;
procedure Add(NewObject: TActor);
function AddNew: TActor;
procedure Insert(index: Integer; NewObject: TActor);
property BoldObjects[index: Integer]: TActor
read GetBoldObject write SetBoldObject; default;
end;
TFamilyList = class(TPeopleClassesRootList)
protected
function GetBoldObject(index: Integer): TFamily;
procedure SetBoldObject(index: Integer;
NewObject: TFamily);
public
function Includes(anObject: TFamily): Boolean;
function IndexOf(anObject: TFamily): Integer;
procedure Add(NewObject: TFamily);
function AddNew: TFamily;
procedure Insert(index: Integer; NewObject: TFamily);
property BoldObjects[index: Integer]: TFamily
read GetBoldObject write SetBoldObject; default;
end;
Дополнительная информация
За дополнительной информацией обращайтесь в компанию Interface Ltd.
INTERFACE Ltd. |
|