Русский
Русский
English
Статистика
Реклама

Блог компании lsfusion

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

12.01.2021 10:14:24 | Автор: admin


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



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



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


Одним из основных признаков современного эргономичного интерфейса является его асинхронность. В текущей версии платформы большинство пользовательских операций уже асинхронны (например, события, ввод примитивных данных). Но, как говорится, лучшее враг хорошего, и в следующих версиях планируется сделать асинхронным практически весь 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, и т.д.), считаются общими и создаются только для результирующей формы. Соответственно, в агрегируемых формах обращения к таким общим элементам считаются обращениями к соответствующим элементам результирующей формы.


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

FORMmySuppliers
OBJECTSs=Supplier
AGGRi=incomes
FILTERSsupplier(i.i)=s
;

FORMextendedSuppliers
AGGRSuppliers
PROPERTIES(s)debt
;
run(){
SHOWextendedSuppliers;
}

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


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

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

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


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


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


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


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


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


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


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

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

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


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


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


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

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


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


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


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

FORMreportSales'Продажи'
;
FORMreportSuppliersSales'Продажипопоставщикам''
AGGRreportSales
PIVOTROWsupplier(s);
;
FORMreportStockSales'Продажипоскладам'
AGGRreportSales
PIVOTROWstock(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).

Заключение


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


Подробнее..

Зачем нам понадобился еще один язык программирования

26.01.2021 10:19:42 | Автор: admin

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

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

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

Текущее положение дел

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

Для реализации этой задачи будем использовать, например, Java-stack технологий (хотя ничего принципиально не изменится, если это будет тот же Python). Посмотрим, знание каких языков нам для этого понадобится :

  • Java. Основной язык, на котором будет реализовано большинство логики приложения.

  • XML. Мало кто считает его языком, тем не менее, даже с точки зрения названия (Extensible Markup Language) он им является. Хотя конечно же, это не язык программирования, а язык разметки. Нам он так или иначе понадобится, поскольку именно его используют для конфигурирования множество библиотек (например, Spring, log4j или тот же Apache Tomcat). Кроме того, при разработке фронтенда придется использовать HTML, который, можно сказать, является разновидностью XML.

  • SQL. Теоретически можно обойтись без него, и использовать какую-нибудь ORM технологию (например, Hibernate). Однако, при обработке хоть сколько-нибудь большого объема информации все равно придется переходить или на плоский SQL, или на псевдо-SQL (вроде HQL).

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

  • CSS. Тоже язык разметки со своим специфическим синтаксисом (хоть и довольно простым).

Проблемы

Каждый из этих языков имеет свой отличительный синтаксис, кардинально отличающийся от остальных. Разве что JavaScript похож на Java, но если мы возьмем более модный Python, то будет еще один совершенно новый синтаксис.

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

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

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

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

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

Решение

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

Во-первых, это будет проще для изучения новичку.

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

В-третьих, языки всегда описывают некоторую архитектуру. Платформа имеет декларативную функциональную логику, и существующие императивные языки не очень хорошо подходят для ее описания.

Приняв решение о том, что для решения такой проблемы без собственного языка никак не обойтись, нужно было решить какой синтаксис из уже имеющихся взять за основу. Вариантов по большому счету было два : C-ишный синтаксис, который используется в Java/JavaScript (построенный на специальных символах), или SQL-подобный синтаксис (построенный на ключевых словах).

Мы выбрали второй вариант, так как одной из целей была простота языка, а SQL изначально создавался для бизнес-пользователей, а не разработчиков. Кроме того, SQL, как и lsFusion, описывает декларативную логику, а не императивную, как Java и другие универсальные языки. Еще одним фактором такого решения стало то, что мы хотели встроить в язык достаточно большое количество возможностей, и нужно было много ключевых слов для этого. Сложное сочетание спецсимволов и ключевых слов могло быть не очень интуитивно понятно. Стоит отметить, что похожий синтаксис использовался в ранее популярном языке для работы с данными и бизнес-приложениями FoxPro.

Выбрав решение с ключевыми словами, нужно было еще определиться ,в каком регистре они должны быть. Для SQL на эту тему ведется много баталий. Для первоначальной реализации мы все-таки выбрали схему с большими буквами для ключевых слов, чтобы отделять их от идентификаторов при работе без IDE. Именно такая схема была в первоначальной логике SQL и того же FoxPro, и лишь потом начали практиковаться разные виды регистров. В следующих версиях lsFusion мы также планируем разрешить использовать разный регистр букв для ключевых слов.

Дальше было лишь делом техники реализовать свой язык. Для этого мы взяли ANTLR для разбора языка, а также реализовали плагин для IntelliJ IDEA. Как именно это было сделано, мы возможно расскажем в будущих статьях.

Язык lsFusion получился достаточно похожим на SQL, с той лишь поправкой, что SQL описывает таблицы и запросы, а lsFusion - функциональную логику. Пример того, как логика, описанная в SQL, соответствует такой же логике в lsFusion описана в статье Функциональная СУБД. Примеры остального синтаксиса можно увидеть вот здесь : императивная логика, GUI. Более подробное описание языка можно найти в одних из первых трех статей блога (1, 2, 3).

Надеюсь, что у читателя статьи создалось представление, почему мы решили использовать свой собственный язык, а не создавать очередной Java/Python/Ruby-framework.

Подробнее..

Почему lsFusion, а не 1С?

02.03.2021 10:09:04 | Автор: admin


Предыдущая статья Почему не 1С? вышла больше года назад и вызвала достаточно живой интерес (совсем немного не дотянула до 100к просмотров и 2к комментариев). Впрочем, как и ожидалось, у многих возник резонный вопрос: Если не он, то кто? Безусловно, как многие поняли, та статья писалась не просто так, а чтобы вслед за ней выпустить еще одну статью, где было бы рассказано, как описанные в первой статье проблемы можно и нужно решать. Однако, по различным причинам, выпуск этой ответной статьи был отложен на весьма долгое время. Но, как говорится, лучше поздно, чем никогда.


Как было отмечено в заключении предыдущей статьи, в качестве решения всех описанных в предыдущей статье проблем предлагается использовать платформу (и одноименный язык) lsFusion. Эта платформа имеет в основе несколько достаточно редких, но при этом наиболее высокодекларативных парадигм программирования: комбинаторное (function-level, не путать с functional), реактивное, событийно-ориентированное, программирование на ограничениях (constraint) и метапрограммирование. Впрочем, для неискушенного читателя это все не более чем набор красивых buzzwords, поэтому не будем уделять много внимания теории, а сразу перейдем на более практический уровень, а именно к решению описанных в предыдущей статье проблем.


Структура этой статьи полностью повторяет структуру статьи Почему не 1С? (с теми же названиями разделов и в том же порядке):


Оглавление


При этом в каждом разделе, с названием проблемы в 1С, рассказывается как данная проблема решается в lsFusion.


Объекты: Справочники, Документы и т.д.


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


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

Неэффективное получение данных объектов


Так как для выполнения логики вычислений lsFusion пытается максимально использовать SQL-сервер, а не сервер приложений (причем делает это максимально группируя запросы, чтобы выполнять их как можно меньше), операции чтения объекта целиком в lsFusion не существует в принципе. Как следствие, и проблема N+1 и проблема избыточного чтения в lsFusion возникают крайне редко. Например следующее действие:

fillSum(Invoicei){
FORinvoice(InvoiceDetailid)=iDO
sum(id)<-price(id)*quantity(id);
}
Скомпилируется в одно действие:
fillSum(Invoicei){
sum(InvoiceDetailid)<-price(id)*quantity(id)WHEREinvoice(id)=i
}
Которое, в свою очередь, выполнится одним запросом, в котором будут читаться / писаться только используемые ряды / колонки.

Таблицы / Представления: Регистры


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


  • Таблицы первичные свойства
  • Представления свойства, реализуемые при помощи остальных операторов (впрочем, материализованные свойства можно также рассматривать и как таблицы)
  • Работа с моментами / периодами времени частный случай представлений, свойства, реализуемые при помощи операторов группировки:
    • СрезПоследних GROUP LAST
    • Остатки, Обороты SUM (ОстаткиИОбороты в lsFusion не имеют смысла, так как оптимизатор lsFusion умеет сам объединять подзапросы, если это необходимо)

На тему работы с регистрами в lsFusion была отдельная статья, поэтому подробно останавливаться на этой теме здесь особого смысла нет.


Единственное, что еще хотелось бы отметить. Возможно в lsFusion все же имеет смысл добавить синтаксический сахар по созданию всего этого комбайна из класса регистра, агрегации, а также набора готовых свойств остатков и оборотов. Что-то вроде:

LEDGERSalesGROUPStockstock,SkuskuSUMNUMERICquantity,NUMERICsum;

//автоматическисоздаетклассSalesисвойства:
//stock,sku,quantity,sum=ABSTRACTStock,Sku,NUMERIC,NUMERIC(Sales);-
соответствующиеизмерения/ресурсы
//quantitySales,sumSales(stock,sku)-текущийостаток(имя=имясвойства+имярегистра)
//quantitySales,sumSales(stock,sku,DATETIME)-текущийостатокнадату
//quantitySales,sumSales(stock,sku,DATETIME,DATETIME)-оборотысдатыподату
//ит.п.
И в следующих версиях такой синтаксический сахар скорее всего появится. Другое дело, что чаще всего в сложных проектах регистры имеют более сложную структуру (например, наследуются друг от друга, денормализуют данные для составных индексов, расширяются в разных модулях и так далее), поэтому такой сахар может быть важен разве что для RAD разработки (а точнее прототипирования), которая в современном IT-мире уже не так актуальна.

Регистры поддерживаются в очень частных случаях


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


В отличие от 1С, в lsFusion поддерживается материализация не только суммы и последних по дате значений, но и практически любых вычисляемых данных. Так, в lsFusion можно материализовать:


  1. Композицию, что, например, позволяет прозрачно денормализовывать данные из разных таблиц (это будет показано в разделе "Статичная физическая модель").
  2. Максимумы / минимумы / последние значения по любому полю, что позволяет эффективно организовывать нумерацию и ранжирование данных.
  3. Рекурсию, что, например, позволяет разворачивать иерархию в плоские таблицы (с такой же высокой производительностью).
  4. Выбор (полиморфизм), что позволяет наследовать регистры друг от друга.
  5. И многие другие

Отсутствие ограничений и событий для значений регистров


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

CONSTRAINTcurrentBalance(sku,stock)<0MESSAGE'Остатокнеможетбытьотрицательным';
Соответственно, платформа будет сама максимально эффективно (инкрементальными вычислениями) проверять, что никакое изменение (например, изменение склада прихода или количества расхода), это ограничение не нарушит.

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

WHENSET(currentBalance(Skusku,Stockstock)<0)//когдаостатокстановитсяменьше0
EMAILSUBJECT'Остатокнаскладе'+address(stock)+'длятовара'+name(sku)+
'сталменьше0'TOresponsibleEmail(group(sku));

В параметрах виртуальных таблиц можно использовать только константы


Опять-таки никаких ограничений на использование параметров в lsFusion нет. Так, если надо обратиться к остатку на дату, можно в качестве даты использовать любые, в том числе вычисляемые, значения. Кроме того, не надо думать, о том чтобы проталкивать условия внешнего контекста внутрь вычисления, lsFusion все это делает автоматически. Так если у нас есть следующее действие:

EXPORTFROMprice(Skusku),balance(date(sku),sku)WHEREname(sku)='Колбаса';
Платформа автоматически протолкнет условие ограничивающее наименование (и как следствие даты, на которые будет вычисляться остаток) внутрь подзапроса (и всех подзапросов внутри этого подзапроса), таким образом выполнив оптимизацию predicate push down . Причем в отличии от того же SQL, платформа умеет выполнять эту оптимизацию не только для группировок, но и для разбиений и даже для рекурсий. Впрочем это тема для отдельной статьи, подробно на ней здесь останавливаться не будем.

Запросы


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


Запросы в строках


И логика свойств и логика форм задаются непосредственно на языке lsFusion, соответственно для них:


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

