Overview
ddd4j's stable center is the framework-agnostic domain, CQRS, and SPI layer. The outer modules deliver data, messaging, web, authentication, caching, observability, and runtime adapters.
When to Use
- Deciding which module should own a new capability, port, or adapter.
- Reviewing dependency direction — whether the domain layer imports framework types.
- Tracing a core port (
CommandBus,Publisher,SubjectProvider,Repository) to its actual registered adapter. - Deciding whether a new broker, ORM client, or HTTP integration belongs in core or in a capability module.
- Reviewing how Spring, Guice, and Quarkus CDI share the same core contracts.
- Landing a new capability: where it goes, what registers it, and what proves it works.
When NOT to Use
Do not use this skill when:
- The semantics of
AggregateRoot,Command,Query, orDomainEventthemselves are the question — useddd4j-coreinstead. Install:npx skills add full-stack-skills/ddd4j-skills --skill ddd4j-core. - Which Maven artifact owns a version, or BOM import order is the question — use
ddd4j-bominstead. Install:npx skills add full-stack-skills/ddd4j-skills --skill ddd4j-bom. - A concrete adapter must be implemented (persistence, broker, HTTP, cache, auth) — use that dimension's skill:
ddd4j-data,ddd4j-mq,ddd4j-web,ddd4j-cache, orddd4j-auth. - Generic DDD methodology is the question (bounded contexts, event storming, layering theory) with no ddd4j involvement — use the generic
ddd-skillsinstead; do not force ddd4j module names onto a methodology discussion. - The project is not on ddd4j — use the generic
java-skills; retrofitting ddd4j module structure onto a foreign codebase is out of scope. - You should not conclude an implementation exists from directory names alone — this skill requires call-graph and registration evidence; a folder listing is not a finding.
Trigger Keywords
English: module boundaries, dependency direction, ports and adapters, layering, runtime integration, architecture review, landing a capability
Chinese: module boundaries, dependency direction, ports and adapters, layered design, runtime integration, architecture review, capability placement
Quick Start
- "Can the domain layer depend on a MyBatis Wrapper?"
- "Which module should assemble the CommandBus?"
- "Should a new broker live in core or in the mq module?"
- "How do Spring, Guice, and Quarkus CDI share the core contracts?"
Architecture Zones
| Zone | Responsibility |
|---|---|
| annotation | DDD / CQRS / API / ORM metadata |
| core | AggregateRoot, Command/Query, Event, Repository, Context, SPI |
| kit | Foundational utilities, no business runtime |
| auth / data / mq / web / cache / metrics | Capability interfaces and their implementations |
| runtime-* | DI and lifecycle wiring for Spring, Guice, Quarkus, etc. |
| extensions | Cross-cutting optional extensions |
| ddd-rules | Architecture constraints and static checks |
| parent / dependencies / bom | Build, version ownership, and consumer surface |
Decision Rules
- Domain depends only on core, annotation, and necessary value types.
- ORM, broker, HTTP, and authentication frameworks live in the adapter layer.
- Static facades resolve implementations through Contexts, Registry, or SPI.
- Framework runtimes own registration, request scoping, rollback, and shutdown.
- BOM manages versions only — it does not prove runtime wiring succeeded.
- The same aggregate must not mix snapshot Active Record with Event Sourcing.
Capability Boundaries
✅ Strong At
- Module ownership and dependency direction.
- DDD / CQRS layering with ports and adapters.
- Sharing the core across multiple runtimes.
- Architecture review and landing new capabilities.
⚠️ Needs Input
- Target maintenance line and module POMs.
- Business behavior and transaction boundaries.
- Runtime and deployment model.
❌ Out of Scope
- Detailed framework API explanations.
- Concluding implementation from directory names alone.
- Unverified cross-line parity claims.
Workflow
- Confirm the Git root, branch, and CodeGraph health.
- Trace core ports and their actual adapters from the call graph.
- Mark compile dependencies, runtime registrations, and resource lifecycles.
- Verify separately with architecture tests, behavior tests, and runtime evidence.
- Report facts, inferences, violations, and proposed landing points.
Workflow
Step 1: Confirm the source of truth
Identify the Git root, branch, and maintenance line, and verify CodeGraph health. If the graph is unavailable, fall back to text search and say so in the report.
Step 2: Map the dependency graph
Enumerate compile-time dependencies between modules and confirm arrows flow from adapters toward core ports. Flag any domain module importing org.springframework.*, com.baomidou.mybatisplus.*, io.javalin.*, or io.quarkus.*.
Step 3: Trace the runtime wiring
For each SPI port (CommandBus, Publisher, SubjectProvider, Repository), find the concrete adapter registered by the runtime module. Document request-scope binding, shutdown hooks, and whether context cleanup covers success, exception, and async paths.
Step 4: Validate behavior separately
Run architecture tests (ddd-rules), behavior tests over one end-to-end command path, and collect runtime evidence. Compile dependencies, runtime registrations, and resource lifecycles are three different claims — verify each on its own.
Step 5: Report facts and gaps
Report current branch, modules, ports, adapters, registration points, tests, and risks. Label inferences explicitly and never merge them with facts; state missing implementations instead of inventing a chain.
Gotchas
- Domain importing Spring, MyBatis, Javalin, or Quarkus types — this compiles fine and passes unit tests; only an import audit or
ddd-rulesarchitecture test catches it. - Concrete broker or database clients created inside core — the class exists and works, which makes the violation invisible until the core module is reused on another runtime.
- A missing runtime registration misdiagnosed as a missing core API — the port exists; the static facade (
Contexts/Registry) just returns empty because the runtime never wired it. - Module and directory names treated as functional evidence — an
mqdirectory does not prove a broker adapter registers, initializes, or closes anything. - Reading the dependency tree without reading call sites and lifecycle — a dependency in the POM says nothing about whether it is registered, scoped, or closed at runtime.
Output and Exceptions
Return current branch, modules, ports, adapters, registration points, tests, risks. When an implementation is missing, return missing: specific adapter or registration point; how to provide: module or runtime — never invent a fictitious chain.
Deep Reference
Privacy and Security
Architecture evidence must not include credentials, real tenant data, or private Maven repository authentication. This skill does not access, collect, store, or transmit any user data, credentials, or keys; the architecture report uses only desensitized module and path information.
Audience and Customization
- Developers: provide the target modules, runtime, and behavior.
- Architects: specify a read-only boundary, migration, or compatibility review.
- Testers: specify the required evidence levels.
Customize the target maintenance line, allowed dependencies, and output depth. When input is insufficient, give a tentative verdict first, then list missing: module or runtime; how to provide: POM and call site.
FAQ
- Are skills organized by module? No — by decision domain.
- Does a directory's existence mean the capability is complete? No.
- Can the domain layer depend on a framework? It should not.
- What does the runtime layer do? Registration and lifecycle.
- Does identical cross-line structure imply identical behavior? No.
- What if an implementation is missing? State the gap explicitly; do not invent one.