Refactoring a Legacy Supply‑Chain System with DDD, Hexagonal Architecture, and EventStore
The article details how a legacy e‑commerce supply‑chain system plagued by unclear boundaries, inventory inaccuracies, and tangled dependencies was redesigned using domain‑driven design, hexagonal architecture, CQRS, and an EventStore solution, resulting in accurate inventory, easier extensions, and a reusable event‑driven component.
Any business architecture inevitably accumulates historical problems; architects must use new, appropriate architectural ideas to refactor it effectively.
The main subject is the supply‑chain (inventory) system, also known as the procurement‑in‑stock‑sales chain, which manages warehouse inventory and connects upstream order fulfillment with downstream sales. In Keep's e‑commerce platform, the Skynet and ERP systems serve as core components handling order shipping, after‑sale returns, purchase replenishment, inter‑warehouse transfers, and special stock movements.
The Skynet and ERP systems, built when Keep entered the e‑commerce arena, have grown heavy over years of rapid iteration, leading to increasing operational issues. The legacy supply‑chain system lagged behind business growth and suffered from a lack of systematic planning and code standards, resulting in an almost unfixable monolith.
Unclear system boundaries
Chaotic architecture and unclear internal layering
Inaccurate inventory and unclear inventory‑change context
New business requirements
These pressures made incremental fixes on the old system impossible, prompting a full‑scale reconstruction.
The refactoring plan is organized into three major categories:
Clarify inventory business scenarios
Define bounded contexts
Model inventory concepts
Key inventory concepts include:
Occupied inventory: sold but not yet shipped.
Available inventory: physical stock minus occupied inventory.
Physical inventory: actual items in the warehouse.
In‑transit inventory: purchased but not yet received.
Frozen inventory: reserved for promotions or inter‑warehouse transfers.
After clarifying the domain, the team considered DDD architectural options, focusing on the Hexagonal (Ports & Adapters) architecture to separate domain models from technical details.
Maintain stability of core domain models
Layered design follows the Dependency Inversion Principle: the domain layer depends on no other layers, while lower layers depend on interfaces exposed by higher layers.
Prevent custom queries from corrupting the domain model
Introduce CQRS to separate command and query models.
Avoid domain model corruption from interactions with other bounded contexts
For example, the procurement context uses an anti‑corruption layer (ACL) to map warehouse information from the core inventory context into its own value objects, preventing direct dependency.
Implementation with COLA (Clean‑Architecture‑Layered‑Architecture)
Ensure consistency of document statuses across inventory‑change scenarios
When a lower‑level inventory change occurs (e.g., purchase receipt completed), the corresponding upper‑level business document (e.g., purchase order) automatically updates its status, and similarly for sales outbound documents.
EventStore solution
The team adopted EventStore for event sourcing; the data flow is illustrated below, with the yellow part representing domain‑event error handling.
Publishing domain events (code shown in the original images) and subscribing to them are handled via registered subscription groups.
In the subscription group, events are declared and consumed.
Continuous integration quality is ensured through extensive unit testing:
Domain model unit tests (Domain tests)
Command‑execution tests for core business interfaces (CmdExe tests)
Mockito for mocking dependencies and data
In‑memory H2 database to avoid side effects
Minimal reliance on external middleware (Dubbo, Kafka) or mock them
Automatic CI test execution on git push
The refactor yielded five major benefits:
Accurate inventory, solving warehouse stock discrepancies and providing a reliable baseline for sales inventory.
Easier functional extensions, such as rapid integration with financial systems.
Fast issue localization thanks to clear code structure and traceable inventory changes.
A reusable EventStore component that can be quickly adopted across Keep's e‑commerce services.
A mature DDD best‑practice package ready for rollout to other inventory and after‑sale systems.
Overall, the experience shows that DDD naturally complements micro‑services: DDD defines clear business model boundaries, while micro‑services split the monolith into independently deployable services.
Readers are invited to discuss DDD further in the comments.
Author: Wu Qingming – 12 years of experience, 8 years in e‑commerce system development, currently leading commercial middle‑platform architecture at Keep, specializing in DDD‑based design for complex e‑commerce systems.
Source: https://blog.csdn.net/zhipengfang/article/details/120500445
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.
Architecture Digest
Focusing on Java backend development, covering application architecture from top-tier internet companies (high availability, high performance, high stability), big data, machine learning, Java architecture, and other popular fields.
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.