Тут конечно иногда возникают вопросы с динамическими формируемыми запросами, но как правило они решаются использованием либо соответствующих условных операторов / опций (IF, SHOWIF и т.п.), либо оператора выполнения программного кода (EVAL), позволяющего выполнить любую заданную строку кода на lsFusion.


Отсутствие оптимизатора запросов


В lsFusion внутри очень мощный механизм оптимизации запросов, во многих случаях выполняющий оптимизации, которые не умеют выполнять даже дорогие коммерческие СУБД (не говоря уже о PostgreSQL). Так, все проблемы с производительностью описанные в статье Почему не SQL, lsFusion умеет решать самостоятельно без каких-либо дополнительных действий со стороны разработчика, который, соответственно, может сконцентрироваться на решении бизнес-задач, а не думать как правильно написать запрос и / или в какую временную таблицу положить его результат.


Так пример из статьи про 1С в lsFusion будет выглядеть следующим образом:


Пример из статьи
ВБРАТЬ    РасходнаяНакладнаяСостав.Номенклатура,    УчетНоменклатурыОстатки.КоличествоОстатокИЗ    Документ.РасходнаяНакладная.Состав КАК РасходнаяНакладнаяСостав        ЛЕВОЕ СОЕДИНЕНИЕ РегистрНакопления.УчетНоменклатуры.Остатки(,                             Номенклатура В (                                   ВБРАТЬ Номенклатура                                   ИЗ Документ.РасходнаяНакладная.Состав                                   ГДЕ Ссылка = &Документ)) КАК УчетНоменклатурыОстатки        ПО УчетНоменклатурыОстатки.Номенклатура = РасходнаяНакладнаяСостав.НоменклатураГДЕ    РасходнаяНакладнаяСостав.Ссылка = &Документ И    (УчетНоменклатурыОстатки.КоличествоОстаток < РасходнаяНакладнаяСостав.Количество ИЛИ        УчетНоменклатурыОстатки.КоличествоОстаток ЕСТЬ NULL)
currentBalance(InvoiceDetailid)=currentBalance(sku(id));

export(Invoicei){
EXPORTFROMsku(InvoiceDetailid),currentBalance(id)WHEREinvoice(id)=iAND
currentBalance(id)<quantity(id)ORNOTcurrentBalance(id);
}
Соответственно никаких Номенклатура В ( ВБРАТЬ Номенклатура ИЗ Документ.РасходнаяНакладная.Состав ГДЕ Ссылка = &Документ) в lsFusion писать не надо.

Отсутствие расширенных SQL возможностей


Кроме классического набора операций в SQL-92, состоящего из группировок и композиций (аналог в SQL соединения), в lsFusion также поддерживаются операции:


  • Разбиение / упорядочивание (аналог в SQL оконные функции)
  • Рекурсия (аналог в SQL рекурсивные CTE)
  • Полиморфизм (косвенный аналог в SQL наследование таблиц)

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


Отсутствие запросов на изменение


Большинство ERP-платформ хотя формально и поддерживают ORM механизмы, но на практике, из-за плохой производительности, решения на ERP-платформах все равно в абсолютном большинстве случаев используют запросы на SQL-подобных языках.


Впрочем, в том же 1С запросы поддерживаются только для операций чтения данных, для записи все-таки приходится использовать ORM механизмы, производительность которых оставляет желать лучшего. В lsFusion такой проблемы нет, и все операции, в том числе создание объектов, могут выполняться на сервере БД, причем одним запросом. Например:

generateCards(){
FORiterate(i,1,10000)NEWd=DiscountCardDO
number(d)Card:+i;
}

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

Тоже самое касается и механизма изменения / удаления большого количества данных / объектов:

FORsum(DiscountCardd)>10000DO
vip(d)TRUE;
FORsum(DiscountCardd)>10000DO
DELETEd;
Скомпилируется в:
sum(DiscountCardd)TRUEWHEREsum(d)>10000;
DELETEDiscountCarddWHEREsum(d)>10000;
И опять-таки выполнится одним запросом.

Отказ от автоматических блокировок


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


  1. Использовать версионные СУБД (или версионный режим в том же MS SQL).
  2. Повысить уровень изоляции базы до Repeatable Read или еще лучше до Serializable.
  3. Материализовать данные, для которых важна целостность.
  4. Все транзакции с конфликтами записей или дедлоками откатывать и повторять заново.

Именно этот способ решения проблемы используется в lsFusion. Правда, в отличие от того же 1С (как и остальных платформ) в lsFusion:


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

Формы


В lsFusion формы универсальный механизм, отвечающий за объединение данных вместе и вывод их пользователю / ИС в том или ином виде.


Отказ от единого потока выполнения: разделение логики на сервер и клиент


В отличие от 1С в lsFusion поток выполнения един и для сервера, и для клиента. Такое единство значительно упрощает взаимодействие с пользователем / клиентским устройством с точки зрения процесса разработки. Так, пример в статье про 1С написан именно на языке lsFusion, и, соответственно, выглядит следующим образом:

f()<-someData();//читаемданныеизбазынеобходимыедляmyForm
DIALOGmyFormOBJECTSaINPUTDO//ОткрытьФормуМодально,пользователь
выбираеткакой-тообъект
IFisSomething(a)DO//читаемданныедляэтогообъектаиеслиснимичто-то
нето
DIALOGotherFormOBJECTSb=aDO{//ОткрытьФормуМодально,открываем
другуюформугдепользовательвыбираетдругойобъектb
g(b)<-someInput(b);//записываемданныедляb
APPLY;//сохраняемизменениявбазу
}
В какой-то степени lsFusion использует подход обычных форм в 1С, только делает это гораздо более масштабируемо и производительно. Фактически, вся магия асинхронности остается под капотом, а разработчик может сконцентрироваться строго на решении бизнес-задач, а не думать о том, где и как должен выполнять написанный им код.

Тут может возникнуть впечатление, что в lsFusion вообще не существует возможности выполнять заданный код на клиенте (в смысле кроме уже встроенных в платформу операторов/действий). Но это не так, в lsFusion существует специальная опция CLIENT в операторе INTERNAL, которая позволяет выполнить заданный именно на клиенте код. Для десктоп клиента этот код задается на Java, а для веб-клиента на JavaScript. Правда обычно такая тонкая настройка нужна очень редко, поэтому подробно останавливаться на ней здесь особого смысла нет.


