Вступление

В эпоху цифровизации, Вы когда-нибудь задумывались, существуют ли способы значительно снизить затраты на разработку автоматизации какого-либо процесса? И речь не про жалкую экономию в 5-10%, а именно экономию в разы, когда от идеи до ввода в промышленную эксплуатацию - достаточно пару недель разработки. Не месяцы и не годы подготовки тендеров, ФТТ, документов, а только собственные силы. Когда работающий прототип можно "накидать" за пару недель и сразу демонстрировать работающее решение, параллельно доводя его до совершенства. Особенно это актуально для инжиниринговых, конструкторских или производственных предприятий, которые по своей сути не являются разработчиками ИТ, но вынуждены здесь и сейчас, малыми затратами, обеспечивать собственные нужды различными ИТ-решениями.

И если вы подумали, что речь пойдёт про "разбушевавшийся" тренд с LLM и vibe coding - НЕТ.

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

Рецепт

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

Можно сказать, что такие платформы можно отнести к low-code классу. Частично это так, но не совсем. Low-code во многом применяется только в части построения модели данных или UI, но для сложных процессов в любом случае требуется полноценное программирование. Платформа как раз "убирает" рутинные операции, а разработчик сосредотачивает всё своё время на программировании конкретного процесса, используя простые платформенные абстракции.

Немного конкретики

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

Приведу популярные примеры, "широко известные в узких кругах":

  1. Hexagon SmartPlant Foundation (ранее Intergraph SmartPlant Foundation) - зарубежная кастомизируемая платформа для решения внутренних задач инжиниринга.
    Основной язык программирования: С#.

  2. TDMS  - отечественная кастомизируемая платформа, с готовыми модулями по документообороту.
    Основной язык программирования: Microsoft Visual Basic и С#.

  3. Dassault Systèmes 3DExperience (ранее Dassault Systèmes Enovia, ещё ранее matrixone) - зарубежная мощнейшая кастомизируемая PLM, платформа, широкого спектра применения.
    Основной язык программирования: Java, JSP, Angular.

Подобных платформ относительно много. Я привёл только те, с которыми хорошо знаком.

Касаемо 3DExperience - это вообще лидер в области кастомизации. Она и является моей специализацией уже много лет. И проще перечислить что мы на ней НЕ делали, чем все её возможности.

И да, изначально (лет 20 назад) PLM - это только про жизненный цикл изделия. Но поскольку возможности такой платформы предполагают гибкую архитектуру модели данных, разработчики быстро догадались применять их для решения любых повседневных задач, а не только хранить там сборочные модели с разбивкой вплоть до болтиков. Документооборот - пожалуйста, управление требованиями - легко, управление проектами - уже завтра будет готово и т.д. Поэтому сегодня, я бы называл такие решения - суперплатформами. Что думаете об этом?

Положительные стороны при использовании платформ

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

  • Любая платформа идеально вписывается в инфраструктуру и архитектуру любого предприятия.

  • Снимает вопросы кем, на чём и как разрабатывать новый модуль или функциональность.

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

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

  • Ну и самое главное - платформа даёт возможность здесь и сейчас вносить изменения своими силами!

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

А минусы?

Безусловно и минусы тоже есть. Самое главное - это зависимость от конкретного вендора и его действий. В связи с последними событиями, иностранные вендоры прекратили поддержку продуктов в РФ, и сейчас покупка (или продление) лицензий стала невозможной. Конкретно 3DExperience (от французской компании Dassault Systèmes), из-за отсутствия возможности докупить и продлить лицензии, сейчас отважно погибает на глазах у предприятий, отметив "20 лет" успешного внедрения.

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

