Olá, sejam todos muito bem-vindos a mais uma aula. E na aula de hoje a gente vai explicar em detalhes o que é a Clean Architecture, uma arquitetura de aplicação proposta pelo Robert C. Martin, o Uncle Bob. Ela é mais uma Dom-centric architecture, uma arquitetura que visa fortalecer e evidenciar o domínio e os casos de uso da aplicação. É uma arquitetura bem legal que tem muita coisa parecida com o Portion Adapters e a gente vai estudar em detalhes agora. E a gente vai estudar em detalhes agora. Então vamos lá, quando você cai na arquitetura limpa, essa é a imagem que você vê com mais frequência. Ela é basicamente a porta de entrada da arquitetura. Então, diferente da porta em adapters, da arquitetura hexagonal, ela tem quatro camadas. Ela tem quatro camadas, muitos termos, muitos conceitos, mas justamente são quatro camadas diferentes do portion adapters que são basicamente duas. diferentes do Portion Adapter que são basicamente duas. Então aqui a gente tem Entities, que são as Enterprise Business Rules, então são as regras de negócio a nível Enterprise, empresarial. Depois a gente tem a camada de casos de uso, que são as Application Business Rules, a gente vai ver com mais detalhes o que é cada um deles. Depois a gente toda aquela camada que de fato pilota a nossa aplicação ou é pilotada pelos casos de uso e é interessante que o autor comenta muito sobre o flow of control também ele não fala só sobre as definições sobre as camadas, como organizar como também sobre como deveria ser um fluxo básico desde um ator Ele não fala só sobre as definições, sobre as camadas, como organizar, como também sobre como deveria ser um fluxo básico desde um ator até um interface adapter, até um caso de uso, até um outro interface adapter de saída e, por fim, retornar essas informações. É importante ressaltar que a arquitetura limpa foi publicamente proposta em 2012, que veio esse artigo do The Clean Architecture, que foi onde o termo foi concebido, mas o Uncle Bob já havia feito um post sobre essa arquitetura um pouco antes. Ele só ainda não tinha, acho que talvez, dado esse nome, ele formulou depois melhor essa arquitetura. E é importante também ressaltar que essa arquitetura e o livro dele foi muito, mas muito inspirado neste livro, desculpa a qualidade da imagem ela estava meio ruim mesmo, este é um livro bem antigo, acho que de 72 chamado Object Oriented Software Engineering A Use Case Driven Approach, então orientação orientação engenharia de software orientada ao objeto utilizando uma abordagem de casos de uso. Então, esse livro foi feito por Ivar Jacobson e, basicamente, ele vem com uma ideia muito parecida com a que o Uncle Bob trouxe aqui. Lá no livro ele chama de IBC. Interactor Boundary Control, se não me engano. Ou é EBC, Entities Boundary Control, perdão. É EBC ou BCE, né? Então, Boundary Entities Control, que é quase a mesma coisa, né? Os casos de uso, as entidades e a parte de adaptadores, né? Então, no próprio livro do Uncle Bob, o The Clean Architecture, o Craftsman, não sei o que, ele menciona várias vezes esse livro, ele dá bastante créditos ao livro. E não só a este, como também a este aqui. Patterns of Enterprise Application Architecture, do Martin Fowler. É um outro livro que tem... É um catálogo de padrões que também muitos dos padrões são mencionados e linkados no livro do Uncle Bob e justamente os termos são retirados daí também, entre outras coisas, mas esses são os dois principais livros que o Uncle Bob se baseia muito para construir essa arquitetura limpa. Então, bora lá conhecer os detalhes. Então, quais são os principais termos que quem fala que sabe arquitetura limpa deve ter na ponta da língua? Principalmente para entrevistas. Então, fica aqui a dica. O primeiro termo, entidades. Entidades, também conhecido como Enterprise Business Rules, então regras de negócio a nível empresarial, elas são as mesmas entidades de domínio, diferente do que é de JPA, diferente do que é entidade de banco de dados, objeto relacional, essas aqui são as entidades de domínio. E o Uncle Bob vem com essa proposta de Enterprise Business Rules, porque naquele conceito, naquela época, ainda existia muito, por exemplo, o conceito de bibliotecas compartilhadas com essas classes compartilhadas. E neste conceito de biblioteca compartilhada de domínio, nesse lance de ser compartilhado, que vinham essas regras de negócios empresariais, que são regras de negócios que sempre precisam estar lá, que sempre precisam ser validadas. Em contraste, em diferença dos casos de uso, que a proposta deles é justamente ter regras de negócio específicas por aplicação. E não só isso, os casos de uso, eles descrevem o input desejado que deve ser provido do autor, do actor, ele descreve o fluxo de controle e o fluxo que vai fazer com que gere um output esperado também para aquele autor. Então, o caso de uso define o input, define o output e a forma de como é construído, como é gerado este output. E além disso, ele tem variações e regras de negócio específicas da aplicação. Qual é a diferença, então, entre esses dois conceitos? Business Rules Enterprise e Application Business Rules. Eu vou citar um exemplo aqui, que é um cenário de nota fiscal. Vamos supor que seja do interesse da companhia que a nota fiscal sempre tenha uma validação de que o emissor da nota fiscal nunca pode ser o mesmo do tomador daquela nota fiscal, de quem está recebendo aquela nota fiscal. Essa validação deveria ficar a nível da entidade. Ela é uma Enterprise Business Rules. Independente da aplicação, independente do sistema, ela nunca vai variar. Agora, em contrapartida, pode-se dizer que a gente pode ter uma validação que no sistema emissor público de nota fiscal a gente valida que o valor da nota fiscal nunca pode ser zero, para de repente evitar qualquer tipo de fraude, lavagem de dinheiro. Mas nos sistemas internos desse nosso sistema a gente confia nos funcionários e nos internos pode sim ser emitido com um autor fiscal com valor zero para justamente justificar de repente uma transferência de estoque, sei lá. É um exemplo, onde a gente tem regras de negócio em ânimo de aplicação e regras de negócio empresarial. Depois disso a gente tem o conceito de interface adapters esse aqui eu nem preciso explorar muito é o mesmo conceito do hexagonal só tem uma única diferença aqui que você pode já estar imaginando é que pelo fato do autor isolar frameworks and drivers é desejado que os interface adapters não tenham acoplamento com a layer de fora, não tenham acoplamento com os frameworks and drivers, não conheçam os frameworks and drivers. Por exemplo, conhecer uma interface que o framework and driver utiliza ou interpreta de alguma maneira, ou implementa de alguma maneira, para que aí sim a gente consiga fazer com que a layer de dentro não conheça a layer de fora. Isso aqui é bastante importante e é, de certa forma, até meio difícil de conseguir seguir isso no ecossistema Java, principalmente no ecossistema do Spring, na verdade, onde é usado muito de annotations. Então, a nível de controllers é um pouco difícil de garantir isso, mas existe sim uma abordagem, eu vou mostrar para vocês. Agora, gateways e presenters, esses sim é possível fazer respeitar esse conceito. Então, a gente tem os controllers. Os controllers é basicamente o meio de campo, a interface adapter para o mundo web, até para o UI pode ser também. A gente tem os presenters, que é uma maneira de converter o output de um caso de uso para uma estrutura de dados específica que um ator demanda. E a gente tem o conceito de gateways, que lá no Port and Adapters a gente conhece como repository. O gateway aqui é uma referência ao padrão descrito no livro Patterns of Enterprise Application Architecture. Justamente lá no livro é descrito como um gateway sendo um meio de acesso, por exemplo uma interface, para qualquer sistema ou recurso externo ao pacote ou à aplicação. Então, justamente por isso que é utilizado o gateway aqui. E o autor, o Uncle Bob, não menciona nada sobre Clean Architecture Plus mais DDD. Lá no DDD é utilizado o conceito do repository, que também está descrito no Patterns of Enterprise Application Architecture e no Microservice Patterns, onde o repository é a interface única para gerenciar, para você manusear, manipular os agregados da sua aplicação. Então, tem autores, como por exemplo, Rodrigo Branas e outros autores da comunidade, que quando utilizam Clean Architecture junto com DDD, trabalham com uma mistura entre os dois, entre tanto gateways quanto repositories. No mercado livre, por exemplo, a gente só usa gateways, mas a gente também não usa tanto DDD assim. Estamos utilizando... E na versão prática, eu vou trazer para vocês justamente essa mistura, a utilização desses dois conceitos. DDD com repository e de gateways para acessos a sistemas ou recursos externos. Depois, então, a gente tem a layer de fora, que é a layer de frameworks and drivers, que é basicamente a única layer que deveria ser acoplada a frameworks e bibliotecas terceiras. A interfaces, a web, a devices, a banco de dados. Então, é a única layer que deveria ser acoplada. Principais conceitos. Vamos lá, isso aqui também é bastante importante você saber, principalmente em entrevistas, se alguém for perguntar explique então o que é arquitetura limpa. Alguns aqui são menos importantes, não é tão cobrado, outros são mais importantes. Então vamos lá, data mappers. É mencionado no livro do Uncle Bob sobre o Clean Architecture o data mapper que basicamente é o cara que implementa um Gateway. Ele é a implementação de um Gateway do ponto de vista de acesso à persistência, de acesso ao banco de dados. Esse padrão Data Mapper está descrito lá no Patterns of Enterprise Application Architectures, o print é de lá. E ele diz basicamente que esse Data Mpper é uma camada de mappers, de mapeadores, que move o dado de um objeto para uma linha numa tabela de um banco de dados, ou num banco de dados não relacional, tanto faz, para um documento, num banco de dados não relacional, para colunas de um banco de dados não relacional, tanto faz, para um documento num banco de dados não relacional, para colunas de um banco de dados não relacional colunar, enfim, ele é responsável por fazer isso. Por exemplo, implementar uma interface adapter, poderia implementar, normalmente implementa uma interface adapter, e essa interface adapter é quem faz o depara do que vem da nossa entidade de domínio para o que este data mapper espera e o data mapper basicamente é quem de fato rece em dependências difíceis. Ele implementa, por exemplo, a mesma interface, a mesma assinatura de uma dependência difícil de ser testada, justamente por ter um acoplamento, uma interface difícil de ser testada, de ser testada, justamente para ter um acoplamento, uma interface que precise ser testada, fazendo então com que essa dependência seja isolada no ambiente de teste, mas que a sua interface consiga ser testada para que a gente teste o comportamento que manipula essa dependência. É esse objeto que facilita isso. É simples assim. Screaming Architecture, tá? Este é um conceito bastante importante que o Uncle Bob, ele, eu acredito que ele criou o nome do conceito, ele criou o termo, né? O termo é o nome, justamente. Mas o conceito mesmo, quem criou foi o Ivar Jacobson, lá no livro dele, Object Oriented Software Engineer, a Use Case Driven Approach. E lá no livro do Ivar Jacobson, ele justamente diz que o sistema, a estrutura do software, são estruturas que suportam os casos de uso de um sistema. Assim como as plantas das casas gritam sobre os casos de uso dessas construções, a arquitetura do nosso software deveria gritar sobre os casos de uso do nosso sistema. Então, sua arquitetura deveria dizer aos seus leitores os casos de uso, deveria dizer o que o seu sistema faz aos leitores e não quais ou como o sistema faz, quais os frameworks o sistema utiliza aos seus leitores, ou seja, ele dizer os casos de uso e não dizer o framework. E por que tem essa analogia com um blueprint, com uma planta de uma construção, de uma casa ou aqui desta mansão, por exemplo? Porque se você analisar a planta, a gente tem aqui, neste nível, nesta planta, a gente tem, por exemplo, você bate o olho e você vê, master bedroom, então a sala suíte principal, o banheiro da suíte principal, o closet masculino e o feminino da suíte principal, uma sala de exercícios, uma biblioteca, uma sala de jantar, o grande salão, o porta-carro, a garagem, outra garagem, não sei o que, a cozinha. Então, você sabe o que tem aqui. Você sabe que ele é uma cozinha, que é para cozinhar coisas. Já está implícito isso. Você não vê aqui, por exemplo, escrito sala com concretos e buchas tal e não sei o que. E persianas e alvenaria e marcenaria. Tipo, você não vê o como, você vê o que é. E justamente o Screaming Architecture é sobre isso. É sobre você organizar as pastas que estão dentro dos casos de uso, no caso, e de domínio com o nome do que é aquilo, do que é aquele que representa. Então, eu gosto, lá na pasta de application, por exemplo, as pastas de uso serem o nome daquele recurso, daquele agregado. Então, event, customer. Eu vou mostrar isso na prática para ficar um pouquinho mais tangível para vocês. Mas na Clean Architecture eu não uso a pasta chamada use case. Eu particularmente não gosto. Eu gosto de usar event, customer. E aí uma pasta chamada gateways. Essa pasta também poderia estar dentro do domain e a pasta de domain é a mesma coisa então eu não utilizo pasta chamada useCases isso também é para tentar respeitar o Screaming Architecture e não só a pasta como também o nome do caso de uso o nome do caso de uso um caso de uso em si deveria implementar o padrão comand ou seja ele só tem um único mais o público chamado de cute e o caso de uso deve carregar na classe no nome da classe a semântica do que ele faz que foi o que a gente fez lá creio que eventos cliente customer então isso Create Customer. Então, isso também faz parte do Screaming Architecture. Dependency Rule. A regra da dependência. Então, a gente já comentou um pouco sobre isso, mas... As dependências... O acoplamento entre as dependências deve sempre vir da camada de fora para a camada de dentro e nunca ao contrário, da camada de fora para a camada de dentro e nunca ao contrário da camada de dentro para a camada de fora. Ou seja, os frameworks and drivers dependem dos interface adapters que por sua vez dependem dos casos de uso, que por sua vez dependem das entidades. E aqui também se aplica o mesmo princípio que eu comentei lá no Portion Adapters, que é o princípio da inversão de dependência. Esse conhecimento da regra da dependência, ela só é possível através da inversão da dependência. Ou seja, o cara de dentro expõe uma interface pública que o cara de dentro expõe uma interface pública que o cara de fora vai implementar, e aí o cara de fora, às vezes, é injetado no cara de dentro. Não é para todos os cenários aqui. A inversão de dependência funciona muito bem para, principalmente, os interfaces adapters de presenter e de gateway e repository. Controller, nem tanto. Depois a gente tem o Application Business Rules, eu já expliquei. Então, Application Business Rules é o conceito onde cada aplicação tem regras de negócios específicas da aplicação, que não necessariamente é replicada em outras aplicações e que não necessariamente é uma regra de negócio a nível empresarial. Enterprise e Business Rules são todas as regras de negócio que, aí sim, são níveis empresariais, que deveriam estar em todas as aplicações, independente dela qual seja. E, por último, um conceito bem importante é que justamente a gente tem quatro camadas. É o conceito das camadas, na verdade. justamente a gente tem quatro camadas, é o conceito das camadas na verdade. Então, o Uncle Bob isola os casos de uso das entidades, ou seja, na verdade, vamos de dentro para fora, isola as entidades dos casos de uso, isola os casos de uso dos interfaces adapters, e isola os interfaces adapters da camada de frameworks and drivers. E o ponto muito importante é que casos de uso, entidades e interfaces adapters não deveriam ser acoplados a frameworks e bibliotecas externas. Ou seja, isolar casos de uso de entidades e interfaces adapters de frameworks e bibliotecas externas. Ou seja, isolar casos de uso de entidades, interfaces e adapters de frameworks e bibliotecas externas. Na prática, na prática, é fácil de... Na prática não é tão fácil de você isolar as interfaces e adapters de frameworks e bibliotecas. Tá bom? Casos de uso e entidades, sim, sempre deveria ser, com exceção de algumas bibliotecas, né, que normalmente a gente faz vista grossa, como por exemplo, Lombok, como por exemplo, Vavr, que é o antigo Java Slang, uma biblioteca que tem mônadas funcionais que são construções que faltam no Java. Construções como ETHER, um option, que é um option mais recente, como Validation, como try, entre outros. Então, esses caras que são realmente construções que faltam na linguagem, eu particularmente faço vista grossa. Agora, outras bibliotecas e frameworks que, de fato, são fáceis de serem substituídas, como, por exemplo, bibliotecas Spring da vida, bibliotecas de router, bibliotecas de resiliência. Isso deveria estar o máximo possível isolado desses caras. Beleza. Vamos então entender, vamos tentar tangibilizar como é que vai ser a estrutura de classes da nossa aplicação ao utilizar Clean Architecture. A gente tem aqui então o nosso conceito de Interactors, de casos de uso, e dentro ali da pasta de casos de uso, quer dizer, não da pasta do caso de uso, mas dentro ali da nossa pasta de application, onde tem os casos de uso, a gente deveria ver isso aqui como classes, como arquivos, vamos assim dizer. Então, a gente tem um arquivo que é o principal, que é o FinancialReportGenerator. Esse ger ele é justamente o nosso caso de uso, o caso de uso implementa uma interface que é quem os nossos controllers, por exemplo, são acoplados, né, que ele é o financial report requester, então ele é a porta de entrada, né, o caso de uso, ele demanda uma estrutura de dados, né, o DS é data structure, né, então ele é a porta de entrada o caso de uso ele demanda uma estrutura de dados o DS é Data Structure ele demanda uma estrutura de dados de entrada e ele demanda e ele expõe uma estrutura de dados de saída o caso de uso pode estar acoplado a uma interface que é um Gateway então aqui eu tenho um Financial Data Gateway por exemplo, e o caso de uso ele estará acoplado a regras de negócio de domínio, as entidades de domínio. Então isso aqui é a anatomia de um caso de uso. Depois disso a gente tem os controllers, então os controllers estão ali na lei de interface adapters, eles fazem o meio de campo entre frameworks e drivers e casos de uso. Então o Controller conhece muito sobre a estrutura de dados de entrada, a estrutura de dados de saída e sobre a interface daquele caso de uso. E nesta versão, que foi retirada do livro, no capítulo 8, o Presenter, a interface do Presenter, está fora do Interactor, está fora do ecossistema do caso de uso. Ela é chamada pelo Controller. Mas, normalmente, inclusive no livro tem uma outra abordagem, inclusive na imagem tem uma outra abordagem, que é o caso de uso é implementado o presenter é implementado fora, mas quem expõe a porta que aquele presenter implementa é o caso de uso. Então você vai ver essa interface aqui dentro e quem chama essa interface justamente é o caso de uso e não o controller. Eu vou mostrar também no diagrama mais pra frente. Depois a gente tem aqui a layer de database, essa layer aqui é também misturada entre interface adapter e frameworks and drivers, tá? Aqui basicamente o financial data mapper, ele é uma implementação do gateway, então ele é uma interface adapter, mas ele também tem regras de baixo nível de banco de dados, onde ele consegue mapear o objeto para o banco de dados, então consegue mapear o objeto para o banco de dados então ele também está meio que na lei ali de frameworks and drivers, ele está meio mais ou menos nessa imagem aqui e aí por fim a imagem completa que é trazendo o conceito do presenter aqui também então temos dois presenters aqui que implementam essa interface que aqui está na camada de interface adapters. Mas normalmente a implementação que está na camada de interface adapters, a interface em si deveria estar dentro dos casos de uso, dentro da camada de application. E aqui a gente tem dois, o screen e o print. Então o screen implementa a interface do presenter, ele pega a estrutura de dados que voltou daquele caso de uso, converte em uma outra estrutura de dados e passa por uma interface que através do princípio de inversão de dependência é injetado uma view ou injetado um PDF viewer, por exemplo, para impressão. Aqui a gente tem também na literatura, também no livro do Clean Architecture, Craftman, Guides to Software Structure and Design, a gente tem essa outra versão onde o presenter é orquestrado através do caso de uso e não através do controller e também respeita um pouco da imagem, que eu sei que é uma qualidade ruim, eu peguei do post oficial, ele representa o flow of control que o Anko Bob tanto fala, que é basicamente, vem de um ator, chega num controller, o controller que tem o fluxo passa para o caso de uso, o caso de uso ele expõe uma porta de saída que o presenter conhece e a implementa. Então, através dessa interface, ele não conhece o presenter, mas ele passa o fluxo de controle para o presenter sem mesmo conhecer, através aqui da inversão de dependência. E depois esse fluxo volta. E o controller também não conhece sobre o caso de uso. Isso aqui é importante. O controller conhece a interface, a porta de entrada do caso de uso, justamente para evitar dependência transitiva, para evitar do controller conhecer ou ser acoplado a dependências internas do nosso caso de uso. é isso, estamos por aqui acho que deu para entender bastante da arquitetura limpa quando a gente quando a gente for aplicar na prática a arquitetura limpa, acho que vai ficar também mais claro e nas próximas aulas também eu vou desmistificar algumas coisas de entidades de casos de uso de eventos que a nossa aplicação pode emitir e também as reais diferenças entre uma arquitetura como o Portion Adapters da Clean Architecture. Então é isso, espero que vocês tenham gostado. Vejo vocês na próxima aula.