Отказ от синхронности


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


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


Отказ от WYSIWYG: разделение интерфейса на запись и чтение


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


  • Из-за отсутствия оптимизатора, в динамических списках крайне противопоказано использовать подзапросы / виртуальные таблицы (представления).
  • Динамические списки нельзя редактировать.

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


Невозможность обращаться в списках к реквизитам форм / текущим значениям других списков


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

FORMbalance
OBJECTSst=Stock,sk=Sku
PROPERTIES(st)name
PROPERTIESname(sk),currentBalance(st,sk)
FILTERScurrentBalance(st,sk)
;
При перемещении текущей записи в верхнем списке (складов), нижний список (товары, которые есть на выбранном складе) будет обновляться автоматически.

Избыточные уровни абстракции


Основным принципом при создании lsFusion был и остается принцип чистота и завершенность всех создаваемых абстракций. Так:


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


Как следствие, количество абстракций в lsFusion значительно меньше чем в 1С. Соответственно взглянем на абстракции 1С из предыдущей статьи глазами lsFusion:


  • Объекты / записи

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


  • Объекты / ссылки на объекты

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


  • Данные формы / Данные объектов

В lsFusion поддерживается практически абсолютная реактивность на всех уровнях, в том числе на уровне форм. Соответственно необходимости в каких-то дополнительных абстракциях вроде данных формы в lsFusion попросту нет. Есть просто данные, и соответственно при любом их изменение платформа автоматически обновляет все представления их использующие. Если же форме нужны какие-то свои локальные данные, разработчик просто создает необходимые локальные первичные свойства, и работает с ними также как и со всеми остальными свойствами (например хранящимися в базе). То есть никаких крышесносящих РеквизитФормыВЗначение в lsFusion нет.


  • Запросы / СКД / Аналитика (BI)

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


  • Печатные формы печатное представление формы, дизайн которого задается при помощи JasperReports, одной из самых распространенных систем отчетности под Java. Позволяет строить pixel-perfect формы, и вообще обладает огромным количеством различных возможностей.
  • Встроенная аналитика одно из представлений списка объектов формы, поддерживает графики, диаграммы, сводные таблицы и многое другое.
  • Сложные интерактивные формы с вычисляемыми данными обычное интерактивное представление формы позволяет отображать как первичные, так и вычисляемые данные, а также создавать сразу много списков объектов и связывать их друг с другом одной строкой кода (в разделе выше был пример).
  • Программный интерфейс работы с данными структурированное представление формы, позволяет экспортировать (и наоборот импортировать) любую форму в JSON, XML, XLSX, DBF и другие распространенные форматы.

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


Закрытая физическая модель


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


Открытая и прозрачная физическая модель дает массу преимуществ:


  1. Простая и очень производительная интеграция со сторонними инструментами (например BI).
  2. Возможность использования стандартных средств администрирования БД (например, профайлеров)
  3. Читабельные запросы в журналах и логах.

Статичная физическая модель


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


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

date=DATADATE(DocumentDetail)
barcode=DATASTRING(Sku);
sku=DATASku(DocumentDetail);

barcode(DocumentDetaildd)=barcode(sku(dd));
count(STRINGbc,DATEd)=GROUPSUM1IFdate(DocumentDetaildd)>dANDbarcode(dd)=bc;
FORMx
OBJECTSbc=STRINGPANEL,d=DATEPANEL
PROPERTIEScount(bc,d),VALUE(bc),VALUE(d)
;
При выполнении этой формы сформируется запрос в котором будет:
  1. JOIN с таблицей товаров, штрихкод в таблице SKU совпадает с заданным;
  2. подсчет количества строк документов по всем датам больше заданной.

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

barcode(DocumentDetaildd)=barcode(sku(d))MATERIALIZED;//помечает,что
должнобытьхранимое
INDEXbarcode(DocumentDetaildd),date(dd);//строимсоставнойиндекс
После такой оптимизации SQL сервер сможет начать использовать построенный составной индекс и производительность будет максимальной.

Закрытые исходники и лицензии


Открытые исходники и лицензия в последнее время стали де-факто стандартом в отрасли средств разработки. Даже Microsoft, известная ранее консервативностью в этом вопросе, открыла исходники .Net, сделала его бесплатным и выпустила версию под Linux.


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


lsFusion выпускается под LGPL v3 лицензией, которая подразумевает свободное использование, распространение и модификацию (за исключением выпуска коммерческой версии платформы), в общем практически все что угодно. Исходники доступны на GitHub. Это обычный Maven-проект, соответственно поддерживаются все стандартные циклы сборки Maven: compile, install, package и т.п. Также открыты исходники сервера сборки, плагина, управление проектами ведётся в GitHub Projects. То есть вся инфраструктура открыта настолько, насколько это возможно.


Отсутствие наследования и полиморфизма


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


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


Про то в каком именно виде в lsFusion поддерживаются наследование и полиморфизм уже неоднократно рассказывалось на хабре, как в формате tutorial, так и на конкретных примерах, поэтому повторяться тут не будем.


Отсутствие явной типизации в коде


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


Также стоит отметить, что в некоторых правилах класс параметра может не задаваться явно, но при этом он автоматически выводится из семантики правила, и дальше все работает, точно также, как если бы этот класс параметра задавался явно. Например:

invoice(InvoiceDetailid)=DATAInvoice;
sum=GROUPSUMsum(InvoiceDetailid)BYinvoice(id)//уsumсчитаетсяестьодин
параметрклассаInvoice(путемвыводаклассазначенияinvoce,вданномслучае-Invoice)

FORMmyForm
OBJECTSmyObject=MyClass
;
filtered=FILTERmyForm.myObject;//уfilteredсчитаетсяестьодинпараметркласса
MyClass(выводитсяизклассаобъектаmyObjectформыmyForm)

Отсутствие модульности


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


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


  1. События предметной области (и все то, что на них построено ограничения и агрегации) позволяют разбить всю бизнес-логику на множество небольших напрямую независимых друг от друга правил. Эти правила, в свою очередь, автоматически выстраиваются платформой в один большой поток выполнения, в зависимости от того, какие данные эти правила изменяют / используют.
  2. Расширения позволяют расширять практически все существующие в платформе абстракции. Такая возможность опять-таки позволяет максимально декомпозировать любую сложную бизнес-логику (например, сложные формы).
  3. Множественные наследование и полиморфизм дают все преимущества ООП, основным из которых является все та же декомпозиция (а значит и модульность). Отметим, что полиморфизм в какой-то степени являются частным случаям расширений (то есть они расширяют существующее абстрактное свойство / действие, добавлением к нему новых реализаций).
  4. Отказ от инкапсуляции и акцент на данных, а не объектах (это уже упоминалось в самом первом разделе). Впрочем, тут конечно важно не отсутствие синтаксического сахара в виде this, а то, что классы в lsFusion получаются по сути открытыми, то есть опять-таки расширяемыми.
  5. Метапрограммирование позволяет осуществлять шаблонизацию кода, тем самым значительно уменьшая его дублирование, а значит опять-таки (пусть и косвенно) повышая модульность создаваемых решений

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


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


Ставка на визуальное программирование


В предыдущей статье были подробно расписаны все недостатки ВП, и скорее всего, именно поэтому подход Everything as code стал золотым стандартом в мире современной разработки. Именно такой подход используется и в lsFusion.


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


Фатальный недостаток


Вообще, проблема переписывания всего, что только можно, это проблема не только 1С, но и многих других ERP-платформ. Обусловлено это, видимо, историческим наследием, и имеет как минимум две проблемы:


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

В lsFusion используется другой подход: если можно использовать что-то готовое, лучше использовать что-то готовое. В крайнем случае использовать что-то с максимально высоким уровнем абстрагирования и сверху достроить то, чего не хватает.


Итак, что и где используется в lsFusion:
  1. Язык. Тут мы получаем больше всего вопросов в стиле почему мы не используем какой-нибудь уже существующий язык. На самом деле мы изначально и пытались использовать Java для задания логики приложения. Но со временем стало очевидно, что в отличие от того же 1С, язык lsFusion фундаментально отличается от всех существующих языков. Он гораздо более декларативный и высокоуровневый, сочетает в себе и логику запросов, и логику процедур, и даже логику представлений. Соответственно преимущества от поддержки своего языка явно начали перевешивать риски того, что на начальном этапе многие разработчики негативно относятся к любым новым языкам. В итоге мы все же решились на свой язык. И на мой взгляд, приняли правильное решение.


    Но естественно, поддержка языка lsFusion делалась не с нуля для создания серверных парсера и лексера в lsFusion используется ANTLR, для того же самого в IDEA используется Grammar-Kit (парсер), JFlex (лексер).

  2. UI. Для реализации десктоп-клиента используется Java SE (Swing, Web Start), что позволило получить поддержку сразу всех ОС, а также обновление и установку клиентского приложения прямо из коробки. Впрочем, как уже говорилось в одной из предыдущих статей, основным клиентом в текущей и следующих версиях будет веб-клиент, поэтому подробно на особенностях реализации десктоп-клиента останавливаться не будем.


    Для реализации веб-клиента в lsFusion используется:

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


      Тут многие могут заметить, что GWT уже полумертв, и сейчас использование того же TypeScript было бы логично. Но:


      а) при начале разработки веб-клиента TypeScript ещё только-только появился;


      б) разработчик на lsFusion напрямую с GWT не сталкивается, поэтому его наличие в структуре ни на что не влияет, и при необходимости клиентскую часть всегда можно перевести на любую другую технологию.


      Но когда-нибудь миграция на TypeScript, я думаю, все же случится.

    • Full Calendar, Leaflet используются для поддержки нестандартных представлений списков (календаря и карты).
    • Spring Security, MVC, DI используются для задач аутентификации, управления сессиями, а также инициализации серверов (веб, приложений).
  3. BI для задач внутренней аналитики в lsFusion используется представление сводная таблица. Для реализации этого представления используются:

    • pivot-table, subtotal для пользовательской настройки BI, отрисовки таблиц (в том числе с подитогами),
    • plotly для отрисовки графиков и диаграмм,
    • tableToExcel для выгрузки сводных таблиц в Excel (с сохранением форматирования, collapsible рядов и т.п.).

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

  4. Печатные формы. Для работы с печатными формами в lsFusion используется одна из самых популярных технологий в этой области JasperReports.


    Тут стоит отметить вот какую особенность. В 1С по непонятным причинам технология работы с печатными формами объединена с инструментами аналитики, что, на мой взгляд, достаточно странно, так как:


    а) если группировки и колонки постоянно изменяются, дизайн по определению является динамичным и, скажем, уместить его в А4 или просто сделать красивым весьма непросто;


    б) аналитические инструменты требуют определенную ячеистость, что с другой стороны усложняет построение pixel-perfect печатных форм.


    В lsFusion используется другой подход: инструменты аналитики объединены с обычными таблицами (используют те же rendererы, стили, события и т. п.), а печатные формы являются отдельным механизмом. Соответственно BI обладает интерактивностью обычных таблиц (переход по ссылке, детализация и т. п.), а печатные формы используются в основном для печати документов и периодичной отчетности (с минимальной кастомизацией).

  5. IDE. Когда мы начинали разработку плагина для IDE, IDEA ещё не была настолько популярна (Eclipse был существенно популярнее), поэтому выбирая IDEA мы изрядно рисковали. Ирония, но несмотря на меньшее сообщество, найти материал по разработке своего языка под IDEA оказалось проще, да и ее архитектура выглядела существенно более продуманно. Сейчас IDEA (а точнее IntelliJ Platform) практически без сомнения лидер на рынке IDE, обладает огромным количеством возможностей, практически все из которых поддерживаются при работе с lsFusion (либо из коробки, либо благодаря реализации необходимых доработок в lsFusion плагине). Плюс stub indexы, chameleon element'ы и многое другое позволяет обеспечить высокую производительность практически на любых объемах lsFusion кода (скажем, у меня в агрегированном проекте десятки проектов достаточно высокой сложности с сотнями тысяч строк кода, и все работает очень быстро).
  6. Система контроля версий. Everything as code позволяет использовать любую из существующих систем контроля версий, самой популярной из которых, безусловно, является Git. Впрочем, на некоторых проектах с непрерывной поставкой без крупных функциональных веток можно спокойно использовать тот же Subversion (что, например, мы и делаем на некоторых проектах).
  7. Система управления зависимости / сборки. Опять таки EaC позволяет использовать существующие системы управления зависимости / сборки в Java, наиболее распространенной из которых является Maven (так центральный репозиторий для lsFusion поддерживается на repo.lsfusion.org).


    Чтобы подключить сервер в Maven-проект достаточно в pom.xml добавить следующие строки:


    <repositories>        <repository>            <id>lsfusion</id>            <name>lsFusion Public Repository</name>            <url>http://repo.lsfusion.org</url>        </repository></repositories>
    

    Что еще важнее, через Maven очень легко подключать сторонние серверные Java библиотеки. Например, если нам надо решить СЛАУ, просто находим соответствующую библиотеку в центральном Maven репозитории, добавляем в pom.xml.


    <dependency>        <groupId>org.apache.commons</groupId>        <artifactId>commons-math3</artifactId>        <version>3.2</version></dependency>
    

    И эту зависимость автоматически подключат и IDE, и сервера сборки.

  8. Сервера приложений и БД. Для работы с серверами БД используется JDBC, при этом все проблемы с производительностью / соответствием спецификации решаются именно родными средствами СУБД. То есть никаких пропатченных версий Postgres не требуется (которых может не быть в центральных репозиториях Docker, yum и т.п.)


    Также сервер приложений использует несколько компонент Java Spring, что значительно упростило реализацию процессов инициализации и настройки сервера приложений и сделало эти процессы более стандартизированными.



Неуважительные по отношению к разработчикам лицензирование и брендирование


Как уже упоминалось выше, lsFusion распространяется под лицензией LGPL v3.0, которая позволяет все что угодно, кроме, разве что, создания коммерческой версии lsFusion и ее дальнейшей продажи. Соответственно, для разработчика платформа lsFusion не более чем инструмент для решения его задач, а не манна небесная, на которую он должен молиться и с которой его должны ассоциировать. Как следствие, основной ценностью в экосистеме lsFusion является не платформа как таковая, а решения на этой платформе, и что, возможно даже более важно, компетенции людей / компаний их дорабатывающих, внедряющих и поддерживающих. Почему именно такие акценты актуальны в современном ИТ-мире? Дело в том, что большинство бизнесов сейчас уже как-то автоматизировано, и, соответственно, основной вопрос заключается как раз в качестве этой автоматизации ее глубине, гибкости и соответствии существующим бизнес-процессам. А обеспечение всех этих требований требует как хорошо спроектированных модульных специализированных решений, так и умение быстро и качественно дорабатывать эти решения прямо на лету (так как, как правило, в крупных проектах внедрение сначала идет as is, а только потом to be). Соответственно грести все компании, использующие платформу, под одну гребенку, превращая их во франчей, в конечном итоге, не выгодно никому:


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

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


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


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


Заключение


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


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

Ну и наконец, хотелось отметить, что это ещё не все. В процессе подготовки и обсуждения первой статьи выяснилось ещё как минимум несколько важных пунктов, где lsFusion если не лучше, то уж точно сильно отличается от 1С и других существующих на рынке ERP-платформ.


Так, среди таких пунктов можно вспомнить:

Существенный оверхед при работе с большими объектами (например документами)


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


Ограниченность пользовательских настроек


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


Невозможность одновременной работы с объектами (по аналогии например с Google docs)


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


Неудобная работа с динамическим количеством колонок


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


Отсутствие мгновенного контроля ссылочной целостности при удалении


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


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

Неочевидные / неэргономичные интерфейсы для выполнения многих базовых действий


Например:


  • Настройка группировок настройка через списки, вместо интуитивных drag-drop интерфейсов.
  • Групповое изменение данных вообще не WYSIWYG операция, а находится где-то в администрировании (часть БСП как я понял).
  • Фильтрация если скажем необходимо отфильтровать все записи с текущим полем > заданного значения (закопана в Еще -> Настроить список, где необходимо найти нужную колонку и сделать еще несколько нажатий).
  • Подсчет количества записей, суммы по колонке честно говоря так и не нашел где это делается (но может просто плохо искал)

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


Невозможность прозрачной подмены представлений списков / свойств


Прозрачно заменить представление в 1С не может:


  • ни пользователь например, просто нажав соответствующую кнопку (как, например, в Odoo или lsFusion)
  • ни даже разработчик декларативно выбрав для отображения данных другой renderer, отличный от таблицы / поля, например, карту, спидометр или вообще любую js-функцию (причем так, чтобы обновлением данных продолжала заниматься сама платформа).

Ограниченность ряда абстракций (которые являются частными случаями)


Например, если необходимо:


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

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



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


Подробнее..

MyCompany бесплатное и открытое решение для небольшого бизнеса

09.02.2021 10:17:03 | Автор: admin


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

По этой причине мы решили создать базовое решение с названием MyCompany, которое реализует основные бизнес-процессы малого бизнеса. Оно полностью бесплатно, выпускается под Apache лицензией, и ее исходники находятся на Github. Решение легко устанавливается и поддерживает российское законодательство.

В качестве системы управления базой данных используется PostgreSQL. На сервере решение устанавливается и запускается как Java приложение, состоящее из сервера приложений и веб-приложения под управлением Apache Tomcat. В качестве GUI может использоваться как веб-интерфейс, так и десктоп-клиент, запускающийся через Java Web Start.

Функционал


Демо-версию с заполненными данными можно посмотреть по адресу https://demo.lsfusion.org/mycompany-ru. Авторизация по указанной ссылке отключена.

image

В качестве основы была взята логика, заложенная в известном в мире решении Odoo. К сожалению, далеко не все подходы, реализованные в нем, хорошо подходят для использования в российских реалиях. Поэтому часть процессов пришлось изменить в соответствии с собственным опытом и другими популярными приложениями. Несмотря на это, логика MyCompany гораздо ближе к мировым стандартам, чем к логике 1С. Также в ней имеется локализация на английский язык (с возможностью добавления любого другого языка).

