Olá, seja muito bem-vindo a mais um vídeo. E vamos lá, a gente vai falar agora sobre arquitetura hexagonal. A gente pincelou bastante os problemas que a gente quis resolver, os problemas de você ir para uma arquitetura que não diz exatamente como você deve organizar a sua aplicação, que é uma arquitetura muito abrangente, que é arquitetura em camadas com o padrão MVC. E lembra daquela frase lá do começo? Vamos voltar lá para a gente ver rapidinho a frase? O que o Alistair Coburn propôs aqui em 2005 publicamente, mas que provavelmente ele elaborou, aqui em 2005 publicamente, mas que provavelmente ele elaborou uns anos antes, mas só conseguiu formar em 2005 a proposta, permita que a aplicação seja igualmente dirigida por usuários, programas, testes automatizados, Batch Scripts, e que seja desenvolvida e testada de maneira isolada dos dispositivos de tempo de execução, dos dispositivos que ela de fato precisa e dos bancos de dados que ela de fato precisa. E aí o que ele vem com a proposta então? Vamos lá. que é basicamente o hexágono, que é você proteger o núcleo da sua aplicação. O que é o núcleo? Os casos de uso e o seu domínio, as suas entidades de negócio, dentro desse hexágono interno que a gente aqui está chamando de application, do mundo externo, ou seja, da parte da esquerda, que são os primary actors, esse é o termo, ou drivers, ou seja, daqueles que usam casos de uso. Todos aqueles que utilizam casos de uso são drivers. A gente está blindando os nossos casos de uso destes drivers, ou seja, o caso de uso não tem acoplamento algum com nenhum deles. E blindo também da outra ponta, que é conhecida como os secondary actors, que são os driven actors, aqueles atores que são dirigidos pela aplicação. Não há nenhum acoplamento da camada de aplicação dos casos de uso com a parte da esquerda, que são os drivers, e nem com a parte da direita, com os driven actors. E como isso é possível? Isso é possível através de adapters e através de portas bem definidas. Então, vamos recapitular os principais termos antes de ir fundo na explicação. Drivers barra Primary Actors, ou seja, todo mundo que dirige ou que utiliza um caso de uso da nossa aplicação. Adapters. Os adapters são aquelas classes, aqueles métodos que são os responsáveis por entender um driver entender aqui o o ter o acoplamento do driver ou seja, entender as especificações do driver e converter esses dados e essas especificações no que o caso de uso espera na interface do caso de uso é, claro, e não só dos drivers, mas como também do Driven Actors, ou seja, os adapters estão na outra ponta também que implementa uma interface de uma porta de saída do hexágono e que converte esse domínio, essa estrutura de dados para o domínio em algo que o secondary actor, que o driven actor consiga compreender. Depois a gente tem as portas. Muita gente confunde a porta com a entrada de um ator ou a saída de um ator, mas não é isso, essas não são as portas. As portas não estão lá no começo. As portas estão entre os adapters e a aplicação. Tanto na parte da entrada, adapter e aplicação. Então a porta é o que o adapter usa para entrar dentro do núcleo do hexágono. Para entrar dentro do hexágono. E entre o hexágono e o adapter de saída, entre o adapter do Driven Actor, tem uma outra porta, ou seja, é, por exemplo, um repository. Bom, retomando aqui, perdão. E, por último, a gente tem os Driven Actors, como já mencionado, que são aqueles, aquela parte que está à direita, que é quem os casos de uso pilotam, utilizam. Então, o driver utiliza, através de um adapter, um caso de uso, que é através de um adapter, que utiliza uma interface, que utiliza um Driven Actor através de uma interface que é implementada por um adapter. Basicamente, isso aqui. Então a gente tem um ator. Quem que pode ser o ator? Pode ser um teste, pode ser um controller, ou melhor, uma REST API, um HTTP server, pode ser um broker, que vai passar por uma camada de adapter, que entra basicamente na nossa aplicação e passa por uma camada de adapter, ou seja, eu peguei do body da request o valor, peguei do header da request outro valor e instanciei o input do meu use case e passei para ele. O driver é responsável por isso, por saber de onde ler esses dados do ator para compor a informação que um caso de uso necessita. E aí ele usa a porta exposta pelo hexágono, a porta que na verdade é um caso de uso, a interface do caso de uso. Ele usa a interface do caso de uso. Assim como o business logic aqui, dentro do hexágono, ela implementa essa porta, implementa esse caso de uso. E depois que está aqui dentro, reparem que o caso de uso, ele usa uma outra porta, ou seja, ele usa uma outra interface, que é implementada por um adapter, ou seja, ele recebe essa essa por um adapter, ou seja, ele recebe essa entidade de negócio e é responsável por convertê-la naquilo que o Driven Actor sabe ler. Então reparem como ambas as partes de fora apontam para dentro do hexágono. Isso aqui é muito interessante, é importante a gente ter em vista. Então vamos lá, vamos recapitular os principais conceitos aqui. O autor, Alex Tarko-Burn, ele prega muito isso de pensar nos casos de uso primeiro. Comece a sua aplicação com os casos de uso. Depois você define o banco de dados, depois você utiliza, define qual vai ser o ator de entrada, se vai ser uma REST API, se vai ser SOAP, se vai ser GraphQL. Então, primeiro pense no caso de uso, comece a codificar o caso de uso, isole eles dentro do hexágono, depois você declara isso para o mundo. Isso vai te ajudar a pensar em interfaces coesas por causa de uso, sem ficar enviesado e acoplado a um ator específico. Dependency Inversion Principle. Então é um princípio que vocês já viram muitas vezes aqui no decorrer do curso. A estrutura hexagonal foi muito falada no módulo de DDD, no módulo de Solid mas o que esse princípio diz? é quando é quando basicamente a dependência ela é invertida e um cara de baixo, um cara de fora implementa uma interface de cima e esse cara é injetado sem que a sua camada, sem que a camada que usa essa interface conheça ela. Então você inverte a dependência. O cara de cima usa o de baixo, mas é o de baixo que implementa o de cima. Dessa forma, o cara de cima, que é um cara de alto nível, ele não conhece os detalhes baixo nível, que é o cara de baixo. O cara de baixo sim conhece os detalhes de alto nível de cima, porque ele precisa implementá-los. Só que na hora de usar é invertido. O cara de cima que usa o de baixo. As portas são de entrada ou saída do hexágono, como a gente comentou, então as portas são aquelas, não são por onde o driver entra ou sai, o driven actor sai, e sim são por onde esses casos, os adapters desses casos estão entrando ou recebendo informação. Os adapters se localizam entre as portas e o exágono não, acho que está invertido aqui, mas se localizam entre a porta e o ator, Ou seja, ele está entre o... Quando vem o ator, tem o adapter e a porta. Quando sai, tem uma porta, o adapter e o ator. Então, o adapter está sempre entre uma porta e um ator. E essa última... Esse conceito aqui, na verdade, não é uma regra, mas o autor colocou como um detalhe a mais na nova edição do post, que ele, na forma como ele implementa e utiliza o hexagonal, ele gosta de manter as portas agrupadas para o contexto. Por isso que ele define lá no primeiro exemplo, deixa eu ver se tem aqui. Por isso que aqui, por exemplo, ele define como uma porta sendo TriggerData, ali embaixo uma outra porta Administration, ali em cima Notification depois database. Ou seja, ele agrupa as funcionalidades da aplicação de uma certa forma onde ele expõe portas para essas funcionalidades. Então, se você for ver ali embaixo, por exemplo, administration, eu tenho o HTTP adapter lá em cima, eu também tenho o HTTP feed, o IL feed, teste adapter, lá embaixo também Test Adapter, né? Qual que é a proposta dele aqui? Por que ele faz isso? Porque no conceito dele, a porta é utilizada por várias pessoas, né? Então, por exemplo, as pessoas entram num prédio comercial com vários carros diferentes, imagina que cada carro, por exemplo, é um ator. Mas todos eles, no fim das contas, passam por um adapter. Então, vamos supor que o estacionamento é o adapter, ou seja, onde fica ali o carro, vai a pessoa e passam pela mesma porta que entra no prédio comercial. Então, a porta recebe várias pessoas, vários atores diferentes. Então, por isso que ele gosta de agrupar como porta. Mas ele deixa aberto. Ele fala que se você quiser usar como uma porta, como se fosse cada use case, pode ser. E o padrão não impõe como organizar as pastas da aplicação. Esse é um pequeno detalhe. Ele não importa como você vai organizar as pastas dentro do hexágono, para ele o importante é que você consiga manter a integridade do hexágono consiga fazer com que a parte de dentro não tenha acampamento com fora e sim a parte de fora que saiba implementar saiba utilizar a parte de dentro e aqui por último, como eu já mostrei esse exemplo, mas voltando aqui, então aqui tem um resumo um pouco maior do que ele quer dizer com arquitetura hexagonal. Então aqui a gente tem os atores, a gente tem um ator que é um wide feed, a gente tem um ator que é um test, e a gente tem um ator que é uma chamada HCP. eles entram no hexágono de fora, aqui, está vendo? E passam todos por essa camada de adapter. Isso aqui tudo é adapter. E aí depois o adapter entra por uma porta, que entra para a aplicação. Tá bom? Bom, é isso. Espero que vocês tenham entendido os conceitos da arquitetura hexagonal. E vamos para a prática.