Как стать автором
Обновить
70.65
lsFusion
Не очередной язык программирования

lsFusion 5, 6: больше асинхронности, агрегация / расширение / пользовательская настройка форм, новые представления

Время на прочтение11 мин
Количество просмотров2.6K


После выпуска первой публичной (третьей) версии платформы мы получили огромное количество фидбэка, большая часть работы над которым нашла отражение в недавно вышедшей четвертой версии платформы. Впрочем, значительная часть этого фидбэка осталась “за бортом”, но не была забыта, и соответственно сформировала план развития платформы на ближайшее будущее. Именно об этом плане и пойдет речь в этой статье.



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



Больше асинхронности


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


Асинхронный ввод объектных данных на форме


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


  1. Для опции INPUT в операторе DIALOG можно будет задать опцию ASYNC и свойство, значение которого необходимо показывать в выпадающем «контекстном списке» (это свойство также определяет тип вводимого значения).
  2. Также, как и для оператора INPUT, платформа определяет, что DIALOG можно выполнить асинхронно ( есть ровно один ввод, открываемая форма — это форма списка, существует единственная ветка вызова оператора и т.п.), после чего запрашивает у пользователя ввод значения прямо в поле, для которого срабатывает событие изменения. При этом при вводе значения пользователю показывается “контекстный список” возможных значений. Фильтром этого списка является фильтр открываемой формы (плюс фильтр по уже введенному значению), значение элементов списка определяется значением свойства, указанного в опции ASYNC.

Опция ASYNC также будет автоматически использоваться при создании обработок события изменений по умолчанию (таким образом в следующих версиях асинхронный ввод большинства свойств “включится” автоматически).


Асинхронный ввод объектных данных по сравнению с обычным вводом дает следующие преимущества:


  1. Лучшая производительность и время отклика, так как не надо открывать новую форму.
  2. Поддержка из коробки “живого” (устанавливаемого мгновенно) фильтра.
  3. Возможность начинать ввод не дожидаясь окончания полного обновления формы (так как сессии не многопоточны).
  4. Возможность кэшировать “контекстный список" на сервере приложений (если форма диалога открывается в новой сессии).

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


Асинхронное открытие форм


Технически асинхронный ввод значений на форме реализован следующим образом:


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

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


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

Такая “превентивность” позволяет значительно повысить отзывчивость пользовательского интерфейса и тем самым улучшить общий UX при работе с системой.


Асинхронное адаптивное обновление объектов / свойств


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


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


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


Агрегация (наследование) форм


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


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


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


Также при агрегации форм все создаваемые по умолчанию элементы формы (например контейнеры — OBJECTS, BOX, свойства — formOK, formClose, и т.д.), считаются “общими” и создаются только для результирующей формы. Соответственно, в агрегируемых формах обращения к таким «общим» элементам считаются обращениями к соответствующим элементам результирующей формы.


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

FORM suppliersWithIncomes
    OBJECTS s=Supplier
    AGGR i=incomes
    FILTERS supplier(i.i)=s
;

FORM extendedSuppliers
    AGGR Suppliers
    PROPERTIES (s) debt
;
run() {
    SHOW extendedSuppliers;
}

Расширение элементов на форме


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

EXTEND FORM suppliers
    EXTEND PROPERTIES BACKGROUND debt(s)>10
        name(s), number(s)
;
Особенно этот функционал может быть удобен при использовании вместе с механизмом агрегации форм, описанным в предыдущем разделе.

Пользовательская настройка форм


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


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


Добавление/ изменение свойств


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


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


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


Пример выражения:

supplier(sku(d))
GROUP SUM sum(InvoiceDetail id) IF invoice(id)=i
Предполагается, что в интерфейсах, где необходимо задавать выражения, будут отображаться также и имена объектов (чтобы было понятно к чему можно обращаться).

И сам конструктор, и интерфейсы добавления / изменения атрибутов свойств скорее всего будут реализованы при помощи встроенных механизмов lsFusion (то есть на языке lsFusion с использованием таких элементов платформы, как свойства и формы).


