Технологии

Система построена по 3-х звенной архитектуре по технологии SPA.

Клиентская часть реализована на Angular, среднее звено на Node.JS, в качестве СУБД используется MySQL/MariaDB. Бизнес -логика реализуется на уровне RDBMS посредством хранимых процедур. Такой подход оправдан для систем класса ERP, когда бизнес логика подвержена изменениям. Он позволяет использовать парадигму экстремального программирования. Возможно изменение бизнес-логики во время работы пользователей в системе.

Несмотря на то, что в Internet много публикаций, критикующих реализацию бизнес-логики посредством stored procedures, в DdApPs разработан ряд средств, минимизирующих недостатки такого подхода. Реализация бизнес-логики средствами SP предполагает другой уровень мышления у разработчика, чем при ее реализации на среднем уровне посредством таких языков как Java, C#, Python, JavaScript,…

Для случаев, когда реализация бизнес логики посредством SP неэффективна, с целью уменьшения нагрузки на SQL server, она разбивается на две части. Та часть, которая неэффективно реализуется при помощи SQL (длительные расчеты, например себестоимость), реализуется в виде сервисов на MiddleWare. Как показал опыт разработки и использования системы Зебра, таких случаев мало.

Основная идея.

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

Расшифровка названия DdApPs.

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

1.1. DD – data driven, database driven

ApPs – applications

1.1. Aps – если читать наоборот, то SPAsingle page application https://en.wikipedia.org/wiki/Single-page_application Интересная дискуссия на https://stackoverflow.com/questions/21862054/single-page-application-advantages-and-disadvantages

Ps – если наоборот то sp — stored procedures – основное средство конфигурирования прикладных решений на основе DdApPs. https://en.wikipedia.org/wiki/Stored_procedure . Интересна дискуссия на https://stackoverflow.com/questions/459457/what-is-a-stored-procedure

A – Angular Первые два года разработка велась на Angular.js https://angularjs.org/ Это было связано с отсутствием Angular и использовалось для экспериментирования со структурами таблиц в базе данных, а также с пользовательским интерфейсом. Текущий год ушел на полное переписывание клиентской части на Angular https://angular.io/ .

A – ag-grid https://www.ag-grid.com/ — js -grid, без которого написание DDAps было бы невозможным. Начало разработки велось с использованием других таблиц, пока не был выпущен данный продукт. В текущей версии используется free version. Однако в связи с ее ограничениями, в конечном продукте планируется использование ag-grid enterprise – единственной библиотеки проекта с комммерческой лицензией https://www.ag-grid.com/license-pricing.php . Возможно, будет принято решение о выпуске двух продуктов DDAps – free (MIT) и Enterprise.

К сожалению, в названии DdApPs нет буквы N для Node.JS ))

Зависимость между слоями

Когда программное обеспечение имеет несколько слоев, одной из задач архитектора является снижение зависимостей между слоями. В DdApPs несколько механизмов для уменьшения такой зависимости. Общение между клиентом и RDBMS реализовано посредством всего 3-х хранимых процедур (причем 2 из них используются на этапе идентификации пользователя). У этих процедур фиксированный набор параметров.

Все константы, используемые при разработке клиента, первоначально описываются в RDBMS. Процесс обновления констант на клиенте после их изменения в RDBMS автоматизирован.

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

Классификация объектов RDBMS

Все серверные объекты (представления, процедуры и функции) делятся на 3 класса — системные объекты (своего рода API), объекты, реализующие бизнес-логику, вспомогательные объекты и хранимая процедура-посредник.  Последняя осуществляют разбор параметров и формируют вызовы «процедур конфигурации» и /или формируют динамические запросы. Последние, в зависимости от реализуемого ими бизнес — процесса, могут быть различного уровня сложности.

Разработка таких процедур является самой трудоемкой часть создания прикладного решения на базе DdApPs.

Статические и динамические сущности.

В системах типа ERP количество сущностей исчисляется сотнями и даже тысячами. В DdApPs Сущности делятся на 3 группы

статические, например пол.

условно-статические, например касса, склад, источники рекламы.

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

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

Сущности в базе данных

 

Традиционным способом хранения сущностей в базе данных является создание для каждой сущности своей таблицы. Например, если у Вас есть сущность «Types of pinned» с двумя записями «left», «right» и сущность «Types of access» с двумя записями «Full access» и «Select only». Наборы свойств у этих сущностей одинаковые. При традиционном способе, для каждой сущности в базе данных создается отдельная таблица. Для нее пишутся хранимые процедуры для вставки, удаления и изменения (или это делается на MiddleLevel приложения). А что если таких сущностей сотни? Система становится крайне негибкой. Поэтому используется другое решение — хранить такие сущности в одной  таблице, сегментированной по типу сущности . Для ускорения работы с такой, более длинной таблицей, MySQL предлагает механизм Partitioning  https://dev.mysql.com/doc/refman/8.0/en/partitioning.html . Различные аспекты применения этого механизма обсуждаются на форуме https://forums.mysql.com/list.php?106  .

В данной таблице хранятся статические, условно-статические сущности, в том числе и список всех сущностей DdApPs.

Для всех таких сущностей можно выделить 2 набора свойств —

1) общие свойства, используемые в пользовательском интерфейсе.

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

Зачем MariaDB

 

На сегодняшний день в качестве RDBMS в DdApPs используется MySQL, как самая распространенная СУБД. Были попытки использовать PostgreSQL, однако она показалась более сложной при установке на Windows. Автор считает, что серверная часть должна работать на разных операционных системах. Также RDBMS должна обладать простыми средствами администрирования. В связи с более быстрыми темпами развития MariaDB а также открытостью исходного кода, планируется переход на MariaDB. На сегодняшний день этот переход видится абсолютно безболезненным и быстрым. Про отличия между MySQL и MariaDB можно почитать например здесь    https://losst.ru/sravnenie-mysql-vs-mariadb . При создании систем визуализации данных, очень важна возможность получения данных из разных источников. Про возможности MariaDB можно почитать например здесь: http://serge.frezefond.com/2013/12/mariadb-connect-storage-engine-access-to-oracle-11gr2/

Состояние объекта

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

  • временная
  • черновик
  • на исправлении
  • действующая
  • архивная
  • удаленная

Маршруты визирования

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

Умные формы, сервисы

 

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

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

Таблицы

Когда я начинал работу над проектов, я, к сожалению, ничего не знал про ag-Grid https://www.ag-grid.com/ .  Поэтому было испробовано несколько других компонентов.  Ознакомление с этой прекрасной сеткой позволило даже переосмыслить струткуру проекта.  В настоящее время для представления табличных данных используется ag-Grid Community. Для Enterprise версии DdApPs планируется использование ag-Grid Enterprise

Диаграммы

Для отображения диаграмм первоначально планировалось использовать библиотеку D3 https://d3js.org/ . Однако у меня почему-то возникли трудности с использованием данной библиотеки совместно с Anhular. Поэтому вопрос об интеграции данной библиотеки в DdApPs отложен и пока, временно используются  http://www.chartjs.org/  и https://js.devexpress.com/Overview/Charts/  ,которые меня не полностью устраивают.

Внешние файлы

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

Именование объектов конфигурации.

 

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

Нормализация и денормализация

 

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