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.

Top Architect
Top Architect
Top Architect
Escape the if‑else Nightmare with Powerful Workflow Orchestration

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.

Flow configuration screenshot
Flow configuration screenshot

Defining Flow Nodes

Each node implements four lifecycle methods:

process
success
rollback
callback

The engine invokes these methods during execution, separating business logic, success handling, compensation, and final callbacks.

Node definition screenshot
Node definition screenshot

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.

Original Source

Signed-in readers can open the original source through BestHub's protected redirect.

Sign in to view source
Republication Notice

This article has been distilled and summarized from source material, then republished for learning and reference. If you believe it infringes your rights, please contactadmin@besthub.devand we will review it promptly.

JavaOpen-sourceSpringBootprocess engineworkflow orchestrationcode isolationMemberClub
Top Architect
Written by

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.

0 followers
Reader feedback

How this landed with the community

Sign in to like

Rate this article

Was this worth your time?

Sign in to rate
Discussion

0 Comments

Thoughtful readers leave field notes, pushback, and hard-won operational detail here.