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.

JD Cloud Developers
JD Cloud Developers
JD Cloud Developers
Mastering DDD Scaffolding: Architecture, Code Standards, and Common Pitfalls

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.

Clean architecture diagram
Clean architecture diagram

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 config

The 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 services
Overall layered architecture diagram
Overall layered architecture diagram

Scaffold 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-

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.

Backend ArchitectureClean Architecturecoding standardsDDDscaffolding
JD Cloud Developers
Written by

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.

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.