Why Overusing If‑Else Breaks Your Backend and How a Flow Engine Fixes It
The article explains how excessive if‑else branching in business‑centered back‑ends leads to tangled, hard‑to‑maintain code, and demonstrates how a flow‑engine combined with plugin extensions can isolate business logic, improve extensibility, and simplify testing, using the open‑source MemberClub project as a concrete example.
Problem
Backend services often accumulate long if‑else chains to handle many business scenarios. When dozens of business lines are added, the code becomes tangled, hard to understand, test, or modify without risking regressions.
Solution
Introduce a flow engine that lets each business configure its own execution chain.
Use a plugin‑extension mechanism so that only the divergent parts need custom code.
MemberClub Project
https://gitee.com/juejinwuyang/memberclub https://github.com/juejin-wuyang/memberclub
Configuring Flow Execution Chains
The class DemoMemberPurchaseExtension defines three configurable flow chains. Each membership product can bind its own chain through the UI.
Defining Flow Nodes
A flow node implements four core methods: process – main execution success – post‑success handling rollback – error recovery callback – final callback
Flow Execution Process
During execution, a FlowChain receives a context object and invokes FlowChain.execute. Nodes are processed sequentially. If a process call throws an exception, the engine triggers rollback on already‑executed nodes in reverse order. If all process calls succeed, success is invoked on each node in reverse order, followed by a final callback.
Flow Engine Implementation (FlowChain.execute)
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("Current flow:{} sent Skip, stop later execution", 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 exception, ignore 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 exception, ignore 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 exception, ignore name:{}", node.getClass().getSimpleName(), e);
}
}
if (exception != null) {
throw exception;
}
}Full source file: https://gitee.com/-/ide/project/juejinwuyang/memberclub/edit/master/-/memberclub.common/src/main/java/com/memberclub/common/flow/FlowChainService.java
Technical Stack Used in MemberClub
MyBatis‑Plus
ShardingSphere (sharding and multi‑data‑source)
Redis / Redisson
Apollo configuration center
Spring Cloud (Feign, Eureka)
RabbitMQ
H2 in‑memory database
Swagger
Lombok & MapStruct
Key Components Demonstrated
Flow engine (responsibility‑chain style execution)
Extension‑point engine for business‑specific plugins
Distributed retry component
Common logging component
Inventory management
Distributed lock component
Redis Lua scripting utilities
Spring context utility classes
Signed-in readers can open the original source through BestHub's protected redirect.
This article has been distilled and summarized from source material, then republished for learning and reference. If you believe it infringes your rights, please contactand we will review it promptly.
Top Architect
Top Architect focuses on sharing practical architecture knowledge, covering enterprise, system, website, large‑scale distributed, and high‑availability architectures, plus architecture adjustments using internet technologies. We welcome idea‑driven, sharing‑oriented architects to exchange and learn together.
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.