Пользовательские фильтры


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


  1. Диалог с пользовательскими фильтрами показывается в отдельном окне, что не очень удобно для пользователя. Также фильтры идут строго вертикально, что также неудобно в docked интерфейсе.
  2. Не разделены процессы создания и изменения значений пользовательских фильтров (из-за чего интерфейс в большинстве случаев существенно перегружен).
  3. Не существует процесса задания пользовательских фильтров разработчиком (в отличие от, например, порядков).

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


Сохранение глобальных настроек и форм


За исключением весьма редких случаев (например, оперативной “творческой” аналитики) сделанные пользователем настройки необходимо сохранять и восстанавливать при последующих использованиях настроенной формы этим или другими пользователями.


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

FORM reportSales 'Продажи'
;
FORM reportSuppliersSales 'Продажи по поставщикам''
    AGGR reportSales
    PIVOT ROW supplier(s);
;
FORM reportStockSales 'Продажи по складам'
    AGGR reportSales
    PIVOT ROW stock(s)
;

Работа с локальными (промежуточными) настройками формы


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


  1. Состояние можно “кодировать” и сохранять в URL. Тем самым пользователь может легко сохранять / передавать другим пользователям текущий вариант формы (то есть тот, который он видит на экране).
  2. Пользователь может легко переходить “вперед / назад” между вариантами формы, тем самым отменяя или заново повторяя сделанные изменения в настройках формы (например, это очень удобно при использовании функционала детализации в сводных таблицах).

Рефакторинг контейнеров


Исторически в lsFusion существует большое количество различных типов контейнеров, многие из которых пришли из Java Swing и на самом деле являются избыточными и / или недостаточно гибкими / частными случаями. Плюс эти типы контейнеров плохо отображаются на типы контейнеров HTML (веб-клиента, который в последних версиях lsFusion считается основным видом клиента), что делает их более сложными для понимания, а также в некоторых случаях ухудшает производительность веб-клиента.


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


  1. CONTAINER — вертикальный или горизонтальный контейнер. Направление будет определяться опцией direction. Этот тип контейнера по прежнему будет типом по умолчанию.
  2. TABBED — контейнер со вкладками. Здесь все останется как есть.
  3. TABLE — расположение в виде таблицы с выравниванием и по вертикали, и по горизонтали. Придет на смену атрибуту columns в CONTAINER контейнерах, где выравнивание было только по вертикали.

Соответственно типы контейнеров SPLIT и SCROLL превратятся в опции (true/ false) и скорее всего будут включены по умолчанию (у SPLIT отображение разделителя станет опциональным и будет выключено по умолчанию).


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


Также планируется реализовать несколько мелких изменений:


  1. Сворачиваемые контейнеры. Сворачиваемость будет опцией и, скорее всего, включена по умолчанию. Также будет поддерживаться оптимизация аналогичная TABBED контейнеру — если контейнер “свёрнут”, свойства, отображаемые в нем, даже не будут читаться.
  2. Избавление от двойных рамок. В текущей версии вокруг любого контейнера с заголовком рисуется специальная рамка, обозначающая содержимое этого контейнера. Однако если много контейнеров “вкладываются” друг в друга, местами образуется слишком много линий рядом друг с другом, что иногда сильно перегружает дизайн формы (съедает лишнее место). В следующих версиях планируется определять, что одна из рамок рисуется полностью вдоль другой рамки, и соответственно в таких случаях эта внутренняя линия рисоваться не будет.

Новые представления свойств


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


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


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


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


  • Расположению / управлению заголовками и видимостью контейнеров и представлений списков объектов / свойств.
  • Предоставлению и, что самое главное, обновлению данных, используемых в представлениях списков объектов / свойств (своего рода React только для обновления самого state).

Заключение


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


Теги:
Хабы:
Всего голосов 20: ↑20 и ↓0+20
Комментарии0

Публикации

Информация

Сайт
lsfusion.org
Дата регистрации
Дата основания
Численность
51–100 человек
Местоположение
Беларусь
Представитель
NitroJunkie