Пример динамического конструирования схемы Workflow
В комментариях к предыдущему посту Михаил Романов попросил привести пример, демонстрирующий преимущества подхода. Рассмотрим следующий, совершенно типичный, фрагмент схемы:
В комментариях к предыдущему посту Михаил Романов попросил привести пример, демонстрирующий преимущества подхода. Рассмотрим следующий, совершенно типичный, фрагмент схемы:
В этом фрагменте присутствует цикл по согласованию, который выполняется только в том случае, если Исполнитель и Руководитель – это разные пользователи. Сложность восприятия этого цикла связана с:
● Избыточностью для человека условия Надо согласовывать? – это техническое условие, которое необходимо добавлять явно, хотя оно и очевидно для человека. Действительно, если я сам подготовил документ, то с самим собой мне его согласовывать не нужно.
● Наличием двух веток, выходящих из цикла – это тем большая проблема, чем больше схема, т.к. каждое ветвление, да еще и в цикле, усложняет отслеживание потоков управления в схеме.
Посмотрим, что изменится, если этот фрагмент будет определен конструктивным правилом: «На этапе конструирования схемы проверить: если Исполнитель и Руководитель являются разными пользователями, то добавить цикл по согласованию».
Для тех экземпляров процесса, где Исполнитель и Руководитель – это разные пользователи, соответствующий фрагмент схемы будет выглядеть вот так:
А там, где Исполнитель и Руководитель совпадают, еще проще:
Думаю, упрощение рассматриваемого фрагмента схемы заметно невооруженным глазом.
Однако, в этом месте я должен вернуться к исходному своему вопросу: каким должен быть язык конструктивных правил, чтобы эта красота могла быть применимой на практике?
Комментарии 8
- которое надо учитывать при чтении схемы.
Без этого правила схема читается как "Всегда от исполнителя передавать руководителю без дополнительных условий".
В общем, пока не очевидно (либо я продолжаю чего-то недопонимать)
Вот я постоянно ворчу, что от всех этих блок-схем и BPMN-ов сплошные проблемы.
Предлагаю использовать другой подход. Любой workflow можно задать набором работ и переходов между ними (Ну, не любой, конечно, а только однопотоковый, т.е. без параллельных работ. Но, сейчас, это не важно. Суть не изменится.) В графе из работ и переходов между ними выделяем кратчайший путь и называем его основной поток работ (в других источниках: типичный ход событий или же happy path). В каждой вершине, допускающей ветвление организуем вызов ruleengine для проверки допустимости перехода к следующей работе, лежащей на основном потоке работ. Если условие не выполняется, то генерим исключение. Обработчик исключения запускает поток обработки этого исключения, который рано или поздно либо вернет процесс в основной поток(в некоторую из точек потока) либо завершит его. Далее действуем рекурсивно, т.е. выделяем в обработчике его основной поток, из которого могут быть исключения и т.д., пока граф не закончится. Одним словом, идея заключается в том, чтоб из графа сделать набор линейных потоков. В описанном выше примере последняя картинка – основной поток работ (т.к. он самый короткий). Единственная работа в нем завершается проверкой правила «Исполнитель-Руководитель». Если правило не срабатывает, то бросаем exeption«требуется утверждение». Обработчик этого исключения состоит из одной работы руководителя «утвердить» и правила «утверждено». Если, при выходе из этой работы правило истинно, то возвращаемся в основной сценарий в точку, расположенную после активности из квадратика «руководитель». Если и здесь сработало исключение, то возвращаемся в квадратик «руководитель». Если описать это текстом, в формате аля Алистер Коберн (см. у меня в блоге http://wp.me/pRljZ-4r ), то выглядеть это будет примерно так:
Основной сценарий:
1. Пишем документ
2. Исполнитель является руководителем
3. Завершаем основной сценарий
Исключения:
2*: Исполнитель не является руководителем
2.1 Руководитель утверждает документ
2.2 Переходим к п.3 основного сценария
--
2.1*: Руководитель отклоняет документ
2.1.1 Переходим к п. 1 основного сценария
Максим, у этого подхода я вижу только одно преимущество: наглядно виден основной поток работ. Но и с ним не все гладко, даже на приведенном здесь примере. Кратчайший путь, это "Написать документ-Завершить". Но типичным путем здесь чаще всего является "Написать документ-Согласовать-Завершить". Для программиста это не страшно, но рискну предположить, что для бизнес-пользователя, который рецензирует текстовое описание процесса, это может быть не очевидным моментом. Хотя, в принципе, это мелочь.
Но есть и существенный, на мой взгляд, недостаток (помимо тех, что приводили по ссылке): совершенно непрозрачная система передачи управления.
Если список имеет исключения, то чтобы просто понять, куда вернется управление после обработки исключения, необходимо просмотреть обработчики исключений на всю глубину. Делать это на нумерованных списках однозначно сложнее, чем на визуальных схемах. Сравните, например: "2.2 Переходим к п.3 основного сценария" и соответствующую стрелку на самой первой картинке в посте.
А каково будет читателю, если вложенность исключений будет в 3-5 уровней (что соответствует достаточно средненькой схеме)? А делать это придется хотя бы для того, чтобы проверить, выполняются ли текущие требования регламентов - ведь обработка многих из них уйдет в "исключения" данной нотации.
С другой стороны, подход однозначно хорош там, где много действий, но мало условий. Кстати, именно в Use Cases это оправданно, т.к. каждый Use Case - это частный случай, который по определению не имеет много ветвлений. В то время как в Workflow-схемах стремятся все частные случаи протекания процесса свести в общую схему (это до некоторой степени спорный подход, но он есть).
Кстати, нечто подобное предлагал Артем Горбунов: http://artgorbunov.ru/bb/soviet/20080221/