Приветствую моих читателей! Меня зовут Екатерина. Ранее 3.5 года я администрировала bpm-систему, сейчас вот уже более двух лет я работаю системным аналитиком и развиваю нашу собственную bpm-систему. В данной статье хочу рассказать о дилемме, с которой столкнулись я и моя команда.
Немного познакомлю вас с тем, над чем мы работаем — BPMS (система для управления бизнес-процессами, в основе которой лежит BPMN). Движок полностью разработан специалистами компании. Фронтовая часть реализована на основе библиотеки bpmn.io, с доработкой логики, специфичной для внутренних задач. В этой библиотеке представлен широкий выбор элементов, но у нас своя обёртка над ней — bpmn-editor, в которой мы открываем элементы для пользователей по мере проработки логики их автоматизации.
Немного о той части системы, над которой работаю я:
Визуальный редактор процессов, в котором можно проектировать собственные процессы в соответствии с нотацией BPMN 2.0, а также управлять жизненным циклом процессов. Пользователи могут самостоятельно корректировать карты процессов в зависимости от меняющихся потребностей бизнеса.
Автоматизация бизнес-процессов. В зависимости от настроек процесса, система самостоятельно создает задачи для нужных пользователей, отправляет письма, вносит изменения в объектах и контролирует ход выполнения задач в указанные сроки.
Контроль хода выполнения процессов, отслеживание действий сотрудников в рамках их задач, построение отчётов и получение статистики о ходе выполнения задач и процессов.
Основными сущностями движка являются:
Процесс (WorkFlow).
Экземпляр процесса (WorkFlowExemplar) — создаётся при запуске процесса.
Задачи (WorkFlowTask) — создаются экземпляром при попадании токена в User и Manual Task.
Одно из направлений развития: расширение библиотеки компонентов в bpmn-editor.
Ранее в движок была добавлена поддержка элемента Call Activity. И в определённый момент времени от бизнеса поступил запрос на добавление очередного элемента — Collapsed SubProcess. И здесь передо мной стал вопрос: а в чём принципиальное отличие Call Activity и Collapsed SubProcess? Кажется, Действие Вызова может всё то же самое и даже больше. Но как оказалось, не всё так просто. Чтобы разобраться в вопросе, предлагаю сравнить оба элемента и расставить всё на свои места.
Об элементах
В нотации моделирования бизнес-процессов (BPMN) существует два визуально похожих элемента: Свернутый Подпроцесс (Collapsed SubProcess) и Действие Вызов (CallActivity).
Определение ПодпроцессаПодпроцесс представляет собой Действие, заключающее в себе другие Действия, Шлюзы, События и Потоки операций.
Определение Действия ВызоваДействие Вызов определяет отрезок Процесса, где используется глобальный Процесс (Global Process) или Глобальная Задача (Global Task). Оно оформляет их вызов в ходе выполнения Процесса. Результатом запуска этого Действия является передача управления глобальным Процессом или Глобальной Задачей.
В BPMN 1.x Call Activity и SubProcess фактически были вариантами одного и того же элемента. То, что мы сегодня знаем как Подпроцесс, тогда называлось встроенным Подпроцессом, а Call Activity — повторно используемым Подпроцессом.
Оба элемента имеют схожую визуализацию и схожий алгоритм работы: в каждом из этих двух элементов заключена совокупность иных элементов, которые должны быть выполнены для движения токена. Для того, чтобы понять, в чём же принципиальная разница, необходимо определиться, в каких случаях предпочтительно используется каждый из элементов и как они должны работать в исполняемых процессах.
Основные тезисы
Порядок создания
SubProcess: Может быть создан только в рамках процесса: сначала создаётся процесс, потом — Подпроцесс.
Call Activity: Последовательность создания не важна: можно сначала создать вызываемый процесс, а потом вызывающий или наоборот.Контекст
SubProcess: Не имеет своего собственного контекста.
Не имеет входящих или исходящих данных. У отдельных задач на дочернем уровне они есть, но у Подпроцесса, в целом, — нет.
Call Activity: Имеет свой собственный контекст.
Механизм взаимодействия между контекстами вызывающего и вызываемого процессов необходимо настраивать отдельно, например, посредствам маппинга данных: Входящие данные Call Activity по определению являются исходящими данными вызывающего процесса, а исходящие данные Call Activity являются входящими данными для вызывающего процесса. Сами сопоставления данных определяются в конфигурации Call Activity.Тестирование
SubProcess: Не может быть протестирован отдельно от процесса, т.к. является его неотъемлемой частью.
Это может стать проблемой при отладке масштабных схем.
Call Activity: Может быть протестирован самостоятельно.
Разбиение сложного процесса на небольшие исполняемые фрагменты делает тестирование более управляемым, а более крупный процесс может затем собрать эти фрагменты (которые можно повторно использовать в других сценариях) с помощью Call Activity.Исполнение
SubProcess: Подпроцесс — это часть процесса, поэтому не может быть исполнен самостоятельно.
Выполнение Подпроцесса инициируется потоком управления процесса, в котором он находится. Сущность экземпляра подпроцесса не создается.
Call Activity: Единицей исполнения в BPMN является процесс, поэтому вызываемый процесс может быть выполнен как в рамках вызывающего процесса, так и самостоятельно.
Запуск процесса инициируется начальным событием. При запуске создается экземпляр вызванной сущности.Переиспользование
SubProcess: Подпроцесс не может быть использованным в нескольких процессах.
Даже в рамках одного процесса может быть выполнен несколько раз только в том случае, если в него вернется токен, т.е. посредством потоков будет создан "цикл". Если настроенный Подпроцесс будет скопирован и вставлен в тот же пул, то это уже будет два разных Подпроцесса с идентичной структурой.
Call Activity: Может быть вызван из неограниченного количества иных процессов.
Факт наличия вызываемых процессов (выделения повторяющихся последовательностей действий) говорит о высоком уровне навыков проектирования и понимания бизнес-процессов организации.Применение
SubProcess: Используется для упрощения визуализации сквозной логики процесса, преимущественно для печатных версий бизнес-процессов.
Здесь всё зависит от целей использования схем. Так, например, для демонстрации этапов бизнес-процесса на схеме могут быть только блоки Подпроцессов, при этом совершенно неважно, какая комбинация элементов будет внутри.
Call Activity: Могут быть свои пулы и дорожки.
В рамках вызываемых процессов может быть реализована более сложная логика, нежели в Подпроцессах.
Как это может быть реализовано в BPMS?
В большинстве своем при разработке требований для нового элемента я использую следующую структуру:
Добавление элемента в конструктор процесса
Визуализация
Для обоих элементов описана в нотации. Что требуется проработать, так это наполнение SubProcess элементами. В библиотеке bpmn.io предоставлен механизм, позволяющий это сделать. Единственная трудность, которая может возникнуть: при разворачивании Collapsed SubProcess (и обратном сворачивании) вся схема "едет", теряя первоначальный вид.Настройки
Здесь предполагаются как стандартные настройки (например, название элемента), так и специфичные для нашей системы. Как мы уже определились выше, для SubProcess не требуется настраивать передачу данных, т.к. он имеет общий контекст с основным процессом. А вот для Call Activity необходимо как минимум выбрать сам процесс, который будет вызываться, а также настроить маппинг входящих и исходящих данных. Для этого был проработан следующий механизм: в каждом процессе в Start Event и End Event допускается выбор переменных, значения которых будут приняты из вызывающего процесса или переданы обратно (соответственно). В свою очередь в вызывающем процессе в настройках Call Activity определяем, из каких переменных и в какие будут переданы значения как на этапе вызова процесса, так и на этапе его завершения. Работа данного механизма представлена на Рис.5.Входящие/исходящие потоки
Для обоих элементов описано в нотации.Трансформация в другие элементы
Определена в bpmn-editor: элементы трансформируются в схожие по типу. Также при необходимости описывается внутренняя логика системы. Например, у нас в библиотеке компонентов движка есть не все элементы, в которые можно трансформировать элемент. Мы можем искусственно ограничить эти целевые элементы. Также можем при трансформации не сбрасывать настройки элемента, а хранить. Так если провести трансформацию Э1 → Э2 → Э1, то в Э1 восстановятся настройки. Или можем предупреждать при трансформации, что нужно изменить количество потоков и т.д.
Валидация при переводе в Активные
В нашей системе предопределены статусы процессов. Один из них — Активный. Процессы в данном статусе допускаются к выполнению. Для того, чтобы процесс был выполнен корректно, необходимо предварительно осуществить ряд проверок: заполнены обязательные поля, присутствует нужное количество входящих и исходящих потоков и прочее.Выполнение
Здесь опущу моменты, связанные напрямую с системой, а внимание уделю работе движка.
Изучая материалы по данной теме, я несколько раз встречала упоминание того, что при попадании токена в SubProcess, он должен останавливаться. Для SubProcess должен создаваться свой собственный токен. После выполнения всех действий в SubProcess его токен должен умирать, а токен основного процесса двигаться дальше.На мой взгляд создание нового токена не является обязательным условием. Взаимодействие процесса и подпроцесса могут быть выстроены так, что поток управления, переходя в SubProcess, воспринимает все содержащиеся в нём элементы просто как часть основной схемы, поэтому нет нужды создавать новый токен. SubProcess и все его активности будут активированы одним и тем же токеном. Отмечу, что управление токенами зависит от выбранного подхода в реализации исполняемых процессов и может варьироваться в разных системах. Так, например, создание дополнительного токена может потребоваться для сбора статистики по SubProcess. Но это частный случай.
Для Call Activity всё иначе. При запуске процесса создается экземпляр этого процесса. При попадании токена в Call Activity происходит вызов другого процесса. А значит, для вызванного процесса тоже должен быть создан его экземпляр. В экземпляр вызванного процесса будут переданы данные, настроенные в маппинге. Начальное событие породит свой собственный токен, который пройдет свой путь до конечного события (или иного действия, предполагающего завершение работы по экземпляру), вызванный экземпляр завершится, сообщит об этом экземпляру, который его вызвал, передаст данные, настроенные для обратного маппинга, и только после этого родительский экземпляр продолжит выполняться.
Заключение
Однажды может наступить момент, когда бизнес-процесс разрастётся до невероятных размеров. Его будет трудно читать и редактировать. Именно тогда и может возникнуть потребность в декомпозиции и в выборе подхода к ее реализации.
Лично у меня сформировалось мнение, что Call Activity играет столь же важную роль в исполняемом процессе (процессе, который подлежит автоматическому исполнения в программной среде — BPMS), как и SubProcess в неисполняемом процессе (предназначенном для визуализации и моделирования бизнес-процессов). Главное различие заключается в том, что SubProcess группирует активности в рамках одного процесса, тогда как Call Activity используется для вызова внешних, независимых процессов. Конечно, могут возникнуть различные ситуации. Но следует оценить вероятность их возникновения и трудозатраты на реализацию каждого из элементов. Возможно, удастся воспользоваться обходными путями. Для себя я определила, что на текущий момент Call Activity покрывает все известные нам потребности, поэтому пока в библиотеку компонентов добавили только его. Но считаю верным принимать решение, какой именно элемент использовать, необходимо на конкретных данных, исходя из целей и потребностей.