Blog do Aguiar

Clean Architecture com Spring Boot: Guia Completo com Exemplo Prático

Introdução

A Clean Architecture com Spring Boot é uma abordagem de design que organiza o sistema em camadas bem definidas, promovendo baixo acoplamento, alta coesão e independência de frameworks.

Se você já enfrentou problemas como:

… então este artigo vai te ajudar a resolver isso de forma estruturada.

O que é Clean Architecture?

A Clean Architecture foi proposta por Robert C. Martin (Uncle Bob) e tem como objetivo principal:

Separar regras de negócio da infraestrutura

Ou seja:

Estrutura das Camadas

 

 

 

 

 

 

 

 

 

 

 

1. Domain (Entidades + Regras de Negócio)

public class Account {
    private Long id;
    private BigDecimal balance;

    public void deposit(BigDecimal amount) {
        if (amount.compareTo(BigDecimal.ZERO) <= 0) {
            throw new IllegalArgumentException("Valor inválido");
        }
        this.balance = this.balance.add(amount);
    }
}

👉 Não depende de Spring, JPA ou qualquer framework

2. Application (Use Cases)

public class DepositUseCase {

    private final AccountRepository repository;

    public DepositUseCase(AccountRepository repository) {
        this.repository = repository;
    }

    public void execute(Long accountId, BigDecimal amount) {
        Account account = repository.findById(accountId);
        account.deposit(amount);
        repository.save(account);
    }
}

3. Interface Adapters

@RestController
@RequestMapping("/accounts")
public class AccountController {

    private final DepositUseCase depositUseCase;

    public AccountController(DepositUseCase depositUseCase) {
        this.depositUseCase = depositUseCase;
    }

    @PostMapping("/{id}/deposit")
    public ResponseEntity deposit(@PathVariable Long id,
                                        @RequestBody DepositRequest request) {
        depositUseCase.execute(id, request.getAmount());
        return ResponseEntity.ok().build();
    }
}

4. Infrastructure

@Repository
public class AccountRepositoryImpl implements AccountRepository {

    private final JpaAccountRepository jpaRepository;

    public AccountRepositoryImpl(JpaAccountRepository jpaRepository) {
        this.jpaRepository = jpaRepository;
    }

    @Override
    public Account findById(Long id) {
        return jpaRepository.findById(id)
                .map(AccountMapper::toDomain)
                .orElseThrow();
    }
}

Regra de Dependência (A MAIS IMPORTANTE)

As dependências sempre apontam para dentro

Controller → UseCase → Domain
Repository → Domain

❌ Domain NÃO conhece:

📦 Estrutura de Pacotes Sugerida

com.seuprojeto
 ├── domain
 │    ├── model
 │    └── repository
 │
 ├── application
 │    └── usecase
 │
 ├── infrastructure
 │    ├── persistence
 │    └── config
 │
 └── interfaces
      ├── controller
      └── dto

Benefícios Reais

✅ Testabilidade

Você testa UseCase sem Spring:

@Test
void shouldDeposit() {
    AccountRepository fakeRepo = new InMemoryAccountRepository();
    DepositUseCase useCase = new DepositUseCase(fakeRepo);

    useCase.execute(1L, BigDecimal.TEN);

    assertEquals(BigDecimal.TEN, fakeRepo.findById(1L).getBalance());
}

Independência de Framework

Trocar:

👉 sem alterar o domínio

Organização para sistemas grandes

Perfeito para:

👉 (exatamente seu cenário hoje)

⚠️ Erros comuns

❌ Colocar @Entity no Domain

@Entity // ERRADO
public class Account { }   assertEquals(BigDecimal.TEN, fakeRepo.findById(1L).getBalance());
}

👉 Isso acopla ao JPA

❌ Lógica no Controller

// ERRADO
if (amount > 0) {
   account.setBalance(...)
}

👉 regra deve ficar no domínio

❌ Repository direto no Controller

👉 pula o UseCase → vira bagunça

Clean Architecture vs Hexagonal vs DDD

Conceito Foco
Clean Architecture Separação de camadas
Hexagonal Portas e adaptadores
DDD Modelagem do domínio

Quando usar?

Use Clean Architecture quando:

Evite quando:

Conclusão

A Clean Architecture com Spring Boot não é apenas organização — é uma forma de garantir que seu sistema:

Se você quer evoluir como arquiteto, dominar esse conceito é essencial.

Share this content:

Sair da versão mobile