Arquitetura Hexagonal com Java

Arquitetura hexagonal é um estilo que fala sobre camadas de seus objetos de uma forma que isola sua lógica central de elementos externos. A lógica principal é a parte específica do seu negócio, e os elementos externos são como pontos de integração, por exemplo, bancos de dados, APIs externas, interfaces de usuário e outros. Ele divide o software nas partes interna e externa. As partes internas contêm a lógica do Core Business e a camada Domain (explicada em Layered Architecture). A parte externa consiste em interface do usuário, banco de dados, mensagens e outras coisas. Partes internas e externas se comunicam entre si por meio de portas e adaptadores.

Benefícios

  • O software desenvolvido usando esta arquitetura é independente de canais e pode suportar múltiplos canais
  • Fácil de trocar os pontos de integração de entrada e saída
  • Testar o software torna-se fácil porque podemos simular pontos de integração facilmente

Implementação em Java

Como explicado acima, a arquitetura hexagonal é mais em torno de portas e adaptadores. Em Java, as interfaces implementam as portas e a classe de implementação funciona como os adaptadoresEntão, vamos dar uma olhada em um exemplo simples usando o Spring Boot e ver como esse estilo pode ser aplicado a este framework.

Nesta aplicação, temos a funcionalidade para criar / visualizar detalhes do empregado. A lógica do Core Business está no  EmployeeService e o domínio é umEmployeeEntão, essas serão consideradas partes internas 

@Service
public class EmployeeService {
    @Autowired
    private EmployeeRepositoryPort employeeRepository;
    public void create(String name, String role, long salary){
        employeeRepository.create(name, role, salary);
    }
    public Employee view(Integer userId){
        return employeeRepository.getEmployee(userId);
    }
}
@Entity
@Table(name = "employee")
public class Employee{
    @Id
    @GeneratedValue
    @Column(name = "id")
    private Integer id;
    @Column(name = "name", nullable = false)
    private String name;
    @Column(name = "role", nullable = false)
    private String role;
    @Column(name = "salary", nullable = false)
    private long salary;
    // Setter and Getter methods
}

Portanto, agora, esse aplicativo pode expor essa funcionalidade via REST ou Messaging. Assim, criamos o  EmployeeControllerAdapter para expor endpoints REST, que implementa o EmployeeUIPort.

@RestController
@RequestMapping("/employees/")
public class EmployeeControllerAdapter implements EmployeeUIPort{
    @Autowired
    private EmployeeService employeeService;
   @Override
    public void create(@RequestBody Employee request) {
        employeeService.create(request.getName(), request.getRole(), request.getSalary());
    }
    @Override
    public Employee view(@PathVariable Integer id) {
        Employee employee = employeeService.view(id);
        return employee;
    }
}
 public interface EmployeeUIPort {
    @PostMapping("create")
    public void create(@RequestBody Employee request);
    @GetMapping("view/{id}")
    public Employee view(@PathVariable Integer userId);
 }

Como parte da lógica de negócios,EmployeeService também precisa chamar o banco de dados, que é, novamente, um ponto de integração (parte externa), portanto, criamos  EmployeeRepositoryPort, e EmployeeServiceAdapterimplementamos essa porta.

@Service
public class EmployeeServiceAdapter implements EmployeeRepositoryPort {
    @PersistenceContext
    private EntityManager entityManager;
    @Transactional
    @Override
    public void create(String name, String role, long salary) {
        Employee employee = new Employee();
        employee.setName(name);
        employee.setRole(role);
        employee.setSalary(salary);
        entityManager.persist(employee);
    }
    @Override
    public Employee getEmployee(Integer userId) {
        return entityManager.find(Employee.class, userId);
    }
}
public interface EmployeeRepositoryPort {
    void create(String name, String role, long salary);
    Employee getEmployee(Integer userId);
}

Então, vemos como  EmployeeService usou a EmployeeUIPortporta para expor seu serviço e   EmployeeRepositoryPort interagir com o banco de dados. Além disso, EmployeeControllerAdapter eEmployeeServiceAdapter ajuda a integrar com APIs REST e DB.

Conclusão

Para resumir, a arquitetura hexagonal é uma abordagem usada para dividir o aplicativo em  partes internas e externas . Eles estão conectados através de portas (expostas pelo lado de dentro) e adaptadores (implementados pelo lado de fora). Portanto, ao aplicar essa abordagem, o código do caso de uso principal permanece intacto e pode servir a vários canais, suportando diferentes protocolos. Também ajuda a tornar o aplicativo testado com facilidade. No entanto, sugiro não implementar essa arquitetura completamente para todo o aplicativo, mas usar interfaces e adaptadores seletivamente.

O código de todos os exemplos acima pode ser encontrado  no GitHub .

Leave a Reply

Your email address will not be published. Required fields are marked *

This site uses Akismet to reduce spam. Learn how your comment data is processed.