Mastering DDD Scaffolding: Architecture, Code Standards, and Common Pitfalls
This article introduces a DDD scaffolding project, explains its theoretical foundations, presents the layered architecture and generation commands, details coding conventions for each module, and addresses frequent questions and solutions for practical adoption.
Background
Our team has been continuously advancing systematic governance of business systems, during which we created a DDD scaffolding project that standardizes new projects and guides legacy projects through DDD refactoring.
Theoretical Basis of the Scaffold
DDD‑related application architectures such as four‑layer, onion, hexagonal, and clean architecture share the principle of separating concerns by layering, keeping the domain layer independent of external implementations.
The clean architecture consists of four layers:
Frameworks & Drivers layer : external systems like databases, caches, or front‑ends; highest change frequency and must be isolated from core business logic.
Interface Adapters layer : adapts external systems to internal business systems, handling protocol conversion.
Application Business Rules : the use‑case layer that orchestrates core business rules.
Enterprise Business Rules : the core domain logic layer, containing only business rules without technical concerns.
Scaffold Introduction and Usage
Generate a new project with the following Maven command:
mvn archetype:generate \
-DarchetypeGroupId=com.jd.jr.cf \
-DarchetypeArtifactId=ddd-archetype \
-DarchetypeCatalog=local \
-DarchetypeVersion=0.0.1-SNAPSHOT \
-DinteractiveMode=false \
-DgroupId=com.jd.demo.test // modify according to project name \
-DartifactId=demo-test \
-Dversion=1.0.0 \
-Dpackage=com.jd.demo.test \
-DappName=demo-test -s D:/git/settings.xml // local git configThe generated project structure is:
|--- adapter -- Adapter layer (interaction with external systems)
| |--- controller -- API implementation
| | |--- assembler -- DTO ↔ Domain model conversion
| | |--- impl -- Protocol implementation
| |--- repository -- Repository layer
| | |--- assembler -- PO ↔ Domain model conversion
| | |--- impl -- Domain repository implementation
| |--- rpc -- RPC layer (external service calls)
| |--- task -- Task scheduling adapters
|--- api -- Application protocol layer (exposed APIs)
|--- boot -- Boot layer (framework, drivers)
| |--- aop -- Aspect‑oriented programming
| |--- config -- Configuration
| |--- Application -- Main class
|--- app -- Application layer (use‑case orchestration)
| |--- cases -- Application services
|--- domain -- Domain layer (core business logic)
| |--- model -- Domain objects
| | |--- aggregate -- Aggregates
| | |--- entities -- Entities
| | |--- vo -- Value objects
| |--- service -- Domain services
| |--- factory -- Factories for complex objects
| |--- port -- Interfaces (ports)
| |--- event -- Domain events
| |--- exception -- Exception wrappers
| |--- ability -- Domain capabilities
| |--- extension -- Extension points
| |--- impl -- Extension implementations
|--- query -- Query layer (read services)
| |--- model -- Query models
| |--- service -- Query servicesScaffold Coding Conventions
1. Api Module
Define interfaces ending with Resource or Service to stay consistent with legacy applications.
Use dedicated request classes (preferably extending BaseRequest) instead of primitive types.
Wrap responses in a generic class.
All request/response classes end with DTO.
Avoid enum fields in DTOs.
2. Adapter/Controller Module
Convert between DTOs and domain VO/DO objects.
Contain no business logic; only parameter conversion and non‑business validation.
Cache logic for response values can be placed here.
3. App Module
Classes end with Case.
Orchestrates domain logic, calls domain ports, and may invoke cross‑domain services.
Can directly use domain repositories.
Handles transactions that span multiple aggregates.
4. Domain Layer
Domain services end with Service.
Entity classes have no suffix; value objects end with VO.
Domain services may call repositories and ports.
Prefer placing business logic in Entities and VOs first, then aggregates, and finally Domain services.
Follow Dependency Inversion: domain depends only on interfaces defined in its port package.
5. Adapter/Repository and Rpc Modules
Repository implementations convert DO to PO before persisting.
Each Repository corresponds one‑to‑one with an aggregate.
Transactions can be started inside Repository implementations if needed.
Rpc layer should define anti‑corruption objects ending with DTO for external interfaces.
Common Issues and Solutions
Q1: Should the Api module’s jar depend on other applications’ jars? A1: Ideally each application defines its own classes; avoid cross‑application dependencies by using separate common packages when necessary.
Q2: Can the Api package contain enum definitions? A2: Prefer not to expose internal enums; place shared enums in a common package if external visibility is required.
Q3: Must data storage use a unified version field? A3: New projects should use a unified version for optimistic locking; legacy systems may adopt it selectively based on effort.
Q4: For frequent RPC calls, can we skip anti‑corruption layer objects? A4: Although it may reduce short‑term effort, defining anti‑corruption objects is recommended for long‑term maintainability and standardization.
-end-
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.
JD Cloud Developers
JD Cloud Developers (Developer of JD Technology) is a JD Technology Group platform offering technical sharing and communication for AI, cloud computing, IoT and related developers. It publishes JD product technical information, industry content, and tech event news. Embrace technology and partner with developers to envision the future.
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.