На данный момент в решении отсутствует реализация регламентной отчетности (бухгалтерского учета) и расчета заработной платы. В этой нише на территории РФ исторически сильны позиции решений на платформе 1С, а бухгалтера это очень консервативные пользователи. По этой причине на первом этапе предполагается выгрузка необходимых данных в систему бухгалтерского учета, а непосредственно решение используется для ведения управленческого учета.

MyCompany имеет модульную архитектуру и состоит из семи крупных блоков:

image

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

Справочники (Master Data)


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

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

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

Есть возможность автоматически загружать данные юридических лиц через API, предоставляемый DaData.

Склад (Inventory)


В этом блоке реализована логика складского учета с расчетом остатков по местам хранения. Места хранения могут иметь иерархическую структуру. Сотрудникам компании можно предоставлять доступ только к отдельным местам хранения.

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

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

Поддерживаются четыре основных вида документов :

  • Приемка. Регистрирует приемку товара на склад. Поддерживает логику ожидаемого и принятого количества, а также статусы процесса приемки и размещения.
  • Отгрузка. Отражает расход со склада и перемещение между складами. Кроме того, на определенном статусе резервирует товар на складе.
  • Списание. Отражает списание товара со склада.
  • Инвентаризация. Регистрирует обнаружение или потерю товара на складе. Инвентаризация может проводится целиком по месту хранения, выбранной категории или определенным товарам.


Реализован поштучный учет и интеграция с Честным знаком в части получения контрольных марок, передачи и получения документов в/из ГИС МТ.

Расчеты (Invoicing)


Этот блок реализует логику регистрации входящих и исходящих накладных и платежей. Поддерживается логика связи входящих и исходящих документов для расчета долгов по документу и контрагентам. Реализована возможность разнесения стоимости услуг на себестоимость товаров различными способами.

Поддерживаются четыре основных вида документов :

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


Реализованы печатные формы УПД, ТОРГ-12 и ТОРГ-13.

Закупки (Purchase)


В блоке реализована логика заказов товара и услуг у поставщика. Поддерживается возможность регистрации прайс-листов поставщиков с последующей автоматической подстановкой цен в заказ.

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

Продажи (Sales)


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

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

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

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

Розничная торговля (Retail)


В этом блоке реализован функционал по розничной торговле товарами и услугами.

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

К системе можно подключать несколько касс, настроенных, как для одного, так и для разных мест продаж.

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

Производство (Manufacturing)


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

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

Установка


Для установки решения потребуется сервер под управлением операционной системы Linux или Windows с подключением к Интернет.
На нем должно быть минимум 2 гигабайта оперативной памяти, должен быть открыт порт 8080 для работы веб-клиента и порт 7652 для работы десктоп-клиента.

Linux


Рассмотрим установку MyCompany на примере команд для сервера под управлением CentOS 7, выполняемых с правами суперпользователя root.

