Salve, Deus, beleza? Continuando nossa saga aqui no Domain Dream Design, eu quero reunir nessa aula algumas questões sobre padrões de arquitetura e também sobre Design Patras, que são muito utilizados no DDD. Eu não quero fazer uma aula para cada. A gente pode ter uma visão e justamente acrescentando ao que o Vernon já disse ali no capítulo que ele fez o overview, eu vou chamar isso aqui de padrões de arquitetura e design patterns. Padrões de projeto. Aí vem justamente a guerra entre o que é padrão de arquitetura e padrão de design. Não vou entrar nessa briga aqui nessa aula, mas eu quero falar um pouquinho sobre... Na verdade, eu vou inverter. Padrões de arquitetura eu vou falar depois. Sobre design patterns primeiro. Padrões de arquitetura. primeiro padrões de arquitetura não há design patterns específicos para a gente poder trabalhar com o DDD, não há assim você tem que usar esses padrões aqui você pode pegar o Gang of Four os padrões que o Martin Fowler fala lá no livro dele. E qualquer tipo de padrão de arquitetura pode ser aplicado para modelar o nosso domínio. Desde que você saiba o motivo, o problema que esse design pattern resolve e entenda o que você está aplicando. Não é para ter aquela síndrome da paternite e ficar usando patterns só por usar, que aí você vai tornar a coisa tão complexa que você vai falar até que a culpa é do DDD e não é. Então, tome cuidado com isso. Mas padrões de design que são muito utilizados. Factories, para a gente poder começar. Factories é muito utilizado com agregados. Mas como assim agregados? É só fazer um new lá na minha classe e já está ok? Não, porque agregados podem ser um pouco mais complexos. Eu posso ter várias formas de criar esse agregado. Às vezes, se eu passar determinados parâmetros, eu vou criar esse agregado de um jeito. Se eu passar com outros, eu crio ali numa outra perspectiva. Eu deixo o new, instanciar o objeto passando todos os parâmetros correspondentes, e essa factory, que é um factory de método, a gente chama de factory method, ela vai servir para que a gente possa criar ele de várias formas. Inclusive, determinadas linguagens como Java, que a gente tem ali uma sobrecarga de métodos, eu posso ter um método com o mesmo nome, aceitando parâmetros diferentes. Eu acho essa abordagem muito legal. Posso ter um create, que recebe vários parâmetros diferentes. Eu posso ter três tipos de método create. Não que eu concorde com... Às vezes é melhor você ter um nome diferente diferente para deixar claro qual é a intenção, mas aquele método vai ser estático para poder criar a própria classe, ele está dentro da própria classe. Como eu posso criar uma factory class para poder gerar esse agregado também? Eu quero tirar essa complexidade, essas situações de dentro do próprio agregado, crio uma outra classe. Então, Factory é muito aplicado. Fora que a gente pode usar Factory também para poder gerar repositórios, objetos de valores também. Pode ser que eu tenha objeto de valor, que eu tenha a opção de gerar ele com Factory por algum motivo, é muito aplicável o method Factory, porque eu crio ali a Factory dentro do próprio objeto de valor, facilitando o uso dele, não preciso gerar uma outra classe. E também nós podemos usar nos serviços de domínio. Às vezes você tem ali um serviço de domínio que precisa de algumas dependências, então você pode ter uma Factory para poder gerar também. Outro padrão que é muito utilizado, inclusive, ele é muito citado no livro do Evans, que é o Specification, que é um Design Pattern, que você pode pesquisar por aí. Ele é muito usado para validação de dados. Então, imagine uma situação que você tem ali uma operação de negócio dentro do seu agregado, e você quer validar se essa operação está ok, você pode definir essas regras de validação dentro de specification. Esse design pattern é legal porque ele permite ser combinado com outras regras. Então, eu posso ter, não que eu estou falando que você tem que fazer dessa forma, mas eu posso ter uma specification que verifica se um campo é vazio, outro se ele é nu e outro se ele é um número. Aí eu posso criar uma regra de validação que esses três casos, ele não pode ser vazio, não pode ser nulo, e tem que ser um inteiro maior que um. Então, esse padrão aqui permite que a gente combine as regras, faça um ou ou um end, enfim. faça um ou ou um end, enfim. Além disso, eu posso fazer regras de negócio para validar alguma coisa também. Imagine que eu tenha um agregado de funcionário. Aí eu quero... Tenho ali algum método dentro do próprio agregado que eu quero verificar se ele pode se aposentar ou não. Isso é uma regra de negócio. Então, eu tenho a regra de aposentadoria do momento e tenho a regra de aposentadoria da nova previdência que foi votada e etc. E a gente tem aquelas transições, aquelas coisas. Então, o que eu poderia fazer? Em vez de colocar essas suas regras de aposentadoria dentro do agregado, isso poderia ser duas specifications. Eu poderia ter uma specification para a regra atual, para a nova regra da previdência, e eu tenho ali um método para poder saber se ele pode aposentar ou não. Então, eu passo a specification, obviamente, como interface, e aí ela me devolve se eu pode aposentar ou não. Então, olha que legal. Eu não preciso de ter essas regras dentro do meu próprio agregado, posso criar novas. Inclusive, eu poderia até verificar se ele consegue aposentar com as duas regras, enfim. Esse padrão aqui é muito útil. Tem também várias libs em várias linguagens de programação que acabam utilizando esse padrão. Ele é bom para fazer essa validação de dados e até para poder trabalhar com filtros também. Muitas APIs podem fazer aqueles URs mais complexos que você recebe das coisas da sua URL, utilizando o próprio specification. E aí, outros design patterns que a gente poderia utilizar, mas tem também o mediator que é usado para tratamento de eventos. A gente vai ver ele na parte prática. E outros que a gente precisar. Mas agora falando em padrões de arquitetura, o Vernon já citou a arquitetura hexagonal e agora eu quero aprofundar um pouco mais nisso agora e na parte prática também a gente vai ver. Imagina uma situação que eu tenha um cliente. Será que eu tenho um bonequinho aqui? Imagina que eu tenho lá o meu cliente, que vai realizar a compra. Então, eu tenho aqui o meu cliente fazendo a compra via web, ele vai lá fazer a sua requisição HTTP. Está aqui a minha aplicação. Quando a gente olha para isso aqui, a gente imagina que é o nosso projeto como um todo. Mas quando a gente quer implementar o DDD ali no nosso projeto, se a gente acaba misturando o coração do nosso negócio com bibliotecas, com o próprio framework, nós temos o que é chamado de invasão do domínio. Porque agora o nosso domínio acaba ficando dependente dessas tecnologias. E a gente está justamente modelando o problema, o coração, se importando com ele, para deixar que ele fique isolado. Que, na verdade, o meu framework, as minhas tecnologias, é que dependam do meu coração do software e não o contrário. Então, para que a gente implemente o DDD mesmo, nós temos que trabalhar com arquitetura em camadas. Se a gente não separar o que é apresentação do usuário, do que é regra de negócio, do que é banco de dados, o que vai acabar acontecendo? Nós vamos perder a essência desse domínio. Então, por isso que é recomendado que a gente trabalhe com os conceitos de arquitetura hexagonal, no mínimo, porque é uma forma de a gente criar aqui a nossa aplicação, agregados repositórios serviços de domínio e outras coisas que fazem parte da aplicação em si o que está aqui para fora, vai apenas utilizar essa aplicação. Então, eu protejo, eu tenho esse limite protegendo as minhas regras mais valiosas, as minhas regras mais ricas. E considerando aqui um database qualquer, deixa eu ver se eu tenho um database. Eu não tenho um database aqui. Ah, esse aqui serve como database. Também essas regras de negócio acabam ficando protegidas do que a gente precisa se conectar. Eu preciso me conectar a um banco de dados, a um servidor de e-mail, a uma mensageria ou qualquer outra coisa? Eu tenho essa limitação aqui. Então, por isso que a criatura hexagonal é chamada de ports and adapters. Se você ver lives do Alistair Cockburn, Adapters. A gente vê que a ideia é que se crie um lado que vai dirigir e o outro lado dirigido. Agora, o que tem aqui dentro, na visão do Alistair, não precisa ter necessariamente DDD. Mas dessa forma, se eu tenho aqui a aplicação devidamente protegida, estou protegendo todo mundo que está dali para dentro. Então, na verdade, tanto o banco quanto o cliente, tanto o meu framework, eles usam a minha aplicação. E a minha aplicação não depende de ninguém. É os outros que dependem dela. Então, é muito importante que a gente utilize arquitetura em camadas. Agora, às vezes você pode não ser tão purista, ou ser tão purista, essa discussão vai mais lá na parte técnica, mas se você quer de fato fazer a implementação em nível de código, tem que ter arquitetura em camadas e arquitetura hexagonal. Se você não dividir aquelas responsabilidades, não vai ficar claro aonde estão as nossas entidades, aonde estão os nossos agregados, serviços de domínio, objetos de valores. E outros agentes. A gente vai ter aqui uma dependência forte com ORMs, com frameworks. E aí você fica preso ao modo dessas tecnologias de trabalhar e de fato você não tem uma modelagem rica do seu domínio. Então é basicamente o que a gente tem que ficar atento em relação a design e padrão de arquitetura é isso, fazendo aqui um resumo. Principalmente Factors, Specification, peço para você poder fazer o dever de casa e dar uma olhadinha, Mediator nós vamos ver depois, e Arquitetura em Camadas a gente vai acabar implementando. Show de bola, pessoal! Então, vamos continuar nossa saga, é isso aí, e até a próxima!