ONTARIO1 представляет собой фреймворк (framework), ориентированный на применение в системах учета для быстрого построения бизнес-приложений. Фреймворк существует в виде библиотеки классов Delphi и реализации методов этих классов, касающихся доступа и обработки данных в виде процедур (stored procedures) сервера БД MS SQL Server. MS SQL Server имеет достаточно мощное расширение ANSI SQL-92 в виде языка Transact SQL, который позволяет реализовать сложную обработку данных на сервере БД.
Условно структуру системы можно разбить на три части или слоя:
Объектная логика реализована в виде библиотеки классов Delphi. Все классы в ONTARIO1 наследуются от единого базового класса. Каждый класс имеет также свои визуальные формы для отображения информации в клиентском приложении, которые также наследуются от соответствующих форм суперклассов.
В самой системе можно выделить две основных части:
Первая часть, как правило, не является предметом изменения и расширения, так как не реализует прикладного назначения системы и может быть модифицирована только при необходимость расширять или изменять сервис ядра. Вторая часть является предметом расширения, изменения и адаптации к существующим прикладным задачам. В данном руководстве речь будет вестись в основном о второй части.
Delphi представляет собой визуальную объектно–ориентированную среду разработки и программирования, в то время как MS SQL Server является реляционной СУБД. Объектный подход к логической организации данных на основе реляционной модели их хранения и обработки позволяет исключить прямой доступ к таблицам со стороны клиентского приложения, которое не знает, как именно и где расположены сами данные, но знает интерфейсные методы их получения, используя в качестве API механизмы вызова встроенных процедур сервера БД.
Объект в понятии приложения и БД является некоторой сущностью - отражением объекта реального мира, обладающей определенными свойствами (атрибутами) и методами (процедурами), вся информация о которой, связанная с логикой интерфейса пользователя содержится в самом приложении, тогда как логика обработки данных-в базе.
Объект создается на основе класса, который представляет собой специализированный класс (компонент) Delphi, обладающий базовыми свойствами, методами и обработчиками событий, связанных с данными в базе, и непосредственно интерпретирующий объектную модель обработки данных в реляционную путем вызова в интерфейсных методах класса процедур БД. Таким образом, свойства объекта явно хранятся в БД в виде атрибутов отношений либо неявно в виде результатов выполнения встроенных процедур. Методы можно разделить условно на управляющие данными, управляющие интерфейсом и смешанные. Методы управления данными в общем случае состоят из вызова одной или более встроенных процедур БД, например, метод для пересчета суммы двух атрибутов объекта и сохранения ее в третьем. Управляющие интерфейсом состоят из логики взаимодействия с пользователем в зависимости от класса объекта, например, заполнение опций контекстного меню объекта в приложении смысловым содержанием доступных методов. Смешанные методы обладают всеми перечисленными возможностями, например, вывод интерфейсной формы для редактирования свойств объекта предваряется получением таковых из БД.
Объект существует в представлении клиентского приложения и одновременно в БД, которая содержит его свойства (атрибуты) и реализации методов (процедуры БД). Объекты в БД хранятся в виде древовидной иерархической структуры неограниченного уровня вложения. Объекты условно разделяются на "Папки" и "Не папки". Папки могут содержать в себе другие объекты, в том числе и папки, образуя поддерево. Для навигации по БД в клиентском приложении существует аналог Windows-Проводника, позволяющий перемещаться по папкам и производить действия со всеми объектами.
Все имена файлов Delphi и MS SQL рекомендуется сокращать до 8 символов.
Классы именуются следующим образом. Первая буква - всегда T (
Type), далее DBO (DataBase Object) и затем с заглавной буквы смысловое название класса, например TDBOUser, TDBOFolder и т.д. Исключение составляет базовый класс, который носит название TDBObject. Имя класса не должно превышать 16 символов.Встроенные процедуры имеют разделение на системные и прикладные, реализующие тот или иной интерфейсный метод класса, связанный с обработкой данных. Системные процедуры имеют название вида spXXX, где sp – признак общесистемной процедуры, XXX – смысловое содержание, например spCreateObj - процедура создания объекта в БД. Прикладные процедуры всегда связаны с конкретным классом, поэтому их название начинается с имени класса, далее идет символ подчеркивания “_” и смысловое название, которое может и не совпадать с названием соответствующего метода. Например
TDBObject_Create – процедура создания объекта класса TDBObject, а TDBObject_Save – процедура сохранения отредактированных свойств объекта класса TDBObject, используемая в системе не только при редактировании.Названия полей (атрибутов) таблиц БД, создаваемых прикладными модулями, должны соответствовать смысловому содержанию и даются на английском языке с некоторыми сокращениями (не рекомендуется давать названия более 10-15 символов для эргономичности), с применением как верхнего, так и нижнего регистра латиницы. Например, поле хранения номера паспорта может иметь вид PaspNum и т.п. Для полей–идентификаторов (первичных и вторичных ключей) требуется применение в названии аббревиатуры ID (идентификатор), например FirmID – идентификатор фирмы.
Диалоговые формы именуются следующим образом. Начало названия состоит из frmDBO, далее название объекта и название соответствующего метода, который вызывает форму, например frmDBOUserEdit - форма редактирования класса "Пользователь". Файл, содержащий модуль формы, имеет длину 8 символов, поэтому он именуется по следующему принципу: первые 3–4 символа – краткое название класса без приставки TDBO, далее 4–5 символов – краткое название соответствующего метода. Например, для формы frmDBOUserEdit файл будет называться UserEdit.pas , а для формы frmDBOSend – ObjSend.pas .
При именование компонентов в формах следует придерживаться “венгерской” записи, которая состоит из префикса, обозначающего тип объекта или переменной, и суффикса со смысловым значением. Например dbgSubTree – Database Grid отображающий некоторое поддерево, dsrcSubTree – источник данных для этого поддерева и т.п. Значения префиксов компонентов в ONTARIO1 не являются обязательными и однозначно определенными для всех компонентов, поэтому их применение зависит от программиста. Можно рекомендовать только придерживаться того стиля, который используется в исходных программных кодах системы.
Для краткости изложения, члены данных класса далее по тексту именуются свойствами, а члены-функции - методами. В литературе, как правило, методами называют виртуальные члены-функции. В классах ONTARIO1 практически все члены-функции являются виртуальными, поэтому мы можем сделать такое допущение при изложении.
Все классы ONTARIO1 наследуются от некоторого базового класса, который называется в системе "Абстрактный объект" (TDBObject), поэтому все сказанное о данном классе относится и ко всем другим классам системы. Данный класс было бы неверно называть абстрактным, так как большинство его методов виртуальны и уже имеют реализацию. Напомним, что абстрактный класс содержит только абстрактные виртуальные методы. Базовый класс обладает следующими свойствами:
Табл.2.1. Свойства базового класса TDBObject
Наименование |
Тип данных |
Краткое описание |
OID | целое | Уникальный идентификатор объекта |
Name | строка (128) | Наименование объекта |
Ext | строка (128) | Расширение наименования (дополнительная информация об объекте) |
CreationDate | дата и время | Дата и время (как правило - создания объекта) |
Attrib | целое | Атрибут для хранения информации в подклассах |
Summ | денежный | Атрибут для хранения информации в подклассах |
State | строка (16) | Атрибут для хранения информации в подклассах |
FolderID | целое | ID папки, в которой расположен данный объект, если 0 - в корне |
Deleted | целое | признак того, что объект логически удален |
OwnerID | целое | ID создателя объекта |
Shortcut | целое | Признак, является ли объект ссылкой (1) или нет (0) |
OriginID | целое | ID объекта, ссылкой на который является данный объект |
BaseClass | строка (16) | Имя класса объекта |
DelMode | целое | Режим удаления объекта (0-логический, 1-физический, 2-запрещен) |
Свойства объектов базового класса, хранятся в БД в таблице Objs, содержащей все вышеперечисленные свойства абстрактного класса в виде одноименных атрибутов (полей). Каждый объект имеет уникальный идентификатор (номер), который одновременно является его первичным ключом. OID может принимать значения от 1 до 231-1. Иерархическое хранение объектов достигается за счет наличия ссылки FolderID, при этом ссылка на FolderID=0 является признаком того, что объект находится в корневой папке. Корневая папка имеет OID=0, не существует в БД и является виртуальной папкой.
Базовый класс имеет следующие методы:
Табл.2.2. Методы базового класса TDBObject
Название | Форма Delphi | Краткое описание |
CreateDBO | TfrmDBOCreate | Вызывает форму создания нового объекта |
CreateDBOClone | - | Инициирует в системе создание нового объекта по некоторому уже существующему |
DeleteDBO | TfrmDBODelete | Вызывает форму удаления объекта из системы |
UndeleteDBO | TfrmDBOUndelete | Вызывает форму восстановления логически удаленного объекта |
Edit | TfrmDBOEdit | Вызывает форму редактирования объекта |
View | TfrmDBOView | Вызывает форму просмотра объекта |
Move | TfrmDBOMove | Вызывает форму перемещения объекта из папки в папку |
- | Вызывает форму печати объекта, если таковая существует | |
PrintToWord | TfrmDBObjectExportForms | Экспортирует свойства объекта в форму документа MS Word и переходит в режим печати, если таковая существует |
ExportFormToWord | TfrmDBObjectExportForms | Экспортирует свойства объекта в форму документа MS Word, если таковая существует |
SendToUser | TfrmDBOSendToUser | Вызывает форму пересылки объекта пользователю |
MakeShortcut | TfrmDBOMakeShortcut | Вызывает форму пересылки ссылки на объект пользователя |
SetPermissions | TfrmDBOAccess | Вызывает форму просмотра и изменения прав доступа к объекту |
SysInfo | TfrmDBOSysInfo | Вызывает форму просмотра системных свойств объекта |
ViewPath | TfrmDBOViewPath | Вызывает форму просмотра пути к объекту в дереве папок |
ViewHistory | TfrmDBOViewHistory | Вызывает форму просмотра истории изменений объекта |
Как следует из описания методов, логика реализована в формах базового класса и процедурах БД, которые вызываются этими формами. Иерархия базовых классов форм в ONTARIO1 имеет следующую структуру:
TForm | |||
\------ | TfrmBaseDialog | ||
\--------------- | TfrmBaseView | ||
\ | \--------------------------- | TfrmDBOView | |
\ | \--------------------------- | TfrmDBOSysInfo | |
\ | \--------------------------- | TfrmDBOViewPath | |
\ | \--------------------------- | TfrmDBOViewHistory | |
\--------------- | TfrmBaseEdit | ||
\ | \--------------------------- | TfrmDBOCreate | |
\ | \--------------------------- | TfrmDBOEdit | |
\ | \--------------------------- | TfrmDBOAccess | |
\--------------- | TfrmBaseAction | ||
\ | \--------------------------- | TfrmDBODelete | |
\ | \--------------------------- | TfrmDBOUndelete | |
\ | \--------------------------- | TfrmDBOMove | |
\ | \--------------------------- | TfrmDBOSendToUser | |
\ | \--------------------------- | TfrmDBOMakeShortcut | |
TfrmModalDlg | |||
\--------------- | TfrmDBObjectExportForms |
Рис.2.1. Иерархия базовых классов форм
Интерфейс формы TfrmBaseDialog описана в файле BaseDlg.pas как:
TfrmBaseDialog = class( TForm )
. . .
public
DataChanged: boolean;
DBOInfo : TDBOInfo;
hSender : HWND;
RetCode : integer;
procedure FormPrint; virtual;
procedure FormRefresh; virtual;
procedure InitDataEnvironment( DBOInfo: TDBOInfo ); virtual;
procedure InitFromTemplate( TemplateID: integer ); virtual;
procedure InitClone( MasterOID: integer ); virtual;
procedure InitFormControls; virtual;
function ValidCheck: boolean; virtual;
procedure BeginTransaction; dynamic;
procedure Commit; dynamic;
procedure Rollback; dynamic;
published
property ContextHelp : boolean read GetContextHelp write
SetContextHelp;
property OnRefreshData: TNotifyEvent read FOnRefreshData write
FOnRefreshData;
end;
Остановимся подробнее на назначении методов базовых классов форм.
Виртуальный метод InitDataEnvironment является стандартным для инициализации компонентов доступа к данным в форме, например для инициализации параметров вызова встроенных процедур чтения данных из БД. Он должен вызываться сразу после создании формы в программе, как это сделано, например в методе View класса DBObject:
procedure TDBObject.View;
var frmView: TfrmBaseDialog;
begin
if MethodFormRef = nil then MethodFormRef := TfrmDBOView;
frmView := MethodFormRef.Create( Application );
frmView.InitDataEnvironment( DBOInfo );
frmView.InitFormControls;
end;
Здесь DBOInfo - структура типа TDBOInfo, содержащая свойства базового класса, приведенные в табл.2.1. Само описание структуры приведено в DBOConst.pas.
Виртуальный метод InitFormControls выполняет восстановление размеров окна формы и некоторых ее компонентов, например, ширину колонок в DBGrid. Состояние формы автоматически запоминается в файле конфигурации ontario.ini при закрытии формы, унаследованной от TfrmBaseDialog.
Виртуальная функция ValidCheck предназначена для проверки корректности заполнения тех или иных полей в форме либо каких–либо других логических условий. Она автоматически вызывается всякий раз при попытке сохранить отредактированные данные в форме и при успешной проверке далее вызывается виртуальный метод SaveDataEnvironment. Программисту требуется лишь при необходимости проверок переопределить функцию следующим стандартным образом, например так:
function TfrmDBOAccCalcEdit.ValidCheck:
boolean;
begin
Result := inherited
ValidCheck;
{ код проверки корректности заполнения
формы }
if edtBank.Value = 0 then
raise
Exeption.Create( 'Не заполнено поле <Банк>' );
end;
В свойстве
RetCode помещается результат последней выполненной встроенной процедуры записи данных в БД, которых в форме с увеличением наследуемых классов будет прибавляться. Для этого следует явно после выполнения очередной процедуры присваивать свойству RetCode параметр Result, но это происходит в виртуальном методе SaveDataEnvironment – стандартном методе записи изменений при редактировании, создании и других операциях. Данный метод появляется только в классе форм TfrmBaseEdit, являющимся базовым для всех форм любого вида редактирования объектов БД. Если в процессе существования формы данные были изменены (соответственно, DataChanged = true), то всегда вызывается диалог, позволяющий выбрать отказ или сохранение изменений. В случае выбора сохранения изменений следует вызов метода SaveDataEnvironment.TfrmBaseEdit = class( TfrmBaseDialog )
. . .
public
procedure SaveDataEnvironment; virtual;
end;
Все действия, исполняемые в процедуре SaveDataEnvironment выполняются в транзакции, причем это является свойством уровня ядра и не требует никакого программирования со стороны прикладного разработчика.
Стандартное использование транзакций, обеспечивающее целостность данных и обработку ошибок, возвращаемых сервером – в переопределяемом методе SaveDataEnvironment или в обработчике события нажатия кнопки “ОК” – реализуется автоматически в любой форме, унаследованной от TfrmBaseEdit и TfrmBaseAction или методе абстрактного объекта. Программисту нет необходимости думать о транзакциях при использовании стандартных средств. Рассмотрим типичный пример в форме создания нового объекта класса “Пользователь”:
procedure TfrmDBOUserCreate.SaveDataEnvironment;
begin
inherited;
spTDBOUser_Create.Active := false;
spTDBOUser_Create.ParamByName( '@OID' ).AsInteger := DBOInfo.OID;
spTDBOUser_Create.ParamByName( '@Login' ).AsString :=
edtLogin.EditText;
spTDBOUser_Create.ExecProc;
RetCode := spTDBOUser_Create.ParamByName( 'Result' ).AsInteger;
end;
Если все же возникнет необходимо управлять транзакциями, используйте API абстрактного объекта (TDBObject) либо одноименные методы диалоговой формы (TfrmBaseDialog):
procedure BeginTransaction – начинает транзакцию;
procedure Commit – фиксирует транзакцию;
procedure Rollback – откатывает транзакцию.
Класс форм
TfrmBaseAction является базовым для всех форм, где присутствует диалог типа “ОК – Отменить”, например в диалоге пересылки объекта (форма TfrmDBOSend). Методы InitDataEnvironment, ValidCheck здесь также присутствуют, причем SaveDataEnvironment автоматически вызывается обработчиком события нажатия кнопки “ОК”.
Содержание Глоссарий Предыдущая Следующая