A Arquitetura Hexagonal (ou Ports and Adapters) foi criada por Alistair Cockburn com o objetivo de tornar os sistemas mais flexíveis, desacoplados e testáveis. Já o Modelo MVC (Model-View-Controller) é uma abordagem clássica para organizar aplicações, separando a lógica de apresentação, controle e modelo de dados.

📌 Diferenças entre Arquitetura Hexagonal e MVC

1. Estrutura e Organização

Característica Arquitetura Hexagonal MVC
Separação de responsabilidades Domínio, Aplicação e Infraestrutura Model, View, Controller
Desacoplamento Alto (depende apenas das interfaces) Médio (Controller depende da View e Model)
Testabilidade Alta (testes de unidade mais fáceis) Média (testes dependem do framework)
Escalabilidade Melhor adaptação a mudanças tecnológicas Boa para aplicações menores
Flexibilidade Alta (troca de tecnologias sem impacto no domínio) Média (depende do framework)

2. Vantagens e Desvantagens

✅ Vantagens da Arquitetura Hexagonal:

  • Independência de frameworks e tecnologia.
  • Código mais modular e reutilizável.
  • Testes mais fáceis devido ao isolamento do domínio.
  • Melhor organização para aplicações grandes e escaláveis.

❌ Desvantagens da Arquitetura Hexagonal:

  • Complexidade inicial maior.
  • Pode ser excessivo para aplicações simples.
  • Maior curva de aprendizado para quem está acostumado com MVC.

✅ Vantagens do MVC:

  • Mais simples de implementar em pequenos projetos.
  • Melhor suporte em frameworks como Spring Boot, Django, Laravel.
  • Código estruturado de forma mais intuitiva para iniciantes.

❌ Desvantagens do MVC:

  • Maior acoplamento entre as camadas.
  • Difícil evolução sem quebrar partes do sistema.
  • Pode levar a problemas de manutenção em aplicações grandes.

🚀 Cenários de Aplicação

Cenário Melhor opção
Aplicações simples e CRUDs MVC
Sistemas corporativos escaláveis Hexagonal
Microservices Hexagonal
Prototipação rápida MVC
Sistemas altamente testáveis Hexagonal

🏗️ Aplicação Prática - Exemplo com Arquitetura Hexagonal

Estrutura do Projeto

hexagonal-architecture-example/
├── src/
│   ├── main/
│   │   ├── java/com/exemplo/
│   │   │   ├── domain/           # Regras de negócio
│   │   │   ├── application/      # Casos de uso
│   │   │   ├── infrastructure/   # Infraestrutura
│   │   │   │   ├── repository/  # Persistência de dados
│   │   │   │   ├── controller/  # API REST
│   │   │   ├── HexagonalApplication.java
│   ├── test/

1. Criando o Domínio (Core)

Definimos a entidade User e a porta (UserRepository), que será usada para persistência.

package com.exemplo.domain;

public class User {
    private Long id;
    private String name;
    private String email;

    public User(Long id, String name, String email) {
        this.id = id;
        this.name = name;
        this.email = email;
    }

    public Long getId() { return id; }
    public String getName() { return name; }
    public String getEmail() { return email; }
}
package com.exemplo.domain;

import java.util.List;
import java.util.Optional;

public interface UserRepository {
    User save(User user);
    Optional<User> findById(Long id);
    List<User> findAll();
}

2. Criando a Aplicação (Use Cases)

A classe UserService implementa a lógica de cadastro e recuperação de usuários.

package com.exemplo.application;

import com.exemplo.domain.User;
import com.exemplo.domain.UserRepository;
import java.util.List;
import java.util.Optional;

public class UserService {
    private final UserRepository userRepository;

    public UserService(UserRepository userRepository) {
        this.userRepository = userRepository;
    }

    public User registerUser(String name, String email) {
        User user = new User(null, name, email);
        return userRepository.save(user);
    }

    public Optional<User> getUserById(Long id) {
        return userRepository.findById(id);
    }

    public List<User> getAllUsers() {
        return userRepository.findAll();
    }
}

3. Criando a Infraestrutura (Adapters)

Implementamos a persistência usando Spring Data JPA.

package com.exemplo.infrastructure.repository;

import com.exemplo.domain.User;
import com.exemplo.domain.UserRepository;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.stereotype.Repository;

@Repository
public interface UserJpaRepository extends JpaRepository<User, Long>, UserRepository {
}

Criamos um controlador REST para expor a API.

package com.exemplo.infrastructure.controller;

import com.exemplo.application.UserService;
import com.exemplo.domain.User;
import org.springframework.web.bind.annotation.*;
import java.util.List;
import java.util.Optional;

@RestController
@RequestMapping("/users")
public class UserController {
    private final UserService userService;

    public UserController(UserService userService) {
        this.userService = userService;
    }

    @PostMapping
    public User createUser(@RequestParam String name, @RequestParam String email) {
        return userService.registerUser(name, email);
    }

    @GetMapping("/{id}")
    public Optional<User> getUser(@PathVariable Long id) {
        return userService.getUserById(id);
    }

    @GetMapping
    public List<User> getAllUsers() {
        return userService.getAllUsers();
    }
}

Conclusão

A Arquitetura Hexagonal oferece maior flexibilidade e desacoplamento, sendo ideal para sistemas escaláveis e de longa duração. Já o MVC é mais simples e direto, sendo útil para projetos menores e rápidos.

📌 Se quiser testar o projeto, configure um banco de dados H2 ou PostgreSQL, e rode com Spring Boot!

🎯 Cursos e Projetos Práticos

  • Criar um CRUD simples usando MVC para comparar.
  • Implementar um microserviço usando Arquitetura Hexagonal.
  • Desenvolver testes unitários para validar a separação de camadas.

Gostou? Faça um fork e contribua! 🚀

📌 Repositório GitHub: [https://github.com/Kaciany/hexagonal-architecture-example]