Your Web News in One Place

Help Webnuz

Referal links:

Sign up for GreenGeeks web hosting
June 29, 2021 11:36 pm GMT

Design: Ports and Adapters

Ol!

Este mais um artigo da seo Design, e nele falaremos sobre um padro muito til chamado Ports and Adapters, tambm conhecido como Arquitetura Hexagonal

Vamos l!

O qu o padro Ports and Adapters?

um padro proposto por Alistair Cockburn para reduzir o acoplamento entre as diferentes camadas de um sistema, aumentando assim sua testabilidade.

O padro recebe este nome por conta da forma como uma aplicao que o utilize interage com o mundo externo: a partir de ports (portas) e adapters (adaptadoes).

Portas so um meio de comunicao com o mundo externo aplicao (que voc pode entender como seu domnio), e podem ser de dois tipos: primrias e secundrias.

As portas primrias, representam as entradas da aplicao, conhecem os contratos do domnio e so oferecidas, geralmente, como casos de uso ou servios de aplicao. Essas portas costumam ser envolvidas por componentes que conversam com o mundo exterior diretamente, e que fazem uma eventual traduo entre o formato de sua prpria entrada e o formato do domnio. Esses componentes que envolvem essas portas primrias so os chamados adaptadores, dada a sua funo de interagir com o mundo externo suprindo o domnio com os dados que este demanda.

Quando o padro foi proposto, foi pensado que as portas primrias se conectariam ou camada de apresentao da aplicao, ou seja, a camada de interao com o usurio, ou a outras aplicaes que se integrariam aplicao em questo.

Soa confuso? Vamos a um exemplo simples.

Imagine que sua aplicao um agendador de tarefas que deve aceitar a criao de tarefas por meio de uma API Web. A porta de entrada, se implementada como um caso de uso, teria a seguinte forma:

public class CreateTaskUseCase : ICreateTaskUseCase{    private readonly IMyTaskDataAccess _dao;    ...    public MyTask CreateTask(string title, string description, DateTime dueDate)    {       var task = MyTask.Create(title, description, dueDate);       _dao.Insert(task);       return task;     }}

Para utilizar este caso de uso, a Web API o envolver por meio de injeco de dependncia, em um controller que o invocar mediante uma requisio, como no exemplo abaixo:

...public class CreateTaskController : ControllerBase{    private readonly ICreateTaskUseCase _useCase;    public CreateTaskController(ICreateTaskUseCase useCase) =>        _useCase = useCase;    [HttpPost]    public IActionResult Create[FromBody] CreateTaskRequest request)    {         try         {             var task = _useCase.CreateTask(request.Title, request.Description, request.DueDate);             return Ok(task);         }         catch(CreateTaskException exc)         {             return BadRequest(exc.Message);         }         catch         {             return InternalServerError();         }    }}

Repare, ento, que temos uma porta primria, o caso de uso de criao da tarefa e posterior persistncia, e um adaptador correspondente, o controller, que abastecer o domnio da aplicao com os dados enviados pelo consumidor da API Web.

J as portas secundrias se apresentam de maneira distinta. Elas costumam ser interfaces que expem um contrato demandado pelo domnio para se comunicar com o mundo externo visando, ou a sada de dados proveniente de seu processamento, ou a satisfao de alguma dependncia do mundo externo que, eventualmente, uma porta primria venha a ter (como, por exemplo, o consumo de outra aplicao).

Um exemplo de porta secundria a interface IMyTaskDataAccess usada pelo CreateTaskUseCase para inserir no banco de dados uma tarefa recm-criada. Esta interface definida na aplicao (domnio) e implementada por quem a utiliza em nosso caso de exemplo a API Web, sendo esta implementao um adaptador.

Por que usar Ports and Adapters?

A maior vantagem do uso do padro o isolamento do domnio, que leva a uma maior testabilidade.
Observando o exemplo acima, podemos ver que possvel testar nosso caso de uso muito facilmente, da seguinte forma:

public class CreateTaskUseCaseTest{    [Fact]    public void CreateTaskSuccessfully    {        //Arrange        var dao = new InMemoryMyTaskDatabase(); //Implementa IMyTaskDataAccess        var sut = new CreateTaskUseCase(dao);        //Act        var task = sut.CreateTask("title", "description", DateTime.Today.AddDays(1));        //Assert        Assert.Equal("title", task.Title);        Assert.Equal("description", task.Description);        Assert.Equal(DateTime.Today.AddDays(1), task.DueDate);    }}

Note que, uma vez que o teste realizado contra o caso de uso, nossa porta primria, e utilizando um mock para a porta secundria, no precisamos nos preocupar com a forma como se dar a entrada de dados no domnio, nem mesmo com o mecanismo de persistncia para a tarefa criada. Desta forma, temos nosso domnio isolado, e uma forma de atestar o funcionamento de sua lgica sem a exigncia de qualquer dependncia externa.

Ou seja, tanto do ponto de vista dos testes, quanto da execuo da aplicao, no h diferena se a entrada de dados vai se dar por uma API Web, um dispositivo mvel, terminal ou pelo consumo de uma fila. Da mesma forma, no importa qual banco de dados est sendo usado, se est em uso ou no algum ORM, qual o mecanismo de mensageria utilizado para publicar eventos ou disparar comandos, nem mesmo qual servio est sendo usado para enviar e-mails de notificao.

Tudo o que a aplicao conhece so suas portas, e cabe a quem for consumir a aplicao implementar os adaptadores correspondentes.

Quando usar Ports and Adapters

Como j sabemos, nenhuma soluo adequada a todos os cenrios e, claro, isso se aplica a este padro da mesma forma.

Em um cenrio orientado a servios, onde cada servio representa um contexto delimitado da aplicao, uma tima opo sim, DDD faz um casamento muito bom o padro por ser orientado a domnio!

Mesmo no utilizando DDD, servios que representem mdulos de uma aplicao tambm se beneficiam deste padro, uma vez que seu escopo reduzido torna mais facilmente mapeveis as entradas e sadas possveis.

Um bom critrio para saber se o uso do padro faz sentido o nmero de casos de uso que um domnio apresenta, e quais as sadas (ou dependncias) possveis para cada um.
No caso de exemplo acima, de agendamentos de tarefas, temos poucos casos de uso -- a criao da tarefa, seu reagendamento e seu cancelamento, por exemplo. Enquanto isso, temos apenas uma sada, a persistncia de seu estado.

claro que, no mundo real, aplicaes podem ser mais complexas que nosso simples agendador de tarefas mas, de todo modo, avaliar a quantidade de casos de uso e sadas segue sendo um bom parmetro. Ou seja, no final das contas, grosso modo, quanto mais alto o nmero de possveis portas, menor a viabilidade do emprego do padro.

Mas, por que Arquitetura Hexagonal?

Este um ponto bastante interessante. A inteno de Cockburn quando usou um hexgono para ilustrar seu padro era a de romper com a viso vertical proposta pelo estilo de organizao em camadas, deixando de lado a aparente hierarquia que ela apresenta (Apresentao -> Negcio -> Infraestrutura) por um modelo que sugere a centralidade do domnio, e superfcies de contato com o mesmo igualmente relevantes.
Ou seja, cada hexagono que representa uma aplicao, representa um domnio cercado por componentes que com ele interagem. Se pensarmos em vrias aplicaes integradas, teremos um mapa com diversos hexgonos onde cada um oferece uma superfcie de contato para outro atravs de seus diferentes lados.

Interessante. No?

Concluso

O padro Ports and Adapters muito til para elevar a testabilidade do domnio, e flexvel o bastante para ser combinado com outros padres de modo a satisfazer as necessidades da aplicao. Seu fit ideal com pequenas aplicaes ou servios, mas pode ser usado em casos mais complexos caso se perceba que seu custo superado pelos ganhos que oferece.

Como de costume, segue um exemplo de cdigo no Github, com um exemplo bastante simples de integrao entre trs servios. Todos os servios implementam o padro, e so acompanhados de casos de teste para demonstrar como a testabilidade do domnio beneficiada. Claro que, por ser um exemplo, os casos de teste sero muito simples, mas entendemos ser o suficiente para demonstrar o valor do padro.

Gostou? Me deixe saber pelos indicadores. Tem alguma dvida ou considerao? Deixe um comentrio por aqui ou em alguma de minhas redes sociais.

Muito obrigado por chegar at aqui, e at a prxima!


Original Link: https://dev.to/wsantosdev/design-ports-and-adapters-48mi

Share this article:    Share on Facebook
View Full Article

Dev To

An online community for sharing and discovering great ideas, having debates, and making friends

More About this Source Visit Dev To