10 признаков "настоящей" платформы управления данными

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

  1. Встроенные сервисы аутентификации и авторизации пользователей.

  2. Статусная и ролевая модель доступа к контенту (данным).

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

  4. Связи между объектами - отдельные сущности.

  5. Наличие версионности объекта.

  6. Управление файлами.

  7. Доступ к контенту (данным) через высокоуровневый API с автоматической проверкой доступа, без необходимости написания нативного SQL.

  8. Универсальный REST API для CRUD-операций с любыми сущностями платформы.
    Если для взаимодействия с контентом требуется создание соответствующего специального REST сервиса, для конкретной сущности - то это не может называться платформой (тут ближе название - фреймворк). У "настоящей" платформы уже есть встроенный универсальный сервис для взаимодействия с любыми записями (имя интересующей сущности передаётся в теле запроса).

  9. Гибкий кастомизируемый UI конструктор, с широкой компонентной базой.

  10. Полноценный аудит: история изменений контента (данных) с указанием кто, что и когда изменил.

Техническая часть

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

Учитывая мою специализацию - 3DExperience, я мог бы легко показать, как осуществляется кастомизация, на её примере. Проблема в том, что её особенности могут отпугнуть, поскольку в качестве основного инструмента кастомизации является внутренний, никому неизвестный язык (mql). Не подготовленный читатель не поймёт о чём речь.

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

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

Кастомизация BE

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

Чтобы пример был достаточно понятен и красочен для широкой публики - я долго перебирал в голове множество интересных вариантов. И остановился на следующем: реализация цифровой модели карьерного самосвала. Но не всех его агрегатов, а только его базовых свойств, плюс колёса/шины. Здесь реализуем модель данных и UI. На выходе будет полноценно работающий модуль. И на всё уйдёт не больше 3 часов конфигурации, включая UI!

Модель данных

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

Схема модели данных
Схема модели данных

Приступим к кастомизации. Формируем модель данных:

Атрибут VIN:

{
  "name": "VIN",
  "data_type": "string",
}

Атрибут Гос.номер:

{
  "name": "RegNumber",
  "data_type": "string"
}

Атрибут Диапазон допустимых давлений, атм:

{
  "name": "PressureRange",
  "data_type": "real_range",
  "dimension": null
}

Атрибут Расположение колеса со списком значений FL (front left), FR (front right) и т.д.:

{
  "name": "WheelLocation",
  "data_type": "string",
  "choice": ["FL", "FR", "RL", "RR"]
}

Основные типы данных атрибутов: string, string multi, real, real_multi, real_range, integer_integer_milti, timestamp, timestamp_range, boolean. Для real* атрибутов также доступна возможность указать группу ЕИ (единиц измерений), с автоматическим пересчётом значений из одной ЕИ в базовую (указывая значение 1 МПа, платформа автоматически пересчитывает и сохраняет базовое значение равное 1 000 000 Па).

Тип Самосвал с атрибутами VIN и Гос.номер:

{
  "name": "DumpTruck",
  "attributes": [
    "VIN",
    "RegNumber"
  ]
}

Тип Колесо:

{
  "name": "Wheel",
  "attributes": []
}

Тип Шина с атрибутом Диапазон допустимых давлений:

{
  "name": "Tire",
  "attributes": [
    "PressureRange"
  ]
}

Жизненный цикл Самосвала cо статусами Создан, Эксплуатация, Консервация, Выведен из эксплуатации и отдельными доступами на каждом:

{
  "name": "DumpTruck",
  "types": ["DumpTruck"],
  "states": [
    {
      "name": "New", 
      "role_access": [
        {
          "name": "PUBLIC", 
          "rights": ["read", "create", "delete", "modify", "file_upload", "file_download"]
        }
      ]
    },{
      "name": "Operation", 
      "role_access": [
        {
          "name": "PUBLIC", 
          "rights": ["read", "modify", "file_upload", "file_download"]
        }
      ]
    },{
      "name": "Conservation", 
      "role_access": [
        {
          "name": "PUBLIC", 
          "rights": ["read", "modify", "file_upload", "file_download"]
        }
      ]
    },{
      "name": "Decommissioned", 
      "role_access": [
        {
          "name": "PUBLIC", 
          "rights": ["read"]
        }
      ]
    }
  ]
}

Жизненный цикл Simple для колёс и справочника шин:

{
  "name": "Simple",
  "types": ["Wheel", "Tire"],
  "states": [
    {
      "name": "New", 
      "role_access": [
        {
          "name": "PUBLIC", 
          "rights": ["read", "create", "delete", "modify"]
        }
      ]
    }
  ]
}

