DDD Folder Structure — Explanation & Justifications

1. domain/

This is the heart of DDD — the Domain Layer, representing the core business logic and rules.

model/

Contains entities like User.java.

Justification: DDD emphasizes rich domain models. Entities encapsulate data and behavior, representing the ubiquitous language of the business.

service/

Contains BusinessRules.java.

Justification: Domain Services handle domain logic that doesn’t naturally belong to a single entity. They implement complex business rules directly in the domain layer.

event/

Contains DomainEvent.java, UserCreatedEvent.java, EventPublisher.java.

Justification: DDD encourages capturing domain events to reflect important business occurrences. Events decouple the domain from infrastructure and allow eventual consistency or integration with other bounded contexts.


2. application/

This is the Application Layer in DDD — orchestrates domain objects to fulfill use cases, without embedding business logic.

port/input/

Contains interfaces like CreateUserUseCase.java, GetUserUseCase.java.

Justification: Defines what the application can do (use cases) without exposing implementation details. This aligns with DDD’s separation of application logic from domain logic.

port/output/

Contains interfaces like UserRepositoryPort.java, EventPublisherPort.java.

Justification: Outgoing ports abstract dependencies on external systems (DB, messaging). This allows domain logic to remain independent from frameworks and infrastructure.

service/

Contains CreateUserService.java, GetUserService.java, EventDrivenService.java.

Justification: Implements application use cases by orchestrating domain objects and invoking domain services/events. Keeps orchestration separate from domain rules.


3. adapter/

This is the Adapters Layer (or Infrastructure/Interface adapters) — bridges domain/application to external systems.

rest/

Contains UserController.java, HealthCheckController.java.

Justification: Incoming adapters that convert HTTP requests into calls to application ports. Controllers never contain business rules, preserving DDD principles.

persistence/

Contains JpaUserRepositoryAdapter.java, SpringDataUserRepository.java.

Justification: Outgoing adapters implementing UserRepositoryPort. They persist domain entities but do not embed domain logic.

lambda/

Contains LambdaHandler.java.

Justification: Another incoming adapter for AWS Lambda, transforming events into calls to application use cases.

events/

Contains KafkaEventPublisherAdapter.java, SnsEventPublisherAdapter.java, SqsEventListener.java, EventDeserializer.java.

Justification: Handles domain events asynchronously. Implements ports for publishing/consuming events, keeping domain unaware of messaging frameworks.

config/

Contains BeanConfig.java, KafkaConfig.java, SnsConfig.java, SqsConfig.java.

Justification: Infrastructure configuration. Keeps domain pure, avoiding framework-specific code inside domain/application layers.


4. infrastructure/

tracing/

Contains LoggingAspect.java, TracingInterceptor.java.

Justification: Cross-cutting concerns for monitoring and tracing. DDD domains remain independent of these technical concerns.

exception/

Contains GlobalExceptionHandler.java.

Justification: Centralized handling of errors. Domain exceptions can propagate through application/adapters, keeping domain logic clean.

metrics/

Contains MetricsCollector.java.

Justification: Tracks performance and events, outside domain logic.


5. src/main/java/org/ldschurch/rest_api/SpringbootLambdaApplication.java

Justification: Bootstraps the application but does not contain domain logic. All core business rules remain in domain/.


✅ Summary

Folder DDD Role
domain/modelCore entities (ubiquitous language)
domain/serviceDomain services implementing business rules
domain/eventCaptures business events, decouples domain from infrastructure
application/port/inputDefines use cases, separates orchestration from domain
application/port/outputAbstracts external systems for domain independence
application/serviceOrchestrates domain entities and services per use case
adapter/restIncoming adapter (HTTP → application ports)
adapter/persistenceOutgoing adapter (application ports → DB)
adapter/lambdaIncoming adapter (Lambda → application ports)
adapter/eventsHandles asynchronous events, decouples domain from messaging
adapter/configTechnical configurations, keeps domain pure
infrastructureCross-cutting concerns (logging, metrics, exceptions)

Why this folder structure perfectly supports DDD: