Backend Development 21 min read

State Machine Selection and Refactoring Strategies for Complex Business Scenarios

This article analyzes the problem of exploding state‑branch logic in merchant onboarding and exit flows, presents decoupling, design‑pattern, and state‑machine solutions, compares three Java state‑machine implementations (Zhuozhou, Cola, Spring Statemachine), and offers practical selection guidance for simple to highly complex B2B use cases.

Zhuanzhuan Tech
Zhuanzhuan Tech
Zhuanzhuan Tech
State Machine Selection and Refactoring Strategies for Complex Business Scenarios

Problem Background

The product team received feedback that the app lacked an online deposit‑refund feature, and the merchant onboarding process now includes many states (e.g., not onboarded, pending, onboarded, exiting, exited) with numerous sub‑states, making the code hard to maintain and extend.

A simplified flow diagram of the account‑closure process is shown below:

How to Solve the State‑Management Problem

During iterative development, the codebase can become a "mountain of shit" if state handling is not refactored.

2.1 Decoupling and Refactoring

Early in the project, when states are few, extracting responsibilities into separate methods solves the problem. The following example shows the before‑and‑after refactoring.

重构前 :入驻方法很长,所有业务代码逻辑耦合在一起。

class A {
//入驻方法
public void join() {
if(未入驻过){
// 实人认证
//查询关联账号
...//其他业务逻辑
}
else if(曾入驻过){
//查询关联账号
//计算售后率
...//其他业务逻辑
}
}
}

重构后 :提取出实人认证、计算售后率等方法。

class A {
//入驻方法
public void join() {
if(未入驻过){
// 实人认证
realPersonAuthentication();
...//其他业务逻辑
}
else if(曾入驻过){
//计算售后率
calculatingAfterSalesRate();
...//其他业务逻辑
}
//查询关联账号
associatedAccount();
}
public void realPersonAuthentication() {
// 实人认证
}
public void associatedAccount() {
//查询关联账号
}
public void calculatingAfterSalesRate() {
//计算售后率
}
}

2.2 Using Design Patterns

Applying the State pattern or Strategy pattern makes the code clearer. For example, merchant permissions depend on the current onboarding state, and complex transition rules can be expressed without a flood of if‑else statements.

The business rules are illustrated in the following diagram:

The class diagram of the State pattern is also shown:

2.3 Using a State Machine

When the number of states and transition logic become large, a dedicated state‑machine framework helps manage complexity.

2.3.1 Characteristics of a State Machine

1) All states are abstracted from the business layer for unified maintenance. 2) Transition rules are defined centrally (configuration files, code, or database). 3) The rules themselves are also centrally maintained, making the overall flow easier to understand and extend.

State Machine Introduction

A state machine consists of four core concepts: State, Event, Action, and Transition.

3.1 Four Core Concepts

State : Represents a condition such as "未入驻", "已入驻", "清退中" etc.

Event : The trigger that causes a transition, e.g., "申请关户".

Action : The operation executed when an event occurs, typically a method or class.

Transition : The rule that links a source state, an event, and a target state, optionally executing an Action.

3.2 Advantages of a State Machine

1) Clear state management : Centralized configuration reduces errors. 2) Easy maintenance and extensibility : Adding or modifying states does not affect unrelated code. 3) Improved team communication : Visual diagrams help non‑technical stakeholders understand the flow.

State Machine Comparison and Selection

The following three implementations are compared:

4.1 Zhuozhou State Machine

Loads transition rules from MySQL into a Map and executes actions based on the current state and event.

public class FsmNode {
private Integer opType;
private Integer role;
private Integer sourceStatus;
private Integer targetStatus;
private NodeType nodeType;
private FsmAction action;
private HashSet<JobConfig> jobConfigs;
private HashSet<TransactionConfig> transactionConfigs;
}

Key features: configuration stored in DB, periodic retry via scheduled tasks, stateless design, supports transactional messages.

4.2 Cola State Machine

A lightweight open‑source framework that combines the State pattern with two Maps.

Core code example:

StateMachine<States, Events, Context> stateMachine = builder.build(MACHINE_ID+"1");
//触发一次事件代码
States target = stateMachine.fireEvent(States.STATE2, Events.EVENT1, new Context());

Features: simple, stateless, high performance, suitable for medium‑size projects.

4.3 Spring Statemachine

Provides a rich feature set, including hierarchical states, parallel states, and sub‑state machines, tightly integrated with the Spring ecosystem.

private Flux<StateMachineEventResult<S, E>> handleEvent(Message<E> message) {
if (hasStateMachineError()) {
return Flux.just(StateMachineEventResult.<S, E>from(this, message, ResultType.DENIED));
}
return Mono.just(message)
.map(m -> getStateMachineInterceptors().preEvent(m, this))
.flatMapMany(m -> acceptEvent(m))
.onErrorResume(error -> Flux.just(StateMachineEventResult.<S, E>from(this, message, ResultType.DENIED)))
.doOnNext(notifyOnDenied());
}

Features: comprehensive, supports reactive programming (Mono, Flux), suitable for highly complex workflows.

Selection Summary

Feature

Cola State Machine

Spring State Machine

Zhuozhou State Machine

Integration

Independent, easy to embed in Java projects

Tight Spring integration, leverages DI, AOP, etc.

Database‑driven, easy to embed

Feature Richness

Basic state/transition support

Full‑featured: hierarchical, parallel, sub‑machines

Basic with retry and transactional message support

Learning Curve

Low

High (reactive model)

Low

Typical Use Cases

Small‑to‑medium projects needing lightweight management

Complex state logic, Spring‑centric applications

Projects with many configuration‑driven transitions

For simple business logic, Cola is recommended; for complex, hierarchical or high‑concurrency scenarios, Spring Statemachine is preferred; for highly customized or DB‑driven needs, Zhuozhou (转转) is a solid choice.

Conclusion

The article demonstrates how to refactor tangled state‑branch code by decoupling, applying design patterns, and finally adopting a state‑machine framework. Selecting the right implementation depends on project size, complexity, and integration requirements.

References: [1] https://github.com/alibaba/COLA [2] https://spring.io/projects/spring-statemachine [3] https://blog.csdn.net/significantfrank/article/details/104996419

backenddesign patternsJavasoftware architectureState Machinerefactoring
Zhuanzhuan Tech
Written by

Zhuanzhuan Tech

A platform for Zhuanzhuan R&D and industry peers to learn and exchange technology, regularly sharing frontline experience and cutting‑edge topics. We welcome practical discussions and sharing; contact waterystone with any questions.

0 followers
Reader feedback

How this landed with the community

login 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.