В этом году «Фоксфорд» впервые проводит международную онлайн-олимпиаду по бизнес-логике. Разработчик олимпиадных заданий Сергей Сочнев делится секретами успеха и размышляет о бизнес-образовании.
Сергей, как вы дошли до создания олимпиады для школьников?
Визуальный конструктор бизнес-логики на основе Camunda BPM
Привет! Меня зовут Олег Гетманский, я – старший архитектор информационных систем. Сегодня расскажу, как мы упростили создание и управление бизнес-процесссами в IdM, оставив в прошлом жестко зашитые в систему правила и внедрив гибкий визуальный конструктор бизнес-логики Camunda BPM. Под катом краткое руководство по внедрению движка с моими комментариями – возможно, для кого-то оно сэкономит несколько рабочих часов или даже дней.
Автоматизация в IdM
Развитая IdM-система должна уметь автоматизировать процессы управления доступом даже в крупных компаниях с сотнями тысяч пользователей. Ее можно рассматривать как пункт управления: система интегрируется с другими информационными ресурсами организации и дает возможность централизованно управлять пользователями и их полномочиями. Процессы управления включают в себя такие операции, как предоставление доступа при приеме на работу, запрос дополнительных полномочий, приостановка доступа при увольнении, смена пароля и прочие действия, которые требуются по регламентам компаний.
Грамотное ООП: организация надёжной бизнес-логики / Дмитрий Елисеев (ElisDN)
С точки зрения разработчика самое сложное в системах класса IdM – это требование абсолютной кастомизируемости: заказчики считают, что в IdM все должно быть настраиваемо. Приведу несколько примеров из жизни:
- Есть стандартная логика бизнес-процесса: IdM автоматически создает учетную запись для сотрудника при приеме на работу и блокирует УЗ и связанные с ней права при увольнении. Написали код, протестировали, выпустили фичу – все работает. Но у заказчика есть такое понятие, как перевод через увольнение, и теперь наша фича ломает этот выстроенный процесс перевода – IdM воспринимает его как просто прием на работу и создает новую учетную запись, а она сотруднику не нужна. Здесь важно, чтобы осталась прежняя учетка, и, уж тем более, чтобы она не заблокировалась.
- IdM автоматически блокирует аккаунт на время отпуска пользователя. Эту фичу можно включить и выключить. Обязательно найдется заказчик, который попросит вместо блокировки отправлять уведомление, или перемещать учетную запись в отдельный каталог.
- IdM автоматически назначает базовые роли новым пользователям. Внезапно найдутся «не такие как все» VIP-пользователи, которым нужно назначать роли в обход регламента – по разным алгоритмам в разных организациях.
- В IdM на одного сотрудника приходится одна персональная учетная запись в домене организации. Это хорошо, но есть такие организации, в которых сотрудники работают на нескольких должностях по совместительству, и должны иметь несколько доменных аккаунтов.
Список потенциальных требований, которые нельзя предсказать заранее, со временем становится все больше и больше. Из-за этого у нас возникает ощущение, что новые фичи всегда получаются недоделанные, а программисты виноваты в том, что разрабатывают недостаточно гибкий продукт.
Как строится модель бизнес-процессов. Взгляд изнутри #shorts
Как можно решить эту проблему? Мы пробовали разные варианты:
- Inline feature flags. Создаём множество параметров конфигурации и прямо в коде бизнес-логики пишем, как нужно поступать в том или ином случае, в зависимости от этих параметров. В отдельном интерфейсе можно включить те или иные флажки. Идея не взлетела, потому что мы все равно не знаем, какие фича-флаги понадобятся в будущем. К тому же чем больше в коде фича-флагов, тем дороже выходит реализация очередного такого флажка.
- Заскриптованная бизнес-логика. Оставить в стабильной ветке лишь общий workflow и архитектурный «каркас» в виде доступных сервисов и API, предоставив командам внедрения возможность самостоятельно закодировать специфичную для заказчика бизнес-логику. В таком случае объектом поставки является комбинация из стандартного продукта и множества скриптовых конструкций (в нашем случае это скрипты на языке Groovy). Кастомизировать и настраивать в такой модели можно практически всё, что угодно, однако при написании скрипта легко поломать то, что работало раньше. К тому же на практике оказалось довольно сложно поддерживать обратную совместимость для старых скриптов в новых версиях продукта.
- Плагины. Выделить сервисы-компоненты в виде простых Spring-бинов, каждый из которых отвечает за свой участок бизнес-логики. Реализацию компонента можно дополнить или вовсе заменить, если подложить в classpath приложения jar-файл, в котором есть альтернативная реализация бина. В таком случае мы получаем высокую кастомизируемость, в том смысле, что позволяем разработчикам самостоятельно написать плагин под конкретного заказчика. Однако при изменении кода оригинальных бинов нам придётся адаптировать все существующие плагины под новую версию продукта.
BPM-движок в основе бизнес-логики
На самом деле продвинутая IdM-система должна уметь управлять аккаунтами и привилегиями, назначать и отзывать роли, посылать уведомления, выявлять нарушения и много другого полезного. Остается только уточнить, когда именно и как именно это всё нужно делать в отдельно взятой организации: когда создавать аккаунт для сотрудника (и сколько их будет), когда назначать роли и какие они будут, когда посылать уведомления, и о чем они должны быть и тому подобное.
Если посмотреть на IdM как на систему, автоматизирующую бизнес-процессы, то получается, что:
- Можно выделить контекстно-независимые компоненты для проведения атомарных операций (создать аккаунт, назначить роль, отправить уведомление). Эти компоненты простые, они очень редко изменяются, и их можно переиспользовать. В своей системе мы иногда создаем новые компоненты, когда нужна новая функциональность.
- Задача располагает к выстраиванию событийно-ориентированной архитектуры. При различных действиях (автоматических или пользовательских) порождаются события. В ответ на различные события происходят автоматические действия, определяемые бизнес-процессами организации («Новый пользователь? Создать доменный аккаунт», «Сотрудник ушел в отпуск? Временно заблокировать аккаунт», и много другого, что может потребоваться в отдельно взятой организации). Любую автоматику можно представить как последовательность простых шагов.
- Максимальная гибкость настройки требуется именно на уровне принятия решений. Это не касается компонентов, выполняющих атомарные операции. Очень редко нужно изменять реализацию конкретных операций, и наоборот — очень часто мы будем изменять алгоритмы принятия решений – то есть добавлять условия на выполнение тех или иных операций, менять их последовательность, убирать из процессов ненужные шаги и добавлять нужные.
Так почему бы не возложить автоматизацию бизнес-процессов на предназначенный для этого движок BPM, оставив непосредственно в IdM только компоненты атомарных операций? Давайте посмотрим, что из этого получилось у нас в нашей IdM-системе.
В качестве BPM-системы мы выбрали Camunda v.7 – это open-source движок, его можно встроить в Java-приложение, он хорошо интегрируется со Spring. Есть визуальный редактор Camunda Modeller, в котором можно рисовать бизнес-процессы (БП). Сами БП у нас будут в формате BPMN (Business Process Management Notation).
Ниже под спойлером будет немного кода в технологическом стеке Java 17 + Maven + Spring Framework + Hibernate.
Компоненты атомарных операций
Сначала создадим атомарные компоненты. Каждый компонент – это небольшой stateless-бин, который отвечает за свою ограниченную область применения. Методы бина должны быть максимально простые и как можно более универсальные, мы должны иметь возможность вызвать их без знания контекста.
Теперь мы можем вызывать компонент RoleOps в скриптовом обработчике Camunda:
roleOps.assignRoleToUser(«id-role-admin», userId)
Получается лаконично, такие однострочники мы затем будем использовать в BPMN-диаграммах.
Интегрируем Camunda в проект
Создаем новый Maven проект, добавляем зависимости на Camunda, Spring и сервисы инфраструктуры IdM:
org.camunda.bpm camunda-engine org.camunda.bpm camunda-engine-spring org.springframework spring-context ru.solarsecurity.inRights.model model-common provided
В нашем случае мы создаем отдельный Maven-модуль, который живет в составе проекта, однако можно сделать отдельный BPM-микросервис. Сегодня это даже предпочтительно: принятие решений – отдельно, исполнители – отдельно.
Создаем конфигурацию Camunda:
Итак, сейчас у нас есть движок Camunda, в нем можно развернуть свои бизнес-процессы и стартовать их.
В нашей IdM бизнес-процессы будут стартовать по сигналу, где сигнал – это какое-либо пользовательское действие или внешнее событие.
Все сигналы наследуются от нашего интерфейса CamundaSignal:
public interface CamundaSignal extends Serializable
Для Camunda важно, чтобы сигналы были сериализуемыми и имели название.
Пример сигнала, который говорит о том, что в IdM появился новый пользователь:
Создаем сервис для запуска бизнес-процессов по сигналам. Поскольку запуск БП и выполнение всех его шагов – это дорогостоящая операция, то лучше не блокировать поток обработки пользовательских запросов и сделать запуск БП асинхронным. Мы отправляем сигналы для Camunda в отдельном ThreadPoolExecutor:
Теперь отправляем сигналы в Camunda там, где возникают соответствующие события в системе:
// В БД сохранен новый пользователь userRepository.save(user); // Сообщаем об этом Camunda camundaSignalService.sendSignal(new UserCreatedEvent(user.getId(), user.getLogin(), user.getName(), user.getAttributes()));
Далее — разворачиваем в Camunda наш стандартный БП, чтобы наполнить уже движок каким-нибудь полезным функционалом. В идеале мы хотим сделать отдельную административную web-страничку для управления бизнес-процессами – разворачивать новые БП, скачивать / включать / выключать существующие. Интерфейсы Camunda для этого не подходят, поэтому создадим свой простой репозиторий сущностей БП.
Сущность бизнес-процесса имеет название, случайный id как UUID, флаг развернут / не развернут, и контент в формате BPMN:
Репозиторий для сущностей БП:
public interface BusinessProcessRepository extends CrudRepository < OptionalfindByName(String name); >
BusinessProcessDeploymentService отвечает за фактическое соответствие сущностей BusinessProcessEntity реальному состоянию БП в Camunda BPM. С помощью него и только него мы будем управлять БП на инсталляциях нашей IdM:
Установка флага deployed = true и деплоймент в Camunda происходят в одной транзакции, поэтому если в процессе деплоя что-то пойдет не так, то сущность BusinessProcessEntity не будет считаться активным процессом.
Для краткости я пропущу написание REST-контроллера и детали реализации фронтенда.
Итоговый вид административной странички управления БП:
Бизнес-процессы разворачиваются в Camunda сразу после загрузки файла. Если снять флажок «Активен» с бизнес-процесса, то деплоймент будет удален из Camunda, но сама сущность BusinessProcessEntity останется в таблице. Так можно включать и отключать БП, не удаляя их из системы. Если загрузить БП с именем, которое уже есть в таблице, тогда старая версия БП будет обновлена в Camunda.
Пишем простой бизнес-процесс
Для составления БП будем использовать редактор Camunda Modeller. Создаем новый файл в формате BPMN diagram (Camunda Platform 7).
Добавляем сигнал начала процесса — userCreatedEvent (как написано в коде: UserCreatedEvent#getSignalName). Добавляем в процесс шаги типа Script Task. Внутри шагов — скриптовые выражения, вызывающие методы атомарных компонентов. В результате получится примерно так:
Сохраняем файл bpmn, загружаем в IdM и таким образом реализуем то, что нужно организации.
Итак, составляя BPMN, можно быстро набросать работающую фичу по желаниям заказчика, возможно, даже сидя вместе с ним за одним столом. Нужно сделать перевод через увольнение? Отлично, только расскажите, с чего оно начинается, и что IdM должна при этом сделать. Если известны стартовые события и правила формирования атрибутов учетных записей, то поддержать множественные доменные аккаунты также будет довольно просто.
В целом, чем больше атомарных бинов, которые можно использовать в БП, – тем более функциональные процессы можно строить в визуальном редакторе.
Теперь мы можем выстроить такой процесс реализации новых фич:
- Системный аналитик (или заказчик, архитектор, разработчик) представляет схематичное изображение нового бизнес-процесса. Это может быть BPMN-диаграмма или просто иллюстрация с разноцветными элементами. Самое главное, чтобы было понятно, какие события должны происходить и как на них нужно реагировать.
- Превращаем схему в валидную BPMN-диаграмму.
- Наполняем диаграмму обращениями к атомарным компонентам через скриптовые выражения.
- Реализуем в IdM новые сигналы (события, запросы) и атомарные компоненты, если существующих недостаточно.
- Получаем рабочий бизнес-процесс в виде файла с расширением bpmn, проверяем работоспособность.
- Устанавливаем готовый bpmn у заказчика.
Готовый БП – это легковесный переносимый артефакт. Файлы bpmn можно копировать, изменять, можно положить их в систему контроля версий и использовать как основу для других кастомных БП.
В заключение
BPM-движок, такой как Camunda, вполне может использоваться как визуальный конструктор в окружении, где требуется 100% кастомизируемость алгоритмов и сложно предсказать, в какую сторону пойдет развитие той или иной фичи.
Плюсы этого решения:
- Это «микросервисно»! Модуль BPM взаимодействует с остальной системой посредством обмена сигналами и событиями, это позволяет выделить его в отдельный микросервис. Инфраструктура исполнения команд, поступающих от BPM, может быть масштабирована отдельно.
- Поощряет написание простого кода. BPMN-диаграммы будут простые и понятные, если таковыми будут атомарные компоненты, которые их поддерживают. Желательно, чтобы Ops-бины принимали и возвращали простые типы данных: строки, числа, enum, record.
- Наглядность. Бизнес-логика в BPMN отображена визуально. Не требуется умение программировать, чтобы понимать диаграммы бизнес-процессов.
- Изменения on-the-fly. Для изменения бизнес-логики на конкретной инсталляции достаточно только загрузить новый файл bpmn.
- Обратная совместимость. Поскольку БП работают только с Ops-компонентами, то для поддержки обратной совместимости нам достаточно того, что публичное API Ops-компонентов не изменяется от версии к версии. Если нам нужны более продвинутые возможности от операционных компонентов, тогда мы просто напишем новые бины.
- Производительность. Мы не используем в Camunda асинхронные процессы, таймеры и пользовательские задачи. Выполнение всего БП укладывается в одну транзакцию. Это значит, что не требуется сохранять промежуточное состояние процесса в базе. Скорость выполнения кода бизнес-логики практически равна скорости выполнения обычного Java-кода. Подробнее о транзакциях в Camunda.
На что нужно обратить внимание, если вы решитесь на внедрение движка BPM:
- Тяжеловесность. BPM-движок усложняет систему как минимум одним своим присутствием. Поэтому если ваша предметная область достаточно предсказуема, и вы можете сохранить гибкость вашего продукта просто посредством написания качественного кода, тогда вам не нужен BPM.
- Нужно знать нотацию. Для того, чтобы грамотно составлять бизнес-процессы, кто-то в команде должен изучить нотацию BPMN 2.0.
- BPM – это автоматические действия. Описанный способ применения движка не подходит для решения общих проблем в области кастомизации. К примеру, если нужно сделать настраиваемые графические формы или слегка изменить сценарий взаимодействия программы с пользователем – тогда BPM не поможет, а более подходящим инструментом будет модульный конструктор фронтенда. Наиболее сильная сторона движка BPM – это автоматизированные процессы и действия, происходящие без участия человека.
- Обязательное протоколирование. Довольно сложно проводить отладку кода бизнес-логики, когда он заключен в BPMN-диаграммы. Крайне желательно делать так, чтобы любое совершенное действие было зафиксировано в файлах логов или в журнале событий, или в системе аудита. По этим данным позже можно будет отследить, почему движок BPM принял то или иное решение на конкретном шаге. Без подробного протоколирования бизнес-процессы – это черный ящик.
- bpmn
- camunda
- idm
- автоматизация процессов
- бизнес-логика
- управление доступом
- Блог компании Ростелеком-Солар
- Информационная безопасность
- Софт
Источник: habr.com