Lotus Notes / Domino – прекрасная платформа для создания мощных корпоративных
информационных систем, ориентированных на групповую работу с электронными
документами. В своей работе над комплексной медицинской информационной системой
"Кондопога" мы на основе тщательного анализа средств разработки и
имеющихся на рынке СУБД выбрали Lotus Notes / Domino в качестве основы всей
системы. Разработка осуществляется с 1999 года, за это время мы постепенно
перешли с версии 4.6 на версию R 5, а затем – на R 6. В данный момент идет
тестирование R 6.5 на совместимость с существующим ПО.
Lotus Notes / Domino полностью отвечает ключевым требования к созданию
медицинской информационной системы по надежности, безопасности,
отказоустойчивости и масштабированию. Работа пользователя в этой среде в
максимальной степени приближена к привычной работе с документами – фактически,
бумага и авторучка у медицинских сотрудников заменена на компьютер. Формы
электронных документов могут быть разработаны по точной аналогии с их бумажными
аналогами (при необходимости), а стандартные средства для работы с документами
(создание, редактирование, печать, отправка по e - mail, электронная цифровая
подпись и т.д.) требуют от пользователя минимального объема обучения.
Однако, как и в любой информационной технологии, имеется ряд недостатков, с
которыми приходится мириться и искать пути их преодоления. Основной их
недостатков Lotus Notes / Domino для применения в медицинской сфере – это слабая
поддержка таблиц в электронных документах. На практике даже с точки зрения
пользователя встроенные в клиентское программное обеспечение Lotus Notes
средства для работы с таблицами значительно уступают аналогичным инструментам в
Microsoft Office. А с точки зрения инструментария разработчика средства для
управления таблицами тем более являются малоэффективными. Некоторые изменения в
этом направлении были сделаны в версии R 6 Domino, однако и они являются
недостаточными. Фактически, в Lotus Notes таблица, как средство отображения,
управления и хранения информации, отсутствует как класс. Но это и понятно – ведь
Lotus Notes – это, прежде всего, объектно-ориентированная СУБД, предназначенная
для групповой работы над документами.
Вместе с тем в нашей работе поддержка табличного формата хранения информации
является неотъемлемой функцией системы. Некоторые документы (лист назначений,
например) и некоторые приложения (бухгалтерия, аптека, склад, автоматизация
службы питания и т.д.) несравненно более эффективно работаю под управлением
реляционной СУБД, чем в среде Lotus Notes / Domino. Все это породило
необходимость совместного использования Lotus Notes / Domino и реляционной СУБД,
в качестве которой был выбран Microsoft SQL Server . В качестве средства
разработки в Lotus Notes / Domino используется специальное программное
обеспечение Lotus Designer, позволяющее создавать мультиплатформенные приложения
на Visual Basic -подобном языке Lotus Script, @-формулах или Java Script. Это
мощное приложение позволяет за очень небольшое время разрабатывать необходимые
программы как для выполнения в среде Lotus Notes, так и для работы в обычном
браузере Internet. Однако для создания приложения для реляционной СУБД его
возможностей явно недостаточно. Поэтому в качестве дополнительного
инструментария мы используем Borland Delphi (в настоящее время – версию 6.0).
Одним из серьезных препятствий на использовании Delphi является задача
совместного доступа как к информации в реляционной базе данных, так и для
доступа к базам данных Lotus Notes / Domino. Для решения этой задачи имеется
несколько подходов:
- Использование компонентов сторонних производителей (http://www.torry.net/index.htm,
http://www.geocities.com/SiliconValley/Peaks/8307/)
- Использование приложения Lotus Notes SQL (http://www-10.lotus.com/ldd)
- Разработка собственных компонентов, используя Notes API (http://www.notesnet.ru/)
- Доступ к ресурсам Lotus Notes посредством OLE.
Первый подход подразумевает использование компонентов для доступа к Lotus
Notes. При этом программы могут обращаться к базам данных и документам,
используя инкапсулированные в эти компоненты свойства и методы. Мы апробировали
имевшиеся в свое время предложения и не нашли решения, полностью
удовлетворяющего наши требования. Использование компонентов вносило
нестабильность в создаваемые приложения, которые нам не удавалось быстро
локализовать и исправить, т.к. либо с разработчиками не возможно было наладить
контакт, либо тех.поддержка требовала дополнительных финансовых затрат и
времени.
Второй подход также, к сожалению, не отвечал требованиям. При этом Notes SQL
фактически эмулирует обращение к базе данных Lotus Notes, как к обычной
реляционной таблице. Тестирование различных версий Notes SQL показала
нестабильность этого программного обеспечения. Особенно ярко недостатки Notes
SQL проявлялись при обработке больших объемов информации – в случайные моменты
работы программы возникали неустранимые ошибки, которые приводили к полном
прекращению работы программ.
Третий подход является более предпочтительным, однако и от него мы со
временем отошли в силу его трудоемкости, большой сложно написания программы,
массы низкоуровневого кода и высоких требований к знанию внутренний архитектуры
Lotus Notes.
Первое время доступ к Lotus Notes посредством OLE казался нам неприемлемым
вариантом с точки зрения скорости работы. Однако наш 5-летний опыт работы
доказал высокую устойчивость программ на основе этого подхода и вполне
приемлемую скорость обработки информации.
Далее мы на примерах покажем, как написать приложение в среде Borland Delphi
для баз данных Lotus Notes.
1. Инициализация сессии.
Основной принцип в написании программ состоит в использовании встроенных
классов Lotus Notes в коде программ. Для этого в первую очередь необходимо
инициализировать сессию связи с Lotus Notes. Для этого требуется, чтобы
клиентское программное обеспечение Lotus Notes было инсталлировано на каждом
компьютере, использующим программу и подключено к одному или нескольким серверам
Domino.
Создадим новое приложение. В разделе uses главного окна приложения укажем
ComOBJ – это библиотека, позволяющая вызывать и обращаться к OLE -объектам .
В разделе public объявим переменные, общие для всего приложения:
public
{ Public declarations }
MySession : OLEVariant; // текущая сессия Lotus Notes
MyLNDataBase : OLEVariant; // база данных Lotus Notes...
Теперь необходимо написать обработчик события OnCreate главной формы
приложения, в котором мы должны создать объект NotesSession, чтобы, используя
его в дальнейшем, иметь возможность в рамках одного приложения обращаться сразу
к нескольким базам данных, серверам, документам, представлениям и т.д.
Обработчик должен иметь следующий вид:
procedure TfmMain.FormCreate(Sender: TObject);
begin
MySession:= createOLEObject('Notes.Notessession');
if varisempty(MySession) then
begin
ShowMessage('Не могу создать сессию с сервером Lotus Notes');
Exit;
end;
end;
Следует иметь в виду, что в рамках одного приложения следует только один раз
инициализировать объект Notessession, т.к. каждая последующая инициализация
будет закрывать предыдущую сессию, а все объекты, созданные на основе этой
сессии, потеряют свою актуальность и их обработка будет невозможна.
2. Доступ к базе данных
После того, как мы инициализировали сессию связи с Lotus Notes, мы можем
обращаться к любым серверам Lotus Domino и базам данных на них. Принципиально
получить доступ к БД Lotus Notes можно 2 способами – либо обратиться к текущей
базе данных, открытой в Lotus Notes, либо вызвать соответствующий метод
NotesSession и открыть любую другую БД . Последний случая является наиболее
востребованным, поэтому рассмотрим его:
procedure TMyButtomClick(Sender: TObject);
var MyServer: string;
begin
// Необходимо вычислить имя сервера,
// на котором находится необходимая нам БД
MyServer:=...
// Теперь открываем БД – например, откроем адресную книгу сервера
MyLNDataBase:=MySession.GetDataBase(MyServer, ‘names.nsf’);
end;
Мы в своей работе используем реестр Windows, в котором храним имя сервера
Domino по умолчанию, к которому подключаются приложения. Для упрощения
разработки и администрирования программ мы использую функцию
GetDefaultServerName, которая работает по следующему алгоритму:
- При вызове функции она проверяет наличие определенного ключа
в реестре Windows.
- Если этот ключ отсутствует или он содержит пустое значение,
функция обращается к файлу notes.ini и считывает из него
значение параметра почтового сервера Notes. Имя сервера
записывается как значение ключа Windows
- Если ключ в реестре Windows имеется и не содержит пустое
значение, функция считывает его и возвращает в качестве ответа.
Таким образом, при первом старте приложения оно самостоятельно выполняет
настройку реестра Windows на подключение к текущему серверу Domino. Если в
дальнейшем требуется перенаправить работу приложения на другой сервер, то либо
пользователь при помощи встроенных в приложение визуальных средств, либо
администратор сети вручную меняют значение ключа. Т.о. со следующего запуска
начинает обращаться к другому серверу – обеспечивает поддержка мультисерверной
конфигурации информационной системы.
3. Работа с базой данных
Из программы, написанной в Borland Delphi, доступны практически все свойства
и методы, предусмотренные разработчиками Lotus Notes / Domino. В том числе Вы
можете осуществлять навигацию по представлениям, осуществлять поиск документов в
базе данных, в том числе и гипертекстовый поиск и т.д. Особенностей по работе с
базой данных вследствие использования Delphi мы не обнаружили. Поэтому в
качестве примера приведем фрагмент кода, осуществляющий последовательный перебор
и считывание документов из коллекции документов NotesDocumentCollection базы
данных адресной книги сервера.
procedure TfmMainWindow.BitBtn1Click(Sender: TObject);
var DocumCount: longint; // количество документов в коллекции
i : longint; // шаг цикла
B1: OLEVariant; // переменная для объекта NotesDatabase
BodyQuery: ansistring;
C1: OLEVariant; // переменная для объекта NotesDocumentCollection
D1: OLEVariant; // переменная для объекта NotesDocument
begin
DocumCount:=0;
// Получаем доступ к БД.
B1:= MySession.GetDatabase(GetDefaultServerName,'names.nsf');
BodyQuery:='Form = "Person"';
// Для поиска используем специальную функцию LNSearch
C1:=LNSearch(MySession,B1,’Пример запроса’,BodyQuery);
DocumCount:=C1.Count;
if DocumCount=0 then Exit; // искомые документы не найдены
D1:=C1.GetFirstDocument;
for i:=1 to DocumCount do
begin.... здесь осуществляется обработка документа
D1:=C1.GetNextDocument(D1);
end;
end;
В этом примере программа обращается к текущему серверу и открывает на нем
базу данных адресной книги. Затем, используя специально разработанную функцию
LNSearch, производит поиск документов в базе данных. Если не найдено ни одного
документа, то работа процедуры завершается. Если какие-то документы найдены, то
они последовательно обрабатываются в цикле. Применение специальной функции
LNSearch обусловлено тем, что стандартный метод Search в классе NotesDatabase,
кроме формулы для поискового запроса, требует передать дату самого старого
документа, который этот запрос сможет вернуть в качестве результата. При этом
дата должна быть передана не в качестве переменной типа TDate или TDateTime, а в
качестве OLEVariant -переменной, созданной как объект класса NotesDataTime.
function LNSearch(LNSession, LNDataBase: OLEVAriant;
Logo: string;query: string):OLEVariant;
var r1:WideString;
r2: OLEVariant;
r3: Smallint;
C1: OleVariant;
begin
r1:=query;
r2:=LNSession.CreateDateTime('01.01.1990'); // здесь может быть любая дата
r3:=0;
C1:=LNDataBase.SEARCH(r1,r2,r3);
Result:=C1;
end;
Отметим, что по нашим наблюдениям, при написании программ в Borland Delphi
следует стремиться использовать навигацию по представлениям вместо использования
метода search. При этом скорость обработки одной и той же коллекции документов,
полученной из представления, примерно на 40% выше, чем при обработке документов,
полученных поиском в базе данных.
4. Работа с документами
В отличие от работы с базами данных, обработка документов Lotus Notes имеет
массу подводных камней. При этом в программах приходится выполнять много
одинаковых операций, которые целесообразно выделять в отдельные функции. Вначале
рассмотрим стандартную функцию считывания текстового значения поля из документа.
function LNGetFieldStrValue(Document: OLEVariant;
FieldName: string;
DefaultValue: string): AnsiString;
var SendValue, RetValue: OLEVariant;
TmpS: Ansistring;
MyPos: integer;
begin
TmpS:=' ';
if FieldName<>'' then
begin
SendValue:=FieldName;
if not varisempty(Document) then
begin
Try
RetValue:=Document.HasItem(FieldName);
except
begin
RetValue:=false;
end; // do
end; // Try
if RetValue then
begin
RetValue :=Document.GetFirstItem(SendValue);
try
TmpS:=RetValue.Text;
except
TmpS:=DefaultValue;
end;
end else TmpS:=DefaultValue;
end else TmpS:=DefaultValue; // varisempty chek
end else TmpS:=DefaultValue;
if TmpS='' then TmpS:=DefaultValue;
Result :=tmpS;
end;
Эта простая функция позволяет значительно упростить написание программ,
особенно в случае, когда документ содержит большое количество полей, значения
которых необходимо считать и обработать. Необходимо отметить, что очень часто в
полях документов Lotus Notes хранится несколько значений или значения записаны с
символами, препятствующими корректной работе со строками в Borland Delphi. Мы в
таком случае используем перегруженную версию представленной функции, которая
может возвращать «очищенную» строку или определенную подстроку.
По аналогии с представленным примером разработаны и версии для числовых
полей, а также полей с датой или временем, что представляет особую трудность при
написании программ. В таком случае, кроме стандартных проверок на корректность
документа, наличия в нем указанного поля, функция может проверить тип
возвращаемого значения или выполнить необходимые преобразования. Например,
возможна конвертация строкового значения в число или смена символа разделителя
разрядов на основании текущих настроек операционной системы.
Несколько усложненный пример – это считывание значения поля в профайле. Как
известно, Lotus Notes, кроме стандартных документов, позволяет поддерживать
хранение информации в т.н. профайлах – документах, к которым можно обратиться по
имени формы и, как дополнение, по имени текущего пользователя. Для чтения
текстового значения из профайла рассмотрим следующую функцию:
function LNGetProfileField(MySession, MyDBName: OLEVariant;
MyServerName, MyProfileName, MyUserName, MyFieldName: string):string;
var D1: OLEVariant;
tmpS: AnsiString;
begin
if MyServerName='' then
tmpS:= GetDefaultServerName else tmpS:=MyServerName;
if varisempty(MyDBName) then
begin
ShowMessage('Фатальная ошибка! Переданный объект
<База данных> пуст. Продолжение невозможно!');
Exit;
end;
D1:=MyDBName.GetProfileDocument( MyProfileName, MyUserName);
if varisempty(D1) then
begin
ShowMessage ('Ошибка при получении профайла '+MyProfileName+'
из базе данных '+MyServerName+
' / '+MyDBName.Name+'. Продолжение невозможно!');
Exit;
end;
tmpS:=LNGetFieldStrValue(D1,MyFieldName,'',False);
Result :=tmpS;
end;
Как видно из примера, эта функция использует стандартную функцию
LNGetFieldStrValue, представленную ранее, но перед этим выполняет ряд
дополнительных проверок и операций.
5. Выводы
Мы используем представленную технологию в практической разработке медицинской
информационной системы "Кондопога" вот уже в течение 5 лет. За это время
многократно убедились в прекрасной устойчивости и приемлемой скорости работы
программ, написанных на Borland Delphi для баз данных Lotus Notes / Domino.
Фактически мы убедились, что способны создавать программы на Borland Delphi,
которые используют весь арсенал встроенных в Lotus Notes классов.
Отметим, что со временем в арсенале программиста накапливается самая
разнообразная масса готовых функций и процедур, которые целесообразно
аккумулировать либо в виде подключаемых библиотек, либо в виде отдельных модулей
(pas -файлов). При этом, по нашим наблюдениям, время на разработку новой
программы можно сократить в несколько раз именно за счет использования готовых и
отлаженных приложений. А это позволяет снизить стоимость разработки и повысить
устойчивость приложений, что является уже не столько инструментарием
разработчика, сколько экономическим стимулом.
Постепенно нами была накоплена целая библиотека класса middleware, которая
реализует практически весь необходимый функционал для написания программ в
Borland Delphi для среды Lotus Notes. Это позволило разработать нашу
информационную систему таким образом, что взаимные недостатки реляционных и
объектно-ориентированных баз данных фактически полностью компенсируются
взаимными достоинствами. Поэтому пользователи ИС "Кондопога" одинаково комфортно
используют и возможности совместной работы над электронными документами Lotus
Notes и встроенные в базы данных Domino приложения, предоставляющие расширенные
возможности работы с таблицами реляционных баз данных, мгновенное построение
диаграмм на основе данных из документов Lotus Notes и т.д.
Гусев А.В., Дмитриев А.Г., Тихонов С.И.
|