Установить платформу lsFusion:
root@centos7: localectl set-locale LANG=ru_RU.UTF-8root@centos7: source <(curl -s https://download.lsfusion.org/yum/install-lsfusion4)

Установить конфигурацию MyCompany:
root@centos7: yum install -y wgetroot@centos7: wget http://download.lsfusion.org/solutions/mycompany-1.0.jar -O /var/lib/lsfusion/mycompany.jarroot@centos7: echo "logics.topModule = MyCompanyRu" >> /etc/lsfusion4-server/settings.properties

Перезапустить службу сервера lsFusion:
root@centos7: systemctl stop lsfusion4-serverroot@centos7: systemctl start lsfusion4-server


Процесс запуска сервера приложений можно контролировать в логе /var/log/lsfusion4-server/start.log.

Windows


Скачать и запустить установщик сервера и клиента по ссылке: 64-битная ОС, 32-битная ОС.
Оставить все параметры по умолчанию. Если необходимо, то задать пароли.

Скачать последнюю версию MyCompany по ссылке и сохранить их в папку lib сервера. (по умолчанию C:\Program Files\lsFusion 4\Server\lib)
Перезапустить службу сервера lsFusion.
image

Миграция данных


В решении существует простой механизм загрузки начальных данных через файлы в формате Excel. Для импорта справочников и других объектов достаточно зайти в Администрирование / Миграция. Для каждого вида справочника есть отдельная кнопка, которая формирует шаблон в формате XLSX, из которого затем можно загрузить данные из старой системы.
image

Доработка


Доработка логики работы решения осуществляется путем внесения изменений в исходный код на внутреннем языке платформы lsFusion. На рабочем сервере это можно сделать добавлением новых модулей путем копирования файлов в папку /var/lib/lsfusion.

Для быстрой и удобной разработки рекомендуется установить локально дистрибутив, который содержит в себе IntelliJ IDEA Community Edition вместе с предустановленным плагином, а также клиентское приложение в виде веб-сервера. При инсталляции устанавливать серверную часть не обязательно, так как нужные библиотеки будут автоматически загружены при помощи Maven. Затем в IDEA нужно запустить Get from Version Control / Github и ввести github.com/lsfusion-solutions/mycompany.git. После этого необходимо настроить запуск сервера через Edit configurations / + / lsFusion Server. После любых изменений, сделанных в исходный код, нужно перезапускать сервер приложений.

image

Для того, чтобы собрать jar-файл с учетом сделанных изменений, необходимо настроить сборку artifacts. Собранный artifact нужно скопировать в папку /var/lib/lsfusion вместо исходного jar-файла решения MyCompany.

Есть вариант подключать базовое решение MyCompany через Maven. Преимущество такого подхода заключается в том, что при обновлении версии базового решения, не будет необходимости делать слияние пересекающихся изменений исходного кода. Недостатком же является невозможность вносить изменения в исходный код базового решения.

Для подключения решения MyCompany через Maven нужно прописать в pom.xml следующие параметры:
<repositories>
<repository>
<id>lsfusion</id>
<name>lsFusionPublicRepository</name>
<url>http://repo.lsfusion.org</url>
</repository>
</repositories>

<dependencies>
<dependency>
<groupId>lsfusion.solutions</groupId>
<artifactId>mycompany</artifactId>
<version>1.0.0-SNAPSHOT</version>
</dependency>
</dependencies>

image

Для большей прозрачности доработок и исключения необходимости слияния кода рекомендуется новую функциональность добавлять в отдельные модули.

Пример:


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

Сначала создаем новый модуль DebtLimit:
MODULEDebtLimit;

Затем заходим в пользовательский интерфейс под администратором и наводим мышкой на заголовок поля с долгом покупателя:

image

Видим, что вычисляемое свойство, которое рассчитывает долг, объявлено в модуле DebtPartner и называется debt с единственным параметром Контрагент(Partner). В новом модуле подключаем этот модуль, чтобы можно было обращаться к его свойствам:
REQUIREDebtPartner;

Создадим для контрагента новое свойство Кредитный лимит, в которое пользователь сможет вводить значение и помещаем его на форму редактирования контрагента partner в контейнер headerRight:
debtLimit'Кредитныйлимит'=DATANUMERIC[14,2](Partner);

EXTENDFORMpartner
PROPERTIES(p)debtLimit
;

DESIGNpartner{
headerRight{
MOVEPROPERTY(debtLimit(p));
}
}

image
Наконец, добавляем ограничение, которое будет проверять, что долг в любой момент времени не должен превышать кредитный лимит по этому покупателю:
CONSTRAINTdebt(Partnerp)>debtLimit(p)MESSAGE'Попокупателюпревышенкредитныйлимит';

Осталось подключить этот модуль к проекту. Создадим новый модуль RogaIKopyta и пропишем его в файле settings.properties:
logics.topModule=RogaIKopyta

При запуске сервера приложений будут подключены только те модули, которые зависят (в том числе рекурсивно) от модуля RogaIKopyta. Соответственно, к нему подключаем созданный нами модуль и MyCompanyRu из базового решения, в котором подключены все основные модули, а также российская локализация:
MODULERogaIKopyta;

REQUIREMyCompanyRu,
DebtLimit;

Чтобы установить эти изменения на боевой сервер нужно либо собрать artifact, как описано выше, либо просто скопировать два файла с модулями RogaIKopyta и DebtLimit в папку /var/lib/lsfusion. Также надо не забыть поменять logics.topModule на рабочем сервере. После изменений нужно перезапустить службу сервера приложений.

image

Поддержка и развитие


Разработкой решения MyCompany занимается белорусская компания ЛюксСофт. Она существует более 20 лет и является лидером на рынке автоматизации крупной розничной торговли в Беларуси. Пять из восьми крупнейших розничных сетей Беларуси используют ее решение lsFusion ERP для автоматизации своей основной деятельности.

Благодаря использованию Java-технологий можно легко подключать различные готовые библиотеки для всевозможных интеграций с внешними системами и других низкоуровневых действий. Удобство разработки обеспечивается за счет использования одной из лучших IDE в мире IntelliJ IDEA (Community Edition).

Основной целью разработки решения MyCompany является поддержка open source движения и популяризация платформы lsFusion. Финансирование решения идет за счет продаж и поддержки коммерческих систем на базе платформы в Беларуси.

На момент написания статьи были реализованы основные функции, необходимые на наш взгляд для минимального жизнеспособного продукта. Дальнейшая разработка будет осуществляться на основе потребностей пользователей. Пожелания по доработке решения можно создавать в виде Issues на Github. Также любые вопросы по решению можно задать в нашем Slack-канале.

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

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

По нашему опыту разработка на lsFusion требует значительно меньше усилий и квалификации, чем разработка на той же платформе 1С. В ней не требуется писать вручную запросы, управлять клиент-серверным взаимодействием и многими другими техническими аспектами. Любой 1С-программист сможет очень быстро освоить разработку на платформе и оказывать услуги по поддержке решения MyCompany. В то же время, в нашей компании есть много людей, которые не имели никакого опыта разработки на чем-либо, и без проблем научились программировать на платформе lsFusion. Большинство продвинутых пользователей Excel, которые умеют строить в нем сложные формулы, а также SQL-программисты, смогут легко освоить базовые механизмы платформы для самостоятельной доработки решения MyCompany.

Бизнес, в свою очередь, сможет сэкономить на различных лицензиях (1С, Windows, Microsoft SQL Server), получив при этом быстрое и современное решение.

Заключение


Основные преимущества MyCompany перед аналогами на российском рынке:

  1. Бесплатность и открытость. Никаких лицензионных условий, подписок, ограничений по пользователям, платежей, HASP-ключей и прочих неудобств.
  2. Скорость и удобство работы. В отличие, от решений на базе 1С, веб-интерфейс работает настолько быстро, что прекрасно работает даже в мобильном браузере. В документы можно добавлять десятки тысяч записей, и это не будет вызывать значительных замедлений при работе. В абсолютно каждую таблицу на любой форме встроено множество возможностей по аналитике и навигации.
  3. Расширяемость. Дорабатывать функционал можно простым добавлением в папку текстовых файлов на лаконичном высокоуровневом языке lsFusion, программировать на котором могут даже продвинутые бизнес-пользователи или любой разработчик 1С.


Подробнее..

Категории

Последние комментарии

  • Имя: Макс
    24.08.2022 | 11:28
    Я разраб в IT компании, работаю на арбитражную команду. Мы работаем с приламы и сайтами, при работе замечаются постоянные баны и лаги. Пацаны посоветовали сервис по анализу исходного кода,https://app Подробнее..
  • Имя: 9055410337
    20.08.2022 | 17:41
    поможем пишите в телеграм Подробнее..
  • Имя: sabbat
    17.08.2022 | 20:42
    Охренеть.. это просто шикарная статья, феноменально круто. Большое спасибо за разбор! Надеюсь как-нибудь с тобой связаться для обсуждений чего-либо) Подробнее..
  • Имя: Мария
    09.08.2022 | 14:44
    Добрый день. Если обладаете такой информацией, то подскажите, пожалуйста, где можно найти много-много материала по Yggdrasil и его уязвимостях для написания диплома? Благодарю. Подробнее..
© 2006-2024, personeltest.ru