Связь СамосвалКолесо с атрибутом Расположение:

{
  "name": "DumpWheel",
  "attributes": ["WheelLocation"],
  "from_types": ["DumpTruck"],
  "from_cardinality": "many",
  "to_types": ["Wheel"],
  "to_cardinality": "one"
}

Связь КолесоШина:

{
  "name": "WheelTire",
  "attributes": [],
  "from_types": ["Wheel"],
  "from_cardinality": "many",
  "to_types": ["Tire"],
  "to_cardinality": "one"
}

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

Ну сформировали json'чики, и что дальше?

А дальше - по сути ничего больше не нужно. Всё готово. Запускаем платформу и сразу можно приступать к созданию конкретных записей объектов и связей между ними.

А как же JPA, SQL, спросите вы? Повторюсь - ничего не нужно, не волнуйтесь, платформа прекрасно понимает что и как нужно сделать, без дальнейшего участия разработчика. Главное правильно сформировать схему.

Обращаю ваше внимание, что такие базовые свойства как: type, policy, state, code, title, description, full_code, full_title, originated, modified - уже присутствуют в каждом объекте и создавать для них отдельные атрибуты не требуется!

Создаём самосвал и 4 колеса к нему

Создаём самосвал, с помощью запроса POST /objects/ - получаем UUIDDumpTruck

{
  "type": "DumpTruck",
  "policy": "DumpTruck",
  "code": "БелАЗ 7545",
  "title": "Карьерный самосвал грузоподъёмностью 45 тонн",
  "attributeValues": {
    "VIN": {
      "value": "0123456789"
    },
    "RegNumber": {
      "value": "x777xx77"
    }
  }
}

Создаём колесо FL, с помощью запроса POST /objects/ - получаем UUIDFL

{
  "type": "Wheel",
  "policy": "Simple",
  "code": "FL",
  "title": "Левое переднее колесо",
  "attributeValues": {}
}

Также, через POST /objects/ создаём ещё 3 колеса и получаем UUIDFR, UUIDRL, UUIDRR.

Создаём шину, с помощью запроса POST /objects/ - получаем UUIDTire.

{
  "type": "Tire",
  "policy": "Simple",
  "code": "18.00-25 ВФ-76БМ нс.32 Е3 ТТ",
  "title": "Шина для строительных, дорожных, подъемно-транспортных машин и вездеходов.",
  "attributeValues": {
    "PressureRange": {
      "inputValueMin": 6,
      "inputValueMax": 6.5
    }
  }
}

Указываем для каждого колеса соответствующую марку шины, с помощью запроса POST /connections/ - получаем соответствующий UUID:

{
  "relationship": "WheelTire",
  "from_id": "UUIDFL",
  "to_id": "UUIDTire",
  "attributeValues": {}
}

Также, через POST /connections/ создаём ещё 3 связи.

И прикрепляем созданные колёса к самосвалу, в каждом указываем соответствующий атрибут WheelLocation с помощью запроса POST /connections/

{
  "relationship": "DumpWheel",
  "from_id": "UUIDDumpTruck",
  "to_id": "UUIDFL",
  "attributeValues": {
    "WheelLocation": {
      "value": "FL"
    }
  }
}

Также, через POST /connections/ создаём ещё 3 связи между самосвалом и остальными колёсами.

Итоговый объект самосвала будет выглядеть так, используем запрос GET /objects/UUIDDumpTruck:

{
  "id": "UUIDDumpTruck",
  "type": "DumpTruck",
  "policy": "DumpTruck",
  "state": "New",
  "code": "БелАЗ 7545",
  "release": "",
  "title": "Карьерный самосвал грузоподъёмностью 45 тонн",
  "originated": "2015-01-20T09:45:27.250293Z",
  "modified": "2015-01-20T09:45:27.250293Z",
  "fullCode": "",
  "fullTitle": "",
  "description": "",
  "files": [],
  "attributeValues": {
    "VIN": {
      "value": "0123456789"
    },
    "RegNumber": {
      "value": "x777xx77"
    }
  },
  "fromConnections": [],
  "toConnections": [
    {
      "id": "UUIDFL",
      "relationship": "DumpWheel",
      "from_id": "UUIDDumpTruck",
      "to_id": "UUIDFL",
      "attributeValues": {
        "WheelLocation": {
           "value":"FL"
        }
      }
    },{
      "id": "UUIDFR",
      "relationship": "DumpWheel",
      "from_id": "UUIDDumpTruck",
      "to_id": "UUIDFR",
      "attributeValues": {
        "WheelLocation": {
           "value":"FR"
        }
      }
    },{
      "id": "UUIDRL",
      "relationship": "DumpWheel",
      "from_id": "UUIDDumpTruck",
      "to_id": "UUIDRL",
      "attributeValues": {
        "WheelLocation": {
           "value":"RL"
        }
      }
    },{
      "id": "UUIDRR",
      "relationship": "DumpWheel",
      "from_id": "UUIDDumpTruck",
      "to_id": "UUIDRR",
      "attributeValues": {
        "WheelLocation": {
           "value":"RR"
        }
      }
    }
  ]
}

Минутка юмора.В платформе 3DExperience для просмотра всей информации о конкретном объекте присутствует специальная команда: print businessobject ID и её самый часто используемый краткий вариант - print bus ID. В простонародье мы называли её "распечатать автобус" :)

В итоговом JSON видны все базовые свойства и кастомные атрибуты объекта, а также его связи с другими объектами, в данном случае - 4 связи с колёсами. Есть автоматические свойства, такие как originated, modified, заполняемые без вмешательства разработчиков. Присутствует статус, который меняется через специальные запросы POST /objects/UUID/promote и POST /objects/UUID/demote. Можно посмотреть историю изменений GET /objects/UUID/history, создать версию объекта POST /objects/UUID/release, копию POST /objects/UUID/copy, и много чего ещё.

А если мы забыли указать для самосвала грузоподъёмность? Что теперь делать? Ничего страшного, добавляем новый атрибут и модифицируем тип:

Атрибут Грузоподъёмность:

{
  "name": "Capacity",
  "data_type": "real_range",
  "dimension": null
}

Тип Самосвал:

{
  "name": "DumpTruck",
  "attributes": [
    "VIN",
    "RegNumber",
    "Capacity"
  ]
}

Теперь вместе с другими кастомными атрибутами VIN, Гос.номер можно указывать и Грузоподъёмность, как для новых, так и для уже созданных самосвалов:

POST /objects/UUIDDumpTruck

{
  "type": "DumpTruck",
  "policy": "DumpTruck",
  "code": "БелАЗ 7545",
  "title": "Карьерный самосвал грузоподъёмностью 45 тонн",
  "attributeValues": {
    "VIN": {
      "value": "0123456789"
    },
    "RegNumber": {
      "value": "x777xx77"
    },
    "Capacity": {
      "inputValue": 45
    }
  }
}

Конфигурация UI

Если устали - листайте к сразу заключению.

Кратко, на примере справочника шин, покажу кастомизацию UI, главной особенностью которой - все изменения осуществляются на стороне BE. Да, да, вы не ослышались! Чтобы поменять FE, нужно опять кастомизировать BE. Иначе говоря, BE хранит в себе все базовые настройки форм, таблиц, панели инструментов и т.д., а FE только считывает конфигурацию и рендерит UI в соответствии с настройками.

Справочник шин

Чтобы отображать справочник в UI, понадобится подготовить 4 связанных компонента:

  1. Таблица.

  2. Запрос, извлекающий шины.

  3. Панель инструментов таблицы.

  4. Команда (кнопка), которая открывает справочник.

Таблица TiresBrand, тут всё очень просто:

{
    "code": {
        "label": "Код",
        "columnWidth": 200,
        "settings": {}
    },
    "title": {
        "label": "Наименование",
        "columnWidth": 200,
        "settings": {}
    },
    "PressureRange": {
        "label": "Диапазон допустимых давлений, атм",
        "columnWidth": 200,
        "settings": {}
    }
}

Запрос TiresBrandAll, который извлекает все шины из платформы. Можно добавить условия фильтрации по статусам или по атрибутам, но сейчас это не нужно, просто ищем все шины:

{
  "type": "Tire",//имя типа из модели данных
  "code": "*",
  "release": "*",
  "where" : null,
  "select": [
    "code",
    "title",
    "PressureRange"//имя атрибута из модели данных
  ],
  "pageSize": 1000,
  "limit": 5000,
}

Панель инструментов TiresToolbar таблицы, с кнопками Создать и Удалить:

{
  "name": "TiresToolbar",
  "childs": [
    "TireCreate",//команда создания шины, с указанием формы создания, типом и ЖЦ создаваемого объекта
    "CommonRowsRemove"//команда удаления строчки таблицы
  ]
}
Здесь можно посмотреть конфигурацию для кнопок TireCreate и CommonRowsRemove

Команда (кнопка) создания шины TireCreate:

{
  "name": "TireCreate",
  "label": "Создать",
  "href": {
    "url": "../form/TireCreate",//TireCreate - имя формы создания шины
    "requestParams": {
      "header": "Создать",
      "actionbar": "CommonActions",//панель действий, с кнопкой создать
      "type": "Tire",//имя создаваемого типа из модели данных
      "policy": "Simple",//имя создаваемого ЖЦ из модели данных
      "target": "RIGHT"//открыть форму справа
    }
  }
}

Форма создания шины TireCreate:

{
  "JBTitle": {
    "label": "Наименование",
    "description": null,
    "placeholder": null,
    "value": {
      "original": [],
      "input": []
    },
    "required": true,
    "editable": true,
    "hidden": false,
    "showClear": false,
    "hideLabel": false,
    "autoFilter": false,
    "clientChanged": false,
    "renderComponent": "JTextbox",
    "choice": null,
    "href": null,
    "selectOptions": null,
    "units": null,
    "validation": null,
    "onChange": null,
    "settings": {}
  },
  "ATRTireAcceptablePressure": {
    "label": "Диапазон допустимых давлений, атм",
    "description": null,
    "placeholder": null,
    "value": {
      "original": [],
      "input": []
    },
    "required": true,
    "editable": true,
    "hidden": false,
    "showClear": false,
    "hideLabel": false,
    "autoFilter": false,
    "clientChanged": false,
    "renderComponent": "JRealRange",
    "searchTerm": null,
    "choice": null,
    "href": null,
    "selectOptions": null,
    "units": null,
    "onChange": null,
    "settings": {
      "step": "0.1",
      "min": "0",
      "max": "15"
    }
  }
}

Команда (кнопка) удаления CommonRowsRemove - стандартная переиспользуемая команда, подходит для удаления любых объектов:

{
  "name": "CommonRowsRemove",
  "label": "Удалить",
  "settings": {
    "rowSelection": "MULTI",
    "confirmMessage": "Удалить выбранные строчки?"
  },
  "href": {
    "composable": "useTable",
    "js": "jmxRowsRemove",
    "settings": {}
  }
}

Команда (кнопка) RefTires, которая открывает таблицу TiresBrand, с панелью инструментов TiresToolbar, с данными из запроса TiresBrandAll:

{
  "name": "RefTires",
  "label": "Каталог шин",
  "href": {
    "url": "../table/TiresBrand",//TiresBrand - имя таблицы
    "requestParams": {
      "toolbar": "TiresToolbar",//имя панели инструментов
      "rowSelection": "MULTI",//можно выбрать несколько строк
      "inquiry": "TiresBrandAll",//имя запроса
      "target": "CONTENT"//таблица открывается в текущем окне
    }
  }
}

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

{
  "name": "MyDesk",
  "childs": [
    "ProjectManagementDesk",
    "TestDesk",
    "DocumentsFlowDesk",
    "RefTires"//имя новой команды с каталогом шин
  ]
}

Результат

После внесения изменений, платформа отобразит соответствующую конфигурацию в UI. На панели MyDesk слева появилась соответствующая категория - Каталог шин, которая отображает таблицу с шинами и кастомную панель инструментов с кнопками Создать и Удалить. Если нажать Создать, то платформа отобразит справа форму создания шины, как и указывалось в соответствующей кнопке:

Справочник шин
Справочник шин

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

Сконфигурированный портал колёс самосвала
Сконфигурированный портал колёс самосвала

Заключение

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

Пример с самосвалом ярко отражает суть - за ~3 часа конфигурации создается работающий модуль с моделью данных, бизнес-логикой и UI, что в классической разработке заняло бы недели, а то и больше. При этом, платформе абсолютно без разницы какой объект планируется цифровизировать: оборудование, изделие, документация или какие-то финансовые потоки и показатели. Гибкая модель позволяет быстро конфигурировать сущности, включая разветвлённые связи между ними.

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

Комментарии (4)


  1. DenSigma
    26.01.2026 13:43

    Я правильно понимаю, что вы показываете, как запрограммировать систему, вместо Java, на JSON?


    1. ilemusic Автор
      26.01.2026 13:43

      Чуть подробнее вот здесь описано:

      Можно сказать, что такие платформы можно отнести к low-code классу. Частично это так, но не совсем. Low-code во многом применяется только в части построения модели данных или UI, но для сложных процессов в любом случае требуется полноценное программирование. Платформа как раз "убирает" рутинные операции, а разработчик сосредотачивает всё своё время на программировании конкретного процесса, используя простые платформенные абстракции.

      Это означает, что если требуется обеспечить пользователей какими-то простыми CRUD-операциями, то программирование не потребуется вообще. Если например, при смене статуса объекта, необходимо выполнить отправку "хитрого" уведомления, то конечно эту функцию надо написать (или взять готовую платформенную), а затем указать в конфиге, что-то типа этого:

      {
        "states": {
          "New" : {
            "promoteAction": "ru.platform.Mail:sendEmail"
          },
          "Approval": {
            
          }
        }
      }

      Здесь я показал на JSON'e, некоторые платформы используют XML или более специфичные форматы. Так было раньше. Сейчас, на мой взгляд, есть более удачное и современное решение для конфигураций. Думаю напишу об этом в следующей статье.


      1. DenSigma
        26.01.2026 13:43

        Позволю себе еще раз повторить свою мысль.

        Программирование требуется всегда. Это заблуждение и маркетинговое вранье продаванов "нокод" систем, что вам не придется программировать. Для разработки, доработки, "конфигруции" и прочего допиливания всегда необходимо программирование. Программирование - суть появления софта.

        Только вместо программирования на Java, Delphi, Шарпа, вы будете "программировать" на джейсоне, каких-то самопальных языках разметки, скриптовых общепринятых и самопальных скриптовых языках, типа одинэсной ахинеи.

        В crud-операциях, как минимум, надо где-то описать модель базы данных, связи и прочее. Вместо java-кода, вам придется "программировать" на Json, или упаси боже, на xml. Аргумент, почему эти конфиги хуже простого кода на Java - в Spring ушли от конфигов на xml в сторону кода Java. И стало проще и читабельнее.

        Ваш пример с конфигурацие хитрого уведомления - просто пример ужаса. Код Java, который будет решать данный функционал, будет проще и короче. Его можно будет отлаживать очень просто. Код на Java отлично автодополняется и проверяется компилятором. Вашу конфигурацию, чтобы проверить, что вы не наврали с синтаксисом, придется проверять запуском приложения и тычком на кнопку. При этом надо промудохаться с поднятием стенда. Да еще надо сформировать пример Customer-а, к примеру, чтобы добраться к нужному интерфейсу и функционалу. Чтобы удостовериться, что вы не написали ru.platform.Mail:sеndEmail (найдите здесь ошибку).

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


        1. ilemusic Автор
          26.01.2026 13:43

          Да, в целом всё верно мыслите, я абсолютно согласен.

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

          Грубовато. Обижаете спецов. В каждой системе есть свои особенности, где-то ABAP, где-то синтаксис на русском... Каждый сам выбирает "сторону". Кому-то - узкая специализация равна смерти, а кто-то прекрасно себя чувствует в ней.

          И тем не менее, конкретно в нашей индустрии, факт остаётся фактом - то что будет 6 месяцев разрабатываться с нуля на java плюс frontend, на платформе я легко сделаю за 3 недели.