Pular para o conteúdo principal

Estrutura do Projeto

Uma estrutura bem organizada é essencial para aplicações DDD. O Archbase recomenda a Arquitetura Hexagonal (Ports & Adapters), que isola o domínio de detalhes técnicos.

Estrutura Hexagonal

Estrutura de Projeto Hexagonal

Organização de Pacotes

domain/ - Core do Negócio

Contém entidades, value objects, agregados e interfaces de repositórios. Nunca depende de outras camadas.

domain/
├── entity/ # Entidades do domínio
│ ├── Cliente.java
│ ├── Produto.java
│ └── Pedido.java
├── valueobject/ # Value Objects
│ ├── CPF.java
│ ├── Email.java
│ └── Dinheiro.java
├── aggregate/ # Aggregates (Aggregate Roots)
│ └── PedidoAggregate.java
├── repository/ # Interfaces de Repository (Ports)
│ ├── ClienteRepository.java
│ └── PedidoRepository.java
├── service/ # Domain Services
│ └── CalculadoraFreteService.java
└── specification/ # Specifications
└── ClienteAtivoSpecification.java

application/ - Use Cases e Ports

Contém casos de uso, commands, queries e interfaces de ports (input/output).

application/
├── port/ # Ports (Interfaces)
│ ├── input/ # Input Ports (Use Cases)
│ │ ├── PedidoUseCase.java
│ │ └── ClienteUseCase.java
│ └── output/ # Output Ports
│ ├── PedidoPort.java
│ └── NotificacaoPort.java
├── service/ # Implementações de Use Cases
│ └── PedidoService.java
├── command/ # Commands (CQRS)
│ ├── CriarPedidoCommand.java
│ └── AtualizarStatusCommand.java
├── query/ # Queries (CQRS)
│ └── ListarPedidosQuery.java
├── handler/ # Command/Query Handlers
│ └── CriarPedidoHandler.java
└── dto/ # Data Transfer Objects
├── PedidoDTO.java
└── ClienteDTO.java

infrastructure/ - Adapters

Implementa detalhes técnicos: REST, JPA, MQTT/JMS, APIs externas.

infrastructure/
├── input/ # Input Adapters (Driving)
│ ├── rest/ # REST Controllers
│ │ ├── PedidoController.java
│ │ └── ClienteController.java
│ ├── graphql/ # GraphQL Resolvers
│ └── websocket/ # WebSocket Handlers
└── output/ # Output Adapters (Driven)
├── persistence/ # JPA/Hibernate
│ ├── entity/
│ │ └── PedidoEntity.java
│ └── repository/
│ └── PedidoRepositoryAdapter.java
├── messaging/ # MQTT/JMS (Artemis)
│ ├── publisher/
│ │ └── PedidoMQTTPublisher.java
│ └── listener/
│ └── PedidoEventListener.java
└── external/ # APIs externas
└── HttpClientPagamento.java

config/ - Configurações

Arquivos de configuração do Spring Boot.

config/
├── SecurityConfig.java
├── DatabaseConfig.java
└── MqttConfig.java # Configuração Artemis/MQTT

Responsabilidades de Cada Camada

Domain (Domínio)

É o coração da aplicação. Contém a lógica de negócio e nunca depende de outras camadas.

// ✅ CORRETO - Entidade com lógica de domínio
@Entity
@DomainEntity
public class Pedido extends PersistenceEntityBase<Pedido, UUID> {

public void adicionarItem(Item item) {
// Lógica de negócio aqui
validarQuantidade(item);
calcularTotal();
}

public void confirmar() {
if (!podeSerConfirmado()) {
throw new IllegalStateException("Pedido não pode ser confirmado");
}
this.status = StatusPedido.CONFIRMADO;
}
}
// ❏ EVITAR - Lógica fora da entidade
@Service
public class PedidoService {
public void confirmarPedido(Pedido pedido) {
pedido.setStatus(StatusPedido.CONFIRMADO); // Lógica deveria estar na entidade
}
}

Application (Aplicação)

Orquestra casos de uso, coordenando objetos do domínio. Usa Commands e Queries (CQRS).

@Component
public class CriarPedidoHandler implements CommandHandler<CriarPedidoCommand, UUID> {

private final PedidoRepository pedidoRepository;
private final ClienteRepository clienteRepository;

@Override
public UUID handle(CriarPedidoCommand command) {
Cliente cliente = clienteRepository.findById(command.getClienteId())
.orElseThrow(() -> new ClienteNaoEncontradoException());

Pedido pedido = new Pedido(cliente, command.getItens());
pedido.validar();

return pedidoRepository.save(pedido).getId();
}
}

Infrastructure (Infraestrutura)

Implementa detalhes técnicos: JPA, APIs externas, mensageria.

@Repository
public class PedidoRepositoryImpl implements PedidoRepository {

@PersistenceContext
private EntityManager entityManager;

// Implementações técnicas de persistência
}

Interfaces (Interface)

Controllers REST, GraphQL, ou qualquer outra forma de comunicação externa.

@RestController
@RequestMapping("/api/pedidos")
public class PedidoController {

private final CommandBus commandBus;
private final QueryBus queryBus;

@PostMapping
public ResponseEntity<PedidoResponse> criar(@RequestBody CriarPedidoRequest request) {
CriarPedidoCommand command = request.toCommand();
UUID id = commandBus.dispatch(command);
return ResponseEntity.ok(new PedidoResponse(id));
}
}

Regras de Dependência

Na Arquitetura Hexagonal, as dependências sempre apontam para o domínio:

CamadaPode Depender De
DomainNinguém (independente)
Application (Ports)Domain apenas
Infrastructure (Adapters)Domain e Application

Regra de Ouro: O Domain nunca deve depender de outras camadas.

Fluxo de Requisição

REST Controller (Input Adapter)

Use Case Interface (Input Port)

Service (Application)

Domain Entity (Core)

Repository Adapter (Output Adapter)

Database

Convenções de Nomenclatura

TipoSufixo/PrefixoExemplo
EntidadeNomes concretos do negócioCliente, Pedido
Value ObjectConceitos do domínioCPF, Email, Dinheiro
RepositoryRepositoryClienteRepository
CommandCommand ou nome verbalCriarPedidoCommand
QueryQuery ou nome verbalListarPedidosQuery
HandlerHandlerCriarPedidoHandler
ControllerControllerPedidoController
DTODTO, Request, ResponsePedidoDTO, CriarPedidoRequest

Multi-tenancy

Para projetos multi-tenant, use a base de entidades com tenant:

@Entity
@DomainEntity
public class Produto extends TenantPersistenceEntityBase<Produto, UUID> {
// Campos do domínio + tenant automático
}

Próximos Passos