Escape the if‑else Nightmare with Powerful Workflow Orchestration
The article explains how tangled if‑else branches in a business middle‑platform can be replaced by a flow‑engine and plugin‑extension approach, using the open‑source MemberClub project to demonstrate configuration, node definition, and execution mechanics that improve code isolation and extensibility.
Problem
When a middle‑platform serves dozens of business lines, developers often accumulate large if‑else blocks. Adding a new business requires editing the same tangled code, increasing the risk of regressions and online failures.
Solution
Introduce a dedicated flow engine that isolates business logic into independent flow nodes and configures a separate execution chain for each business scenario. A plugin‑extension engine provides the differentiated implementation for each business.
Example Project – MemberClub
The open‑source MemberClub project (hosted on Gitee) demonstrates both techniques. It implements a paid‑membership transaction solution and contains the flow‑engine implementation.
https://gitee.com/juejinwuyang/memberclub
https://gitee.com/-/ide/project/juejinwuyang/memberclub/edit/master/-/memberclub.common/src/main/java/com/memberclub/common/flow/FlowChainService.java
Configuring a Flow Execution Chain
Different membership products require different transaction flows. The class DemoMemberPurchaseExtension implements a purchase extension point and registers three execution‑chain configurations.
Defining Flow Nodes
Each node implements four lifecycle methods:
process success rollback callbackThe engine invokes these methods during execution, separating business logic, success handling, compensation, and final callbacks.
Flow Execution Process
Execution starts by creating a context object and calling FlowChain.execute. The engine iterates over the nodes, invoking process. If an exception occurs, the loop breaks and rollback is executed for all already‑processed nodes in reverse order. If no exception occurs, success is executed for each node in reverse order, followed by callback for every node.
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 request, stop further 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 error, 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 error, 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 error, ignore name:{}", node.getClass().getSimpleName(), e);
}
}
if (exception != null) {
throw exception;
}
}Effect
By isolating business logic into independent flow nodes and configuring execution chains per business, the approach eliminates sprawling if‑else structures, simplifies testing, and reduces the chance of accidental regressions when adding new business scenarios.
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.
