Основы BPMN: моделирование процессов с событиями, шлюзами, задачами, пулами и дорожками
В этой статье дам вам полное введение в основы BPMN, включая моделирование процессов с событиями, шлюзами, задачами, пулами и дорожками с практическими примерами.
В двух словах
BPMN (Business Process Model and Notation) это стандартизированная нотация для моделирования бизнес-процессов с помощью графических элементов: событий, шлюзов, задач и swimlines.
Краткое описание
BPMN (Business Process Model and Notation) это графический стандарт для описания бизнес-процессов. Он позволяет единообразно представлять ход процессов независимо от используемого инструмента или организации.
Ключевые элементы BPMN:
События (Events)
- Start Event: начало процесса (тонкий круг)
- End Event: конец процесса (толстый круг)
- Intermediate Event: промежуточное событие (двойной круг)
- Boundary Event: граничное событие при ошибке в задаче
- Timer Event: события по расписанию
- Message Event: события, основанные на сообщениях
Задачи (Tasks)
- User Task: ручная задача, выполняемая человеком
- Service Task: автоматизированная задача
- Script Task: выполнение скрипта
- Manual Task: ручная задача без поддержки системы
- Receive Task: ожидание получения сообщения
- Send Task: отправка сообщения
Шлюзы (Gateways)
- Exclusive Gateway: исключающая развилка (X)
- Parallel Gateway: параллельное выполнение (+)
- Inclusive Gateway: включающая развилка (O)
- Complex Gateway: сложные условия
- Event Gateway: развилка, основанная на событиях
Swimlanes (Дорожки)
- Pool: контейнер процесса для одной организации
- Lane: область ответственности в пуле
- Participant: участник процесса
Ключевые моменты
- BPMN: стандартизированная нотация для моделирования процессов
- События: события процесса (начало, конец, промежуточные)
- Задачи: работы процесса (ручные, сервисные, скриптовые)
- Шлюзы: развилки процесса (исключающие, параллельные, включающие)
- Пулы и дорожки: организационное назначение (Swimlanes)
- Sequence Flow: поток процесса между элементами
- Message Flow: обмен данными между пулами
- Актуально для практики: важно для анализа и оптимизации бизнес-процессов
Основные компоненты
- События: управление процессом через события
- Задачи: выполнение шагов работы
- Шлюзы: принятие решений и развилки
- Пулы: контейнеры процессов для организаций
- Дорожки: области ответственности
- Sequence Flow: ход выполнения процесса
- Message Flow: коммуникация между процессами
- Artifacts: дополнительная информация (объекты данных, группы)
Практические примеры
1. BPMN-процесс: обработка заказа
<?xml version="1.0" encoding="UTF-8"?>
<definitions xmlns="http://www.omg.org/spec/BPMN/20100524/MODEL"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
targetNamespace="http://www.example.com/bpmn">
<!-- Процесс: обработка заказа -->
<process id="bestellprozess" name="Bestellabwicklung" isExecutable="false">
<!-- Start Event -->
<startEvent id="start_bestellung" name="Bestellung eingegangen"/>
<!-- User Task: проверка заказа -->
<userTask id="pruefe_bestellung" name="Bestellung prüfen">
<documentation>
Mitarbeiter prüft Bestellung auf Vollständigkeit und Verfügbarkeit
</documentation>
</userTask>
<!-- Exclusive Gateway: заказ корректен? -->
<exclusiveGateway id="gueltig_pruefung" name="Bestellung gültig?"/>
<!-- Service Task: проверка наличия на складе -->
<serviceTask id="pruefe_lager" name="Lagerbestand prüfen">
<documentation>
Automatisierte Prüfung der Lagerverfügbarkeit
</documentation>
</serviceTask>
<!-- Parallel Gateway: параллельная обработка -->
<parallelGateway id="parallel_start" name="Parallel starten"/>
<!-- User Task: создание счета -->
<userTask id="erstelle_rechnung" name="Rechnung erstellen">
<potentialOwner>
<resourceAssignmentExpression>
<formalExpression>finanzabteilung</formalExpression>
</resourceAssignmentExpression>
</potentialOwner>
</userTask>
<!-- Service Task: отправка товара -->
<serviceTask id="versende_ware" name="Ware versenden">
<documentation>
Automatisierter Versand über Logistiksystem
</documentation>
</serviceTask>
<!-- Parallel Gateway: объединение -->
<parallelGateway id="parallel_end" name="Zusammenführen"/>
<!-- End Event: заказ завершен -->
<endEvent id="end_erfolgreich" name="Bestellung abgeschlossen"/>
<!-- End Event: заказ отклонен -->
<endEvent id="end_abgelehnt" name="Bestellung abgelehnt"/>
<!-- Sequence Flows -->
<sequenceFlow sourceRef="start_bestellung" targetRef="pruefe_bestellung"/>
<sequenceFlow sourceRef="pruefe_bestellung" targetRef="gueltig_pruefung"/>
<sequenceFlow sourceRef="gueltig_pruefung" targetRef="pruefe_lager">
<conditionExpression xsi:type="tFormalExpression">${bestellungGueltig == true}</conditionExpression>
</sequenceFlow>
<sequenceFlow sourceRef="gueltig_pruefung" targetRef="end_abgelehnt">
<conditionExpression xsi:type="tFormalExpression">${bestellungGueltig == false}</conditionExpression>
</sequenceFlow>
<sequenceFlow sourceRef="pruefe_lager" targetRef="parallel_start"/>
<sequenceFlow sourceRef="parallel_start" targetRef="erstelle_rechnung"/>
<sequenceFlow sourceRef="parallel_start" targetRef="versende_ware"/>
<sequenceFlow sourceRef="erstelle_rechnung" targetRef="parallel_end"/>
<sequenceFlow sourceRef="versende_ware" targetRef="parallel_end"/>
<sequenceFlow sourceRef="parallel_end" targetRef="end_erfolgreich"/>
</process>
</definitions>
2. BPMN с реализацией на Java
import java.util.*;
import java.time.*;
// Движок BPMN-процессов (упрощенный вариант)
class BPMNProcessEngine {
private Map<String, BPMNElement> elements = new HashMap<>();
private Map<String, List<String>> sequenceFlows = new HashMap<>();
private Set<String> completedElements = new HashSet<>();
private Map<String, Object> processVariables = new HashMap<>();
public void addElement(BPMNElement element) {
elements.put(element.getId(), element);
}
public void addSequenceFlow(String from, String to) {
sequenceFlows.computeIfAbsent(from, k -> new ArrayList<>()).add(to);
}
public void setVariable(String name, Object value) {
processVariables.put(name, value);
}
public Object getVariable(String name) {
return processVariables.get(name);
}
public void executeProcess(String startElementId) {
System.out.println("=== Запуск BPMN-процесса ===");
executeElement(startElementId);
}
private void executeElement(String elementId) {
if (completedElements.contains(elementId)) {
return;
}
BPMNElement element = elements.get(elementId);
if (element == null) {
throw new RuntimeException("Элемент не найден: " + elementId);
}
System.out.println("\n--- Выполнение: " + element.getName() + " (" + elementId + ") ---");
// Выполнение элемента
element.execute(this);
completedElements.add(elementId);
// Поиск следующих элементов
List<String> nextElements = sequenceFlows.get(elementId);
if (nextElements != null) {
for (String nextId : nextElements) {
executeElement(nextId);
}
}
}
}
// Интерфейс элемента BPMN
interface BPMNElement {
String getId();
String getName();
void execute(BPMNProcessEngine engine);
}
// Реализация событий
class StartEvent implements BPMNElement {
private String id;
private String name;
public StartEvent(String id, String name) {
this.id = id;
this.name = name;
}
@Override
public String getId() { return id; }
@Override
public String getName() { return name; }
@Override
public void execute(BPMNProcessEngine engine) {
System.out.println("Процесс начат: " + name);
engine.setVariable("startTime", LocalDateTime.now());
}
}
class EndEvent implements BPMNElement {
private String id;
private String name;
public EndEvent(String id, String name) {
this.id = id;
this.name = name;
}
@Override
public String getId() { return id; }
@Override
public String getName() { return name; }
@Override
public void execute(BPMNProcessEngine engine) {
System.out.println("Процесс завершен: " + name);
engine.setVariable("endTime", LocalDateTime.now());
Duration duration = Duration.between(
(LocalDateTime) engine.getVariable("startTime"),
(LocalDateTime) engine.getVariable("endTime")
);
System.out.println("Длительность процесса: " + duration.toSeconds() + " секунд");
}
}
// Реализация задач
class UserTask implements BPMNElement {
private String id;
private String name;
private String assignee;
public UserTask(String id, String name, String assignee) {
this.id = id;
this.name = name;
this.assignee = assignee;
}
@Override
public String getId() { return id; }
@Override
public String getName() { return name; }
@Override
public void execute(BPMNProcessEngine engine) {
System.out.println("Задача назначена: " + assignee);
System.out.println("Описание: " + name);
// Имитация действий пользователя
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
}
System.out.println("Задача выполнена");
engine.setVariable("userTask_" + id + "_completed", true);
}
}
class ServiceTask implements BPMNElement {
private String id;
private String name;
private String serviceClass;
public ServiceTask(String id, String name, String serviceClass) {
this.id = id;
this.name = name;
this.serviceClass = serviceClass;
}
@Override
public String getId() { return id; }
@Override
public String getName() { return name; }
@Override
public void execute(BPMNProcessEngine engine) {
System.out.println("Service Task: " + name);
System.out.println("Класс сервиса: " + serviceClass);
// Имитация вызова сервиса
if (serviceClass.equals("LagerService")) {
boolean verfuegbar = checkLagerverfuegbarkeit(engine);
engine.setVariable("lagerVerfuegbar", verfuegbar);
System.out.println("Товар в наличии: " + verfuegbar);
} else if (serviceClass.equals("RechnungService")) {
String rechnungsNummer = generateRechnung(engine);
engine.setVariable("rechnungsNummer", rechnungsNummer);
System.out.println("Счет создан: " + rechnungsNummer);
}
}
private boolean checkLagerverfuegbarkeit(BPMNProcessEngine engine) {
// Имитация проверки наличия
return Math.random() > 0.3; // 70% вероятность наличия
}
private String generateRechnung(BPMNProcessEngine engine) {
return "RG-" + System.currentTimeMillis();
}
}
// Реализация шлюзов
class ExclusiveGateway implements BPMNElement {
private String id;
private String name;
private Map<String, String> conditions;
public ExclusiveGateway(String id, String name) {
this.id = id;
this.name = name;
this.conditions = new HashMap<>();
}
public void addCondition(String targetId, String condition) {
conditions.put(targetId, condition);
}
@Override
public String getId() { return id; }
@Override
public String getName() { return name; }
@Override
public void execute(BPMNProcessEngine engine) {
System.out.println("Exclusive Gateway: " + name);
// Проверка условия
boolean bestellungGueltig = (boolean) engine.getVariable("bestellungGueltig");
System.out.println("Условие 'bestellungGueltig': " + bestellungGueltig);
// Принятие решения
if (bestellungGueltig) {
engine.setVariable("gateway_decision_" + id, "gueltig");
} else {
engine.setVariable("gateway_decision_" + id, "ungueltig");
}
}
}
class ParallelGateway implements BPMNElement {
private String id;
private String name;
public ParallelGateway(String id, String name) {
this.id = id;
this.name = name;
}
@Override
public String getId() { return id; }
@Override
public String getName() { return name; }
@Override
public void execute(BPMNProcessEngine engine) {
System.out.println("Parallel Gateway: " + name);
if (name.contains("starten")) {
System.out.println("Параллельное выполнение запущено");
engine.setVariable("parallel_branches_active", true);
} else {
System.out.println("Параллельное выполнение завершено");
engine.setVariable("parallel_branches_active", false);
}
}
}
// Демонстрация BPMN
public class BPMDemo {
public static void main(String[] args) {
System.out.println("=== Демо моделирования BPMN ===");
// Создание движка процессов
BPMNProcessEngine engine = new BPMNProcessEngine();
// Создание элементов BPMN
StartEvent start = new StartEvent("start_bestellung", "Bestellung eingegangen");
UserTask pruefung = new UserTask("pruefe_bestellung", "Bestellung prüfen", "sachbearbeiter");
ExclusiveGateway gueltigCheck = new ExclusiveGateway("gueltig_pruefung", "Bestellung gültig?");
ServiceTask lagerPruefung = new ServiceTask("pruefe_lager", "Lagerbestand prüfen", "LagerService");
ParallelGateway parallelStart = new ParallelGateway("parallel_start", "Parallel starten");
UserTask rechnung = new UserTask("erstelle_rechnung", "Rechnung erstellen", "finanzabteilung");
ServiceTask versand = new ServiceTask("versende_ware", "Ware versenden", "VersandService");
ParallelGateway parallelEnd = new ParallelGateway("parallel_end", "Zusammenführen");
EndEvent endErfolgreich = new EndEvent("end_erfolgreich", "Bestellung abgeschlossen");
EndEvent endAbgelehnt = new EndEvent("end_abgelehnt", "Bestellung abgelehnt");
// Добавление элементов в движок
engine.addElement(start);
engine.addElement(pruefung);
engine.addElement(gueltigCheck);
engine.addElement(lagerPruefung);
engine.addElement(parallelStart);
engine.addElement(rechnung);
engine.addElement(versand);
engine.addElement(parallelEnd);
engine.addElement(endErfolgreich);
engine.addElement(endAbgelehnt);
// Определение последовательности действий
engine.addSequenceFlow("start_bestellung", "pruefe_bestellung");
engine.addSequenceFlow("pruefe_bestellung", "gueltig_pruefung");
// Условные переходы для Exclusive Gateway
engine.addSequenceFlow("gueltig_pruefung", "pruefe_lager");
engine.addSequenceFlow("gueltig_pruefung", "end_abgelehnt");
engine.addSequenceFlow("pruefe_lager", "parallel_start");
engine.addSequenceFlow("parallel_start", "erstelle_rechnung");
engine.addSequenceFlow("parallel_start", "versende_ware");
engine.addSequenceFlow("erstelle_rechnung", "parallel_end");
engine.addSequenceFlow("versende_ware", "parallel_end");
engine.addSequenceFlow("parallel_end", "end_erfolgreich");
// Установка переменных процесса
engine.setVariable("bestellungGueltig", true);
// Запуск процесса
engine.executeProcess("start_bestellung");
// Статистика процесса
System.out.println("\n=== Статистика процесса ===");
System.out.println("Завершенных элементов: " + engine.completedElements.size());
// Второй запуск с некорректным заказом
System.out.println("\n=== Второй запуск (некорректный заказ) ===");
BPMNProcessEngine engine2 = new BPMNProcessEngine();
// Добавление элементов еще раз
Arrays.asList(start, pruefung, gueltigCheck, endAbgelehnt).forEach(engine2::addElement);
engine2.addSequenceFlow("start_bestellung", "pruefe_bestellung");
engine2.addSequenceFlow("pruefe_bestellung", "gueltig_pruefung");
engine2.addSequenceFlow("gueltig_pruefung", "end_abgelehnt");
engine2.setVariable("bestellungGueltig", false);
engine2.executeProcess("start_bestellung");
}
}
3. Объекты данных BPMN и артефакты
// BPMN-объекты данных
class DataObject {
private String id;
private String name;
private Object value;
private String dataType;
public DataObject(String id, String name, String dataType) {
this.id = id;
this.name = name;
this.dataType = dataType;
}
// Getter и Setter
public String getId() { return id; }
public String getName() { return name; }
public Object getValue() { return value; }
public void setValue(Object value) { this.value = value; }
public String getDataType() { return dataType; }
@Override
public String toString() {
return "DataObject{" + name + "=" + value + " (" + dataType + ")}";
}
}
// BPMN-группа
class BPMNGroup {
private String id;
private String name;
private List<String> elementIds;
private String categoryValue;
public BPMNGroup(String id, String name, String categoryValue) {
this.id = id;
this.name = name;
this.categoryValue = categoryValue;
this.elementIds = new ArrayList<>();
}
public void addElement(String elementId) {
elementIds.add(elementId);
}
// Getter
public String getId() { return id; }
public String getName() { return name; }
public List<String> getElementIds() { return new ArrayList<>(elementIds); }
public String getCategoryValue() { return categoryValue; }
}
// BPMN-текстовая аннотация
class TextAnnotation {
private String id;
private String text;
private String format;
public TextAnnotation(String id, String text) {
this.id = id;
this.text = text;
this.format = "text/plain";
}
// Getter
public String getId() { return id; }
public String getText() { return text; }
public String getFormat() { return format; }
}
// Расширенный BPMN-движок с объектами данных
class AdvancedBPMNEngine extends BPMNProcessEngine {
private Map<String, DataObject> dataObjects = new HashMap<>();
private Map<String, BPMNGroup> groups = new HashMap<>();
private Map<String, TextAnnotation> annotations = new HashMap<>();
public void addDataObject(DataObject dataObject) {
dataObjects.put(dataObject.getId(), dataObject);
}
public void addGroup(BPMNGroup group) {
groups.put(group.getId(), group);
}
public void addAnnotation(TextAnnotation annotation) {
annotations.put(annotation.getId(), annotation);
}
public DataObject getDataObject(String id) {
return dataObjects.get(id);
}
public void setDataObjectValue(String id, Object value) {
DataObject dataObject = dataObjects.get(id);
if (dataObject != null) {
dataObject.setValue(value);
}
}
public void printProcessInfo() {
System.out.println("\n=== Информация о процессе ===");
System.out.println("\nОбъекты данных:");
dataObjects.values().forEach(System.out::println);
System.out.println("\nГруппы:");
groups.values().forEach(group -> {
System.out.println(group.getName() + " (" + group.getCategoryValue() + "): " +
group.getElementIds());
});
System.out.println("\nАннотации:");
annotations.values().forEach(annotation ->
System.out.println(annotation.getText()));
}
}
// Демонстрация расширенных функций BPMN
public class AdvancedBPMDemo {
public static void main(String[] args) {
System.out.println("=== Расширенная демонстрация BPMN ===");
AdvancedBPMNEngine engine = new AdvancedBPMNEngine();
// Элементы BPMN
StartEvent start = new StartEvent("start_antrag", "Заявка получена");
UserTask pruefung = new UserTask("pruefe_antrag", "Проверить заявку", "sachbearbeiter");
ServiceTask pruefungService = new ServiceTask("automatische_pruefung",
"Автоматическая проверка",
"PruefService");
EndEvent endGenehmigt = new EndEvent("end_genehmigt", "Заявка одобрена");
EndEvent endAbgelehnt = new EndEvent("end_abgelehnt", "Заявка отклонена");
// Добавить элементы
Arrays.asList(start, pruefung, pruefungService, endGenehmigt, endAbgelehnt)
.forEach(engine::addElement);
// Объекты данных
DataObject antragData = new DataObject("antrag_daten", "Данные заявки", "Antrag");
DataObject pruefungsErgebnis = new DataObject("pruefung_ergebnis",
"Результат проверки",
"Boolean");
engine.addDataObject(antragData);
engine.addDataObject(pruefungsErgebnis);
// Группа для процесса проверки
BPMNGroup pruefungsGruppe = new BPMNGroup("pruefungsgruppe",
"Процесс проверки",
"Проверка");
pruefungsGruppe.addElement("pruefe_antrag");
pruefungsGruppe.addElement("automatische_pruefung");
engine.addGroup(pruefungsGruppe);
// Аннотация
TextAnnotation hinweis = new TextAnnotation("hinweis",
"Важно: все проверки должны быть задокументированы");
engine.addAnnotation(hinweis);
// Sequence Flows
engine.addSequenceFlow("start_antrag", "pruefe_antrag");
engine.addSequenceFlow("pruefe_antrag", "automatische_pruefung");
engine.addSequenceFlow("automatische_pruefung", "end_genehmigt");
// Инициализировать объекты данных
engine.setDataObjectValue("antrag_daten", "Заявка #12345");
engine.setDataObjectValue("pruefung_ergebnis", true);
// Выполнить процесс
engine.executeProcess("start_antrag");
// Вывести информацию о процессе
engine.printProcessInfo();
}
}
Обзор элементов BPMN
События
| Тип | Символ | Описание | Пример |
|---|---|---|---|
| Start Event | Круг (тонкий) | Начало процесса | Заказ получен |
| End Event | Круг (толстый) | Конец процесса | Заказ завершён |
| Intermediate Event | Круг (двойной) | Промежуточное событие | Таймер сработал |
| Boundary Event | Круг (прикрепленный) | Событие ошибки | Timeout при задаче |
| Message Event | Конверт | Сообщение | Сообщение получено |
| Timer Event | Часы | На основе времени | Время ожидания истекло |
Задачи
| Тип | Символ | Описание | Пример |
|---|---|---|---|
| User Task | Прямоугольник с персоной | Ручная задача | Заполнить форму |
| Service Task | Прямоугольник со звёздочкой | Автоматизированная задача | Сохранить в БД |
| Script Task | Прямоугольник со скриптом | Выполнение скрипта | Выполнить вычисление |
| Manual Task | Прямоугольник с рукой | Ручная работа без IT | Упаковать посылку |
| Receive Task | Прямоугольник с письмом | Ожидать сообщение | Ждать подтверждение |
| Send Task | Прямоугольник с письмом | Отправить сообщение | Отправить письмо |
Gateways (Ветвления)
| Тип | Символ | Описание | Пример |
|---|---|---|---|
| Exclusive Gateway | Ромб (X) | Исключающее ветвление | Да/Нет решение |
| Parallel Gateway | Ромб (+) | Параллельное исполнение | Проверка одновременно |
| Inclusive Gateway | Ромб (O) | Включающее ветвление | Несколько условий |
| Complex Gateway | Ромб (*) | Сложная логика | Множественные условия |
Swimlanes (Дорожки)
| Элемент | Описание | Применение |
|---|---|---|
| Pool | Контейнер процесса | Весь процесс организации |
| Lane | Область ответственности | Отдел или роль |
| Participant | Внешний партнер | Клиент, поставщик |
BPMN XML структура
Базовая структура
<definitions xmlns="http://www.omg.org/spec/BPMN/20100524/MODEL">
<process id="prozess_id" name="Prozessname">
<!-- BPMN-Elemente -->
<startEvent id="start" name="Start"/>
<sequenceFlow sourceRef="start" targetRef="task1"/>
<userTask id="task1" name="Aufgabe"/>
<endEvent id="end" name="Ende"/>
</process>
</definitions>
Расширенная структура
<definitions>
<process id="prozess">
<!-- Pools и Lanes -->
<participant id="participant1" name="Organisation"/>
<lane id="lane1" name="Abteilung">
<flowNodeRef>task1</flowNodeRef>
</lane>
<!-- Datenobjekte -->
<dataObject id="data1" name="Daten" itemSubjectRef="itemDef1"/>
<!-- Artifacts -->
<textAnnotation id="annotation1">
<text>Hinweis</text>
</textAnnotation>
</process>
</definitions>
Лучшие практики BPMN
Проектирование процессов
- Ясность: держите процессы простыми и понятными
- Консистентность: используйте единообразные обозначения и названия
- Полнота: моделируйте все значимые пути выполнения
- Валидация: регулярно проверяйте модели
Соглашения об именовании
- ID элементов: технические идентификаторы без пробелов
- Названия элементов: понятные описания для человека
- Переменные процесса: CamelCase с технической направленностью
- Объекты данных: описательные названия с указанием типа данных
Оптимизация производительности
- Параллелизация: используйте возможности параллельного выполнения
- Автоматизация: минимизируйте ручные задачи
- Упрощение: избегайте лишних ветвлений
- Переиспользование: применяйте подпроцессы для повторяющихся операций
Преимущества и недостатки
Преимущества BPMN
- Стандартизация: единообразная нотация во всём мире
- Инструментальная поддержка: много BPMN инструментов
- Автоматизация: прямое преобразование в BPM системы
- Коммуникация: общее понимание всеми заинтересованными лицами
- Анализ: систематическое улучшение процессов
Недостатки
- Сложность: кривая обучения для сложных процессов
- Затраты: подробное моделирование требует времени
- Интерпретация: разные инструменты могут отличаться
- Поддержка: модели нужно актуализировать
Часто встречающиеся вопросы
-
В чём отличие между Pool и Lane? Pool это весь контейнер процесса, Lane это область ответственности внутри Pool.
-
Объясните разные типы Gateway! Exclusive (исключающее), Parallel (параллельное), Inclusive (с несколькими условиями), Complex (сложная логика).
-
Когда использовать User Task вместо Service Task? User Task для ручных операций, выполняемых пользователем, Service Task для автоматизированных системных операций.
-
Какова цель объектов данных BPMN? Представление информации, которая передаётся и обрабатывается в процессе.
Основные источники
- https://www.bpmn.org/
- https://www.omg.org/spec/BPMN/2.0/
- https://de.wikipedia.org/wiki/Business_Process_Model_and_Notation
Другие статьи про BPMN
BPMN это стандарт моделирования бизнес процессов. Следующие статьи помогут разобраться во всех аспектах BPMN и применять его на практике.
Основы и концепции
- BPMN Business Process Model and Notation - Полное введение в BPMN и моделирование процессов
- BPMN Grundlagen Prozessmodellierung - Подробное объяснение элементов и концепций BPMN



