Вступление

В эпоху цифровизации, Вы когда-нибудь задумывались, существуют ли способы значительно снизить затраты на разработку автоматизации какого-либо процесса? И речь не про жалкую экономию в 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, что в классической разработке заняло бы недели, а то и больше. При этом, платформе абсолютно без разницы какой объект планируется цифровизировать: оборудование, изделие, документация или какие-то финансовые потоки и показатели. Гибкая модель позволяет быстро конфигурировать сущности, включая разветвлённые связи между ними.

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