Mastering Complex Business Logic: A Structured Approach for Scalable Backend Development

In this article, Alibaba senior tech expert Zhang Jianfei shares a practical methodology for handling intricate business scenarios—like product listing in the Retail platform—by combining top‑down process decomposition with bottom‑up object‑oriented modeling, avoiding heavyweight workflow tools, and applying ability sinking to keep domain code clean, reusable, and maintainable.

ITFLY8 Architecture Home
ITFLY8 Architecture Home
ITFLY8 Architecture Home
Mastering Complex Business Logic: A Structured Approach for Scalable Backend Development

1. Business Background

Retail is a B2B model that supplies offline stores; the goal is to digitize and rebuild traditional supply‑chain channels to improve efficiency for new retail. Alibaba acts as a platform providing service functions within the Bsbc ecosystem.

The product lifecycle in Retail is illustrated below, with the "on‑sale" operation highlighted as a critical step that makes a product available to stores.

2. Process Decomposition

Complex business should not be written in a single service method; instead, apply divide‑and‑conquer. Over‑reliance on tools (custom workflow engines, database‑driven pipelines) adds unnecessary complexity. Follow KISS: avoid tools, use a minimal pipeline, and only resort to heavy workflow engines when strict visual orchestration is required.

For the on‑sale use case, the command handler is split into three phases:

@Command
public class OnSaleNormalItemCmdExe {
    @Resource private OnSaleContextInitPhase onSaleContextInitPhase;
    @Resource private OnSaleDataCheckPhase onSaleDataCheckPhase;
    @Resource private OnSaleProcessPhase onSaleProcessPhase;

    @Override
    public Response execute(OnSaleNormalItemCmd cmd) {
        OnSaleContext ctx = init(cmd);
        checkData(ctx);
        process(ctx);
        return Response.buildSuccess();
    }

    private OnSaleContext init(OnSaleNormalItemCmd cmd) {
        return onSaleContextInitPhase.init(cmd);
    }

    private void checkData(OnSaleContext ctx) {
        onSaleDataCheckPhase.check(ctx);
    }

    private void process(OnSaleContext ctx) {
        onSaleProcessPhase.process(ctx);
    }
}

Each phase further contains multiple steps. Example of a process phase:

@Phase
public class OnSaleProcessPhase {
    @Resource private PublishOfferStep publishOfferStep;
    @Resource private BackOfferBindStep backOfferBindStep;
    // ... other steps omitted

    public void process(OnSaleContext ctx) {
        SupplierItem item = ctx.getSupplierItem();
        generateOfferGroupNo(item);
        publishOffer(item);
        bindBackOfferStock(item);
        syncStockRoute(item);
        setVirtualProductExtension(item);
        markSendProtection(item);
        recordChangeDetail(item);
        syncSupplyPriceToBackOffer(item);
        setCombineProductExtension(item);
        removeSellOutTag(item.getOfferId());
        fireDomainEvent(item);
        closeIssues(item);
    }
}

3. Issues After Decomposition

Even with process decomposition, two problems remain:

Domain knowledge becomes fragmented; each use case only knows its own steps, preventing knowledge aggregation.

Business expression in code is weak; repetitive if‑else checks (e.g., inventory validation for combined products) obscure intent.

Original inventory check code:

boolean isCombineProduct = supplierItem.getSign().isCombProductQuote();
if (WarehouseTypeEnum.isAliWarehouse(supplierItem.getWarehouseType())) {
    if (CollectionUtil.isEmpty(supplierItem.getWarehouseIdList()) && !isCombineProduct) {
        throw ExceptionFactory.makeFault(ServiceExceptionCode.SYSTEM_ERROR, "亲,不能发布Offer,请联系仓配运营人员,建立品仓关系!");
    }
    Long sellableAmount = 0L;
    if (!isCombineProduct) {
        sellableAmount = normalBiz.acquireSellableAmount(supplierItem.getBackOfferId(), supplierItem.getWarehouseIdList());
    } else {
        OfferModel backOffer = backOfferQueryService.getBackOffer(supplierItem.getBackOfferId());
        if (backOffer != null) {
            sellableAmount = backOffer.getOffer().getTradeModel().getTradeCondition().getAmountOnSale();
        }
    }
    if (sellableAmount < 1) {
        throw ExceptionFactory.makeFault(ServiceExceptionCode.SYSTEM_ERROR, "亲,实仓库存必须大于0才能发布,请确认已补货.[id:" + supplierItem.getId() + "]");
    }
}

After introducing a domain model, the same logic simplifies dramatically:

if (backOffer.isCloudWarehouse()) {
    return;
}
if (backOffer.isNonInWarehouse()) {
    throw new BizException("亲,不能发布Offer,请联系仓配运营人员,建立品仓关系!");
}
if (backOffer.getStockAmount() < 1) {
    throw new BizException("亲,实仓库存必须大于0才能发布,请确认已补货.[id:" + backOffer.getSupplierItem().getCspuCode() + "]");
}

Using polymorphism (e.g., CombineBackOffer extends BackOffer) eliminates most conditional branches.

4. Combining Process Decomposition with Object Modeling

The combined approach yields a clean system structure (illustrated in the diagram below).

5. Ability Sinking

Instead of forcing every business rule into the Domain layer, only extract capabilities that are reused across multiple use cases. Place reusable logic in Domain Services or Models; keep use‑case‑specific steps in the Application layer.

Example of a reusable model method:

public class CSPU {
    private String code;
    private String baseCode;
    // ... other fields

    /** Determine if the SKU is the minimum unit */
    public boolean isMinimumUnit() {
        return StringUtils.equals(code, baseCode);
    }

    /** Determine if the SKU is a mid‑package */
    public boolean isMidPackage() {
        return StringUtils.equals(code, midPackageCode);
    }
}

By moving such checks into the model, code becomes self‑documenting and avoids scattering string comparisons throughout the codebase.

6. What Business Tech Actually Does

Business technology faces rapidly changing domains and must master problem decomposition, abstraction, and structured thinking—skills shared with low‑level system engineers. Strengthening fundamentals, object‑oriented design, and modeling enables developers to write clean, maintainable business code.

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.

Software Architecturecode complexityprocess decompositionObject Modelingability sinking
ITFLY8 Architecture Home
Written by

ITFLY8 Architecture Home

ITFLY8 Architecture Home - focused on architecture knowledge sharing and exchange, covering project management and product design. Includes large-scale distributed website architecture (high performance, high availability, caching, message queues...), design patterns, architecture patterns, big data, project management (SCRUM, PMP, Prince2), product design, and more.

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.