"Linter Application Builder (LAB): кросс - платформенный инструмент для быстрой разработки приложений клиент-сервер"

LAB: назначение и область применения

ЗАО НПП "РЕЛЭКС"

Linter Application Builder является уникальным средством для быстрой разработки приложений клиент-сервер (RAD). Это единственная система такого класса, полностью разработанная российскими специалистами. Используя имеющийся инструментарий, разработчики могут быстро создавать переносимые прикладные программы с графическим интерфейсом пользователя, использующие реляционные СУБД, поддерживающие язык запросов SQL для доступа к данным.

Первичной целью проекта LAB являлось создание удобного средства разработки для СУБД ЛИНТЕР, которое бы наиболее полно и эффективно использовало возможности этой СУБД. Впоследствии в LAB были реализованы компоненты для доступа к данным через ODBC, чтобы дать разработчикам использовать другие популярные коммерческие и свободно распространяемые РСУБД, такие как Oracle, Microsoft SQL Server, MySQL и т.п.

Одним из основных преимуществ, которые могут получить разработчики, используя LAB, является переносимость, как самой среды разработки, так и созданных с ее помощью приложений. Причем приложение, построенное на одной платформе, может исполняться на любой другой без дополнительных доработок и даже без перекомпиляции кода. Достигается это за счет использования технологии компиляции приложений в байт-код (аналогично Java). Подобными возможностями на сегодняшний день не может похвастаться ни одно средство быстрой разработки клиент - серверных приложений. Имеющиеся среды разработки для языка Java ориентированы на создание приложений произвольного характера и не содержат многих возможностей облегчающих процесс создания приложения, работающего с РСУБД. В то же время LAB специально разрабатывался именно для этих целей, хотя создаваемые в его среде приложения могут выполнять произвольные функции.

Большинство развитых RAD-систем ориентировано на Windows (Power Builder, Visual Basic, Delphi и т.д.). Исключением является, пожалуй, только система Kylix от Borland, но она ориентирована исключительно на создание приложений под Linux и обеспечивает переносимость только на уровне правильно написанных исходных текстов.

LAB же ставит иную цель: дать возможность эксплуатировать готовое приложение на разнообразных платформах. В настоящее время поддерживаются операционные системы Windows (9x,NT,2000,XP), Linux, Free BSD, Sun Solaris на аппаратных платформах Intel и SPARC. Не существует ограничений для переноса системы и на другие программные Unix-платформы и аппаратную платформу MIPS.

Архитектура LAB

Основу LAB составляют:

Компоненты представляют собой те "кирпичики", из которых складывается приложение. В LAB все компоненты подчиняются следующим общим требованиям:

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

Иерархия компонентов приложения с их свойствами и обработкой событий представляется в виде кода на объектно-ориентированном языке, в котором компонент соответствует классу, экземпляр компонента - объекту, а свойства и методы - атрибутам и методам класса и объекта.

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

Разработка во многом упрощается за счет того, что сами компоненты стандартной библиотеки являются достаточно интеллектуальными и выполняют большую работу внутри. Тот факт, что стандартные компоненты полностью реализованы на языке C++, позволяет минимизировать потери производительности приложения, компилированный код которого интерпретируется виртуальной машиной.

Стандартная библиотека в LAB реализована посредством переносимой библиотеки классов C++ RelAPI, являющейся инструментом для разработки переносимых приложений с графическим интерфейсом пользователя в компании РЕЛЭКС. Эта библиотека реализована на основе Win32 API в среде Windows и на основе библиотеки Qt в среде Unix.

Отдельные модули приложения могут быть повторно использованы при реализации других проектов. Для этого разработчик может объявить эти модули в качестве новых компонентов.

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

В состав интегрированной среды разработки входят:

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

Реализация графического интерфейса приложения с пользователем

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

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

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

Для визуальных компонентов определены и общие события, такие как:

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

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

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

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

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

Механизмы для работы с БД

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

Основной концепцией для доступа к данным является понятие источника данных. Источник данных - это не визуальный компонент, обладающий следующими свойствами:

Отличительной особенностью механизма работы с данными является то, что любой визуальный элемент может быть привязан к любому источнику данных, не зависимо от того, поставляются ли данные от СУБД ЛИНТЕР, источника ODBC или из памяти. Это позволяет использовать одну и ту же форму, как для временного ввода информации, так и для непосредственной работы с БД. Таким образом, в LAB нет нескольких повторяющихся семантически наборов элементов управления (как скажем, в Delphi и Kylix), вместо этого одни и те же элементы управления могут использоваться для разных целей (это определяется тем, привязан ли компонент к источнику данных и к какому именно).

Данные из источников могут отображаться любыми визуальными компонентами. Например, компонент-изображение CImage будет автоматически отображать графический данные, взятые из полей типа BLOB, а компонент CTreeView будет автоматически строить дерево по структуре данных, содержащей дополнительное поле LEVEL (уровень иерархии). Такая структура данных автоматически может быть получена одним SELECT-запросом с CONNECT BY. Запросы такого типа поддерживаются многими СУБД, например Oracle и ЛИНТЕР.

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

В простейшем случае, два источника данных и один компонент - связь реализуют схему master-detail. Однако этим возможности не ограничиваются. Источник данных может быть связан с любым количеством других источников, и все эти связи обрабатываются автоматически (естественно, предусмотрено детектирование циклов).

Связь источников данных может выполняться как по равенству пар полей, так и по значениям параметров, которые подставляются в произвольный SELECT-запрос в подчиненном источнике данных.

Разработчики прикладных систем часто сталкиваются с ситуацией, когда в форме приложения вместо одних данных основного запроса должны показываться другие, выбираемые из внешней справочной таблицы по простому или составному внешнему ключу. Кроме того, при вводе данных пользователю должен предоставляться интерфейс, позволяющий выбрать информативное значение из внешней таблицы так, чтобы в основной источник данных вставлялись соответствующие значения ее первичного ключа. Во многих мощных средствах быстрой разработки имеется соответствующий тип компонентов - поисковые поля (lookup fields). Имеется такая возможность и в LAB, причем есть несколько вариантов.

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

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

Пользователь может выбрать значение как из однострочного комбинированного поля ввода с выпадающим списком, так и из ячейки табличного компонента. При этом по умолчанию используется стандартная форма выбора, содержащая несколько колонок справочной таблицы и позволяющая выполнять контекстный поиск нужного значения по первым символам. При желании разработчик приложения может переопределить форму выбора, создав свою собственную форму, реализующую произвольный интерфейс выбора (например, иерархический выбор в виде дерева или нескольких взаимосвязанных списков). Форма выбора содержит специальный компонент - формальный параметр, который выступает в качестве источника данных для ее визуальных компонентов. При вызове этой формы для конкретного визуального компонента, вместо формального параметра подставляется тот компонент CReferenceGroup или CDict, с которым мы работаем в настоящий момент. Это позволяет использовать одну и ту же форму выбора многократно, если структура выбираемых справочных данных повторяется.

Приложения LAB могут работать не только с данными обычных типов, но и с большими двоичными объектами (LOB, CLOB, BLOB, LONG RAW и т.д.). Существует несколько возможностей:

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

Конкретные компоненты включают следующие реализации:

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

Компоненты для работы с РСУБД используют мощные возможности, такие как перетранслированные запросы, пакетное получение/изменение данных и исполнение хранимых процедур. Хранимые процедуры ЛИНТЕР могут возвращать открытый курсор, и соответствующий источник данных может использовать результат работы хранимой процедуры как обычную выборку, сформированную SELECT-запросом.

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

Средства для генерации отчетов

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

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

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

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

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

Компонент CReport поддерживает возможность группировки данных в отчете. Группой считается несколько идущих подряд строк с одинаковым значением поля данных, определяющего группу (поэтому отчеты с группировкой обычно строятся по запросам с ORDER BY). Каждая группа может иметь свои собственные области заголовка и конца, в которых можно выводить, например, сводную информацию о группах и промежуточных итогах по группе соответственно. Уровень вложенности групп не ограничен.

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

Специальный компонент - подотчет позволяет внедрить результаты формирования одного отчета внутрь другого, после чего продолжить печать последнего. Уровень вложенности подотчетов не ограничивается.

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

Например, на практике довольно часто требуется получить сводный отчет, в котором строки и столбцы содержат переменный набор параметров, а на пересечении строки и столбца выводится соответствующее этой паре параметров значение (т.н. "шахматка" или crosstab). Чтобы реализовать такой отчет, можно использовать три источника данных: два источника, выбирающих параметры для строк и колонок (к этим источникам привязан отчет) и третий источник, выбирающий соответствующие значения (зависимость от строки и колонки можно реализовать при помощи двух компонентов - связей) - к этому источнику привязываются визуальные компоненты для отображения собственно данных. Мастер связи с источником данных позволяет вставлять в отчет поля для расчета итогов не только по столбцам, но и по строкам.

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

Формирование отчета выполняется при помощи специальных методов компонента CReport. При этом существуют следующие возможности:

Объектно-ориентированный язык АТОЛЛ

Язык АТОЛЛ был создан как объектно-ориентированное расширение языка, используемого для разработки хранимых процедур и триггеров в СУБД ЛИНТЕР. Создание этого языка преследовало несколько целей: получить простой в освоении и реализации, и в месте с тем реализующий современные концепции объектно-ориентированной разработки язык для разработки прикладных систем в среде средства быстрой разработки приложений клиент-сервер; обеспечить переносимость разрабатываемых прикладных систем; снизить требования к ресурсам по сравнению с языком Java.

Основной единицей компиляции языка АТОЛЛ является класс. Класс может содержать переменные и методы - члены класса, имеющие различную область видимости. Каждый класс может быть унаследован от одного родительского класса. При этом методы дочернего класса могут полиморфно перекрывать методы родительского.

Одной из отличительных черт языка АТОЛЛ является организация распределения памяти под объекты. Все объекты в АТОЛЛ создаются динамически, при помощи операции create. Ссылка на созданный объект может сохраняться в одной или нескольких переменных. Объект может быть удален двумя способами: в результате исчезновения всех ссылок на объект (автоматическая сборка мусора) или явно, при помощи операции destroy. В последнем случае все оставшиеся ссылки на объект, если они были, получают значение NULL.

Никакие переменные, процедуры или функции в АТОЛЛ не могут существовать за пределами классов. Исполнение приложения на АТОЛЛ начинается с автоматического создания главного объекта приложения (имя класса которого задается извне виртуальной машины) и вызова у него метода main, через который передаются аргументы приложения.

Сами классы и методы могут содержать константы и переменные скалярных типов, массивы и ссылки на другие объекты. Как язык, ориентированный на поддержку RAD-системы, АТОЛЛ поддерживает в качестве скалярных типов целые и дробные числа, строки, перечисления, логический тип и дату-время. Для всех этих типов определены различные унарные и бинарные операции (например, можно конкатенировать строки или прибавить к дате определенное количество дней). Кроме того, переменная любого типа может содержать значение NULL.

Память под массивы в АТОЛЛ может выделяться статически или динамически. Каждый элемент массива может хранить данные определенного типа, включая ссылки на объекты и другие массивы.

Для реализации процедурной логики приложения каждый метод АТОЛЛ может содержать последовательно выполняющиеся операторы, ветвления (if, case), циклы (while, for). Для обработки ошибок предусмотрен механизм возбуждения и перехвата исключений.

Язык АТОЛЛ включает библиотеку стандартных функций, позволяющих выполнить разнообразные действия от преобразования значений различных типов и вычисления математических функций до динамического создания объекта по имени класса. Последняя функция позволяет приложению создавать классы, о которых ничего не известно на момент компиляции приложения, кроме одного из его базовых классов.

Такая функциональность возможна благодаря тому, что каждый класс АТОЛЛ компилируется в байт код, содержащий информацию о структуре объекта, идентификаторах переменных и методов и набор инструкций для исполнения каждого метода. Исполняющая подсистема способна выполнять этот байт-код на любой платформе. Полная переносимость достигается, в частности, благодаря хранению всех строк в формате UTF-8. Это позволяет корректно получить из байт-кода строки в нужной кодировке или в представлении Unicode.

При исполнении программы виртуальная машина АТОЛЛ ищет байт-коды классов в отдельных файлах, а также в архивах (библиотеках), содержащих байт-коды нескольких классов. Соответственно, среда разработки LAB позволяет создавать несколько библиотек классов в рамках одного проекта и использовать их в этом и других проектах.

Виртуальная машина АТОЛЛ включает развитые функции отладки, позволяющие:

Эти функции доступны, если приложение скомпилировано для отладки.

Поставка и эксплуатация готовых приложений LAB

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

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

Инсталляционный пакет для Windows представляет собой исполняемый exe-файл для установки приложения, а инсталляционный пакет для Unix - архив и командный файл, позволяющий его нужным образом распаковать. При установке создается другой исполняемый или командный файл, позволяющий легко запустить приложение (при условии, что установлена подсистема LABRT).

Возможности по расширению библиотеки компонентов

Стандартную библиотеку компонентов можно расширить двумя способами:

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

Второй способ позволяет расширить возможности LAB, реализовав на уровне внешних компонентов функциональность, которая не реализована в стандартных средствах LAB (например, использование сетевых протоколов).

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

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

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

Внешние компоненты LAB реализуются при помощи интерфейса, разработанного для языка C++. Пользовательский компонент описывается в виде класса C++, производного от одного из базовых классов библиотеки LAB и включающего декларацию и реализацию свойств, методов и событий. Для удобства используются специальные макроопределения. Один или несколько таких классов компилируются в динамически подключаемую библиотеку, из которой LAB извлекает описание компонентов в режиме "Add-In".

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

Направления развития LAB

Кроме планомерного наращивания функциональности компонентов, среды разработки и языка, LAB будет также развиваться по нескольким крупным направлениям: