forge-docs

0012. Clean Architecture Package Structure Standards

Status: Accepted Date: 2025-12-10 Context: Standardize Java package structure across modules using Clean Architecture principles.

Context

The codebase had inconsistent package structures across modules:

This inconsistency made the codebase harder to navigate, understand, and maintain. New developers had to learn different patterns for each module.


Decision

We will adopt Clean Architecture package structure standards across all modules. All services, applications, and libraries must follow these standards.

Core Principles

  1. Separation of Concerns: Clear boundaries between domain, infrastructure, and presentation layers
  2. Consistent Structure: Same package structure across all modules of the same type
  3. Naming Conventions: Consistent naming patterns for resources, services, and repositories
  4. Single Source of Truth: DTOs defined once in libs/domain-dtos, not duplicated in services

Package Structure Standards

Services (services/{service-name})

io.forge.services.{service}/
├── domain/                               # Business logic
│   ├── dto/                              # Domain DTOs (if service-specific)
│   ├── exception/                        # Domain exceptions
│   └── [Domain services/interfaces]
├── infrastructure/                       # External concerns
│   ├── config/                           # Configuration producers
│   ├── persistence/                      # Database repositories
│   ├── mapper/                           # Entity/DTO mappers
│   └── [Other infrastructure]
├── presentation/                         # HTTP/REST layer
│   └── rest/                             # JAX-RS resources
│       ├── exception/                     # Exception mappers
│       └── [REST resources]
├── adapters/                             # External system adapters (optional)
│   └── [Adapter implementations]
└── runtime/                              # Runtime utilities
    └── StartupBanner.java

Applications (application/{app-name})

io.forge.application.{app}/
├── presentation/                         # HTTP/REST layer
│   └── rest/                             # JAX-RS controllers
│       └── [REST controllers]
└── runtime/                              # Runtime utilities
    └── StartupBanner.java

Infrastructure Libraries (libs/{library-name})

For libraries that provide infrastructure concerns (aws-api):

io.forge.{library}/
├── infrastructure/
│   ├── config/                           # Client producers
│   ├── client/                           # Client implementations
│   └── persistence/                      # Repository implementations
└── domain/                               # Interfaces (if any)
    └── [Domain interfaces]

Client Libraries (libs/domain-clients)

For REST client interfaces:

io.forge.client.{service}/
└── {Service}Client.java

Domain Libraries (libs/domain-*)

For shared domain concerns:

io.forge.domain.{concern}/
└── [Domain types, DTOs, interfaces]

Naming Conventions

REST Resources/Controllers

Domain Services

Repositories

Client Producers

Mappers


DTO Standards

Shared DTOs

All shared DTOs must be defined in libs/domain-dtos:

Service-Specific DTOs

Service-specific DTOs can be defined in services/{service}/domain/dto/:

Rule: If a DTO is used by multiple services or the frontend, it must be in libs/domain-dtos.


Examples

Good Structure: actor-service

io.forge.services.actor/
├── domain/
│   └── ActorService.java
├── infrastructure/
│   └── persistence/
│       └── ActorRepository.java
└── presentation/
    └── rest/
        └── ActorResource.java

Good Structure: security library

io.forge.security/
├── domain/
│   ├── dto/
│   ├── exception/
│   ├── TokenValidator.java
│   └── UserAuthenticationProvider.java
├── infrastructure/
│   └── config/
│       └── CognitoClientProducer.java
├── presentation/
│   └── rest/
│       ├── exception/
│       ├── Secured.java
│       └── [Other presentation classes]
└── adapters/
    └── cognito/
        └── CognitoUserAuthenticationProvider.java

Consequences

Positive:


Implementation

New Modules

All new modules must follow these standards from creation.

Existing Modules

Existing modules should be refactored to follow these standards when:

Note: Not all modules need immediate refactoring. Standards apply to new code and major changes.


Validation

Code reviews should verify:


Decision Owner: Architecture Team

Review Cycle: Review annually or when new module types are introduced