Applying a Flow Engine and Plugin Extension Engine for Business Isolation and Extensibility in Backend Systems
The article explains why over‑designing with workflow orchestration is harmful, introduces a flow‑engine and plugin‑extension approach to achieve clean code isolation and easy business extension, and provides concrete Java examples from the open‑source MemberClub project.
As an excellent programmer, you must keep the professional bottom line: tasks that can be done simply and quickly should be solved with a simple solution, avoiding over‑design and keeping the system concise.
I used to scoff at workflow orchestration, considering it typical over‑design.
In my view, the more straightforward the code, the more reliable; I dislike code that jumps around. With workflow orchestration, you must place each method into extension classes, combine them into a workflow to achieve business functionality—what benefit does this bring?
It wasn’t until I joined a middle‑platform team that I realized workflow orchestration is a life‑saving capability.
The business middle platform must integrate many business parties, each not exactly the same; often you cannot fully reuse code and need to adapt the system for new business.
When adding new business code, you must ensure existing business is unaffected; without workflow orchestration, the code is filled with numerous if‑else branches.
if (biz == BizA || biz == BizB) {
//do some thing
//这部分逻辑相同
if (biz == BizA) {
//差异化处理
}
}
if (biz == BizB) {
//差异化逻辑
}For example, the above code requires separate branches for each business line’s differentiated logic. Imagine more than ten businesses integrated into your system—it becomes maddening.
No one can be familiar with all ten‑plus businesses; each developer may only handle one. Without code isolation, maintainers must sift through tangled code to locate the target logic. Worse, each new business adds more if‑else, creating a "shit mountain"; a single mistake can affect other important services and cause online failures.
Imagine after changing a few lines of code you have to ask testers to regress all ten‑plus business lines—clearly unrealistic.
The problems can be summarized as code isolation and business extension point issues. The solutions are:
Use a flow engine to configure different execution chains for each business.
Use a plugin‑extension engine to implement business‑specific parts.
MemberClub heavily uses a flow engine and plugin‑extension engine to solve business isolation and extensibility problems. MemberClub is an open‑source project hosted on Gitee that provides paid‑membership transaction solutions, handling various purchase scenarios, fulfillment, and after‑sale settlement.
Configuring Flow Execution Chains
Considering that different membership products have different order‑submission processes, each product should configure a distinct flow. The DemoMemberPurchaseExtension implements a purchase extension point and defines three flow‑chain configurations.
Defining Flow Nodes
Methods in a flow node include process , success , rollback and callback .
Flow Execution
During execution, a flow context object is provided. Calling the FlowChain.execute method runs the chain.
The execution stage strings together each flow node like a responsibility‑chain pattern. Nodes are executed in order, invoking process . If process throws an exception, rollback is called; otherwise, after all process calls succeed, success is invoked in reverse order, followed by callback .
Flow Engine Execution Principle
Below is the implementation of the FlowChain.execute method.
public <T> void execute(FlowChain<T> chain, T context) {
Exception exception = null;
int index = -1;
for (FlowNode<T> node : chain.getNodes()) {
try {
node.process(context);
index++;
} catch (Exception e) {
if (e instanceof SkipException) {
CommonLog.warn("当前流程:{} 发出 Skip请求,后续流程不再执行", node.getClass().getSimpleName());
break;
}
exception = e;
break;
}
}
if (exception != null) {
for (int i = index; i >= 0; i--) {
FlowNode<T> node = chain.getNodes().get(i);
try {
node.rollback(context, exception);
} catch (Exception e) {
CommonLog.error("rollback执行异常,忽略 name:{}", node.getClass().getSimpleName(), e);
}
}
} else {
for (int i = index; i >= 0; i--) {
FlowNode<T> node = chain.getNodes().get(i);
try {
node.success(context);
} catch (Exception e) {
CommonLog.error("success 执行异常,忽略 name:{}", node.getClass().getSimpleName(), e);
}
}
}
for (int i = index; i >= 0; i--) {
FlowNode<T> node = chain.getNodes().get(i);
try {
node.callback(context, exception);
} catch (Exception e) {
CommonLog.error("callback执行异常,忽略 name:{}", node.getClass().getSimpleName(), e);
}
}
if (exception != null) {
throw exception;
}
}The full source code can be found in the MemberClub repository.
https://gitee.com/-/ide/project/juejinwuyang/memberclub/edit/master/-/memberclub.common/src/main/java/com/memberclub/common/flow/FlowChainService.java
MemberClub is an open‑source project on Gitee that provides paid‑membership transaction solutions, supporting various purchase scenarios, fulfillment, and after‑sale settlement. It is an excellent project for learning business middle‑platform systems.
Open‑source addresses:
Gitee: https://gitee.com/juejinwuyang/memberclub
GitHub: https://github.com/juejin-wuyang/memberclub
The project integrates many frameworks and components such as MyBatis‑Plus, ShardingSphere, Redis/Redisson, Apollo, Spring Cloud (Feign/Eureka), RabbitMQ, H2, Swagger, Lombok, MapStruct, and demonstrates implementations of a flow engine, extension‑point engine, distributed retry component, generic logging component, inventory management, distributed lock, Redis Lua usage, and Spring context utilities.
Backend Technical Community Invitation
Build a high‑quality technical communication community; developers, recruiters, and anyone interested are welcome to join, share job referrals, and help each other improve.
文明发言,以 交流技术 、 职位内推 、 行业探讨 为主
Advertisement‑free zone: do not trust private messages, avoid scams.
Add me as a friend and I will invite you to the group.
Click the ❤ below to support us, thank you!
Selected Java Interview Questions
A professional Java tech channel sharing common knowledge to help developers fill gaps. Follow us!
How this landed with the community
Was this worth your time?
0 Comments
Thoughtful readers leave field notes, pushback, and hard-won operational detail here.