E agora aqui, galera, não menos importante, mas normalmente é um padrão que a gente usa demais, que é o padrão repository. Agora, algumas coisas que eu quero falar para você para não gerar confusão com o repository, porque você deve estar pensando. Wesley, qual a diferença de gateway com repository? Qual a diferença de data com Repository? Qual a diferença de Data Mapper com Repository? Qual que é a diferença de Repository com Active Record? O meu Repository pode trabalhar com Identity Map? Eu posso utilizar Unit of Work no meu Repository? Então, parece que a gente começa a misturar todos os conceitos que a gente já viu. E é por conta disso que o Reposit repository é um padrão muito utilizado, mas a gente vai entender em qual momento. Então vamos lá, repository. O repository é uma mediação entre a camada de domínio e a camada de dados usando uma interface para acessar os objetos de domínio tá o que que isso significa significa que todas as vezes tá que você quer fazer com que o seu domínio pegue dados você vai ter o que uma interface e essa interface é interface que a sua abstração de dados vai implementar para você receber os seus dados de domínio. Wesley, mas qual a diferença disso com o Data Mapper? Vamos lá. O Data Mapper apenas faz o mapeamento entre uma entidade de mapeamento com um banco de dados. E isso é totalmente independente do domínio da sua aplicação, da lógica da sua aplicação. O repository é diferente. Por quê? Porque eu vou ter lá os meus objetos de domínio, as minhas entidades de domínio, os meus agregados, os velhos objetos. Aí o que eu vou fazer? Ali na camada de domínio, eu vou criar o quê, no final das contas? Uma interface. E eu vou falar o seguinte, olha, quando eu quiser pegar todos os registros, eu dou um find all. Quando eu quero pegar somente o registro, eu dou um find by id. Quando eu quiser inserir, eu vou dar um insert. Então perceba que a sua camada de domínio que está definindo como os dados vão chegar para ele. Entendeu? Então perceba, o data mapper ele apenas mapeia a entidade com banco de dados e traz retorno. O repository ele faz o quê? Ele cria uma interface de domínio, por isso que a gente fala que repository é um serviço de domínio e não um serviço de aplicação. Existem pessoas que, para facilitar o acesso, colocam essa interface dentro da pastinha de application. Eu acho que o Brandas normalmente faz isso. Eu não faço isso. Eu coloco dentro da pasta de domínio mesmo, por quê? Porque eu acredito que fisicamente ela faz mais sentido, porque ele é um serviço de domínio e não um serviço de aplicação, porque quem está determinando como os dados vão ser recebidos vai ser o domínio e não a sua aplicação, porque caso contrário você teria apenas um data mapper, entendeu? Então essa que é a ideia do repository. Como é que funciona isso aqui na prática? Ele media os objetos de domínio e o data mapper. Então olha só que interessante. Vamos imaginar que eu crio uma interface chamada findAll lá no meu domínio. Aí o que eu faço? Eu crio uma entidade chamada Cliente, um Data Mapper, e faço um mapeamento. Então, no meu objeto, no meu repositório de domínio que eu estou implementando, o que eu vou fazer? Eu posso chamar um Data Mapper, fazer a consulta nos dados, aí o que eu vou ter que fazer? Eu vou ter que hidratar esses dados com os meus objetos de domínio e retornar isso para o meu domínio tá o Wesley tá um pouco confuso né se você olhar na aula do brandas ele faz isso claramente né ou seja você tem a única diferença é que você pode por exemplo no repositório tem um objeto que é em memória ou você pode fazer um SQL puro, ou você pode utilizar um RAM botando um data mapper. Então ali no repository, não necessariamente você tem que usar data mapper. Dependendo da situação, você pode até ter um active record para rodar na sua camada de domínio e retornar os dados de objeto. Então o repository não faz distinção de como o objeto é recebido. O que ele faz a distinção é, ele seta uma interface de como os objetos de domínio vão ter que ser entregues. Como os dados vão ser implementados para serem buscados no banco, não interessa. E aí, nesse caso, eu posso usar SQL puro, posso utilizar RM, posso trabalhar com DataMapper, posso trabalhar com ActiveRecord, TableDataGateway. Não interessa como, você pode utilizar da forma que você quiser. Maravilha? Outro ponto, já falei, né? O repositório recebe os objetos de domínio atendendo uma especificação. Essa especificação é exatamente a nossa interface. Ele retorna os objetos de domínio atendendo uma especificação essa especificação é exatamente a nossa interface ele retorna os objetos de domínio então isso é um ponto importante e é uma característica do repositório o repositório ele sempre vai retornar o objeto do domínio ele sempre vai retornar sua entidade o seu objeto de valor o seu agregado inteiro, principalmente se você trabalha com o Domain Driven Design. É muito comum você encontrar por aí softwares que, o que eles têm no final do dia? Ele cria lá uma pasta repository, ele implementa a busca no banco de dados, não interessa como, e na hora de retornar, ele retorna um array. Ou seja, isso não é um repository. Por quê? Porque esse array não é um objeto de domínio. Você tem que retornar o seu objeto de domínio mesmo, a sua entidade que está na lógica de domínio para o repository. Legal? Você pode fazer combinações. O importante é você seguir a especificação da interface e no final do dia você pode trabalhar com SQL e etc. Uma coisa bem interessante aqui também é que é muito comum você ver o repository utilizado junto com um padrão chamado de specification. Por quê? O que o specification faz? O specification cria critérios para trazer os dados. Então, ele pode colocar um critério assim. Olha, traga para mim como um critério onde o id é igual a 1. Então, isso é um critério de busca. E eu posso injetar esse critério no meu repository. E daí eu consigo fazer as minhas consultas com muito mais flexibilidade. Ou eu vou criar um critério onde o valor pode ser maior que 100 ou o valor pode ser menor que 50. Ou seja, eu crio critérios, passo esses critérios, ou seja, essas especificações para o meu domínio, para o meu domínio não, para o meu repository, o meu repository vai trazer esses dados ali para a gente. Ou seja, é muito comum de você ver implementações de repository recebendo implementações de especificações para você conseguir trabalhar. Depois dá uma olhada aí no padrão specification, que tem bastante exemplo aí para vocês. Bacana? Então, olha só que interessante aqui, galera. Só para não ficar algo tão aberto, porque essa parte do repository é algo que normalmente a gente utiliza no dia a dia. Eu só quero revisar. Não sei se você trabalha dessa forma ou não, mas fica ligado no conceito importante aqui. Primeira coisa, você tem uma specification, tá? Então perceba que ele coloca aqui como interface. Ele coloca, que eu digo, eu coloco, tá? Isso aqui é um programa exemplo em TypeScript, tá? Então eu tenho uma interface de specification que tem ali um atributo genérico ali de um tipo, legal? E existe um método que eu coloquei, isSatisfiedBy, o item tal desse objeto, legal? E ele pode retornar true ou false. E aí o que acontece no meio de toda essa história aí? A gente pode ter uma especificação concreta que a gente vai criar. Por exemplo, user email specification, implement, né, specification de user, né? Eu tenho um construtor onde eu passo um e-mail, e aí eu vou ter ali dentro um método falando, e satisfied by, onde vai receber um usuário e ele vai retornar tá que usuário que eu passei bate com o e-mail né que eu passei no construtor então se o e-mail que eu passei no construtor bater com o e-mail do usuário que eu passei esse critério ele é válido legal então isso é um ponto importante então eu tenho a minha especificação aqui você pode ter diversos tipos de especificação né você pode ter especificação de andy or de short de e então a você pode ter diversas especificações que você quer implementar aí e aí finalmente a gente vai fazer uma busca dos dados. Agora, quem define o formato dessa busca? É a minha interface, é a minha especificação do repository que a minha entidade usuário está dando. Então, essa interface aqui, ela é uma interface que fica na minha camada de domínio, ela não fica na minha camada de banco de dados. Por quê? Porque quem está definindo essa interface é o meu serviço de domínio. Então, isso é um ponto importante. Então, partindo desse princípio, quando eu coloco interface user repository, significa que quando eu for implementar o meu repositório concreto, eu vou ter que seguir o quê? Eu vou ter que passar um método, ter um método findBySpecification, onde eu passo a minha specification de user e eu vou retornar, perceba galera, um array de user. Perceba que eu não estou retornando um array qualquer. Eu tenho que retornar user, porque o meu repositório retorna para mim objetos de domínio. Então, isso que é o ponto mais importante. Então, essa é a minha interface. E aqui, por último, eu tenho a minha implementação concreta do meu UserRepository. Se você perceber, o meu UserRepository, ele implementa, tá? Quer dizer, o meu SQL UserRepository, ele implementa o UserRepository, que é uma interface que a gente tem um método findBySpecification. Então, o que acontece aqui? Esse comentário other implementation details, basicamente, é onde a gente busca com SQL. Select asterisco, eu vou trazer esses dados de alguma forma. Ou eu posso criar outros métodos, não interessa. O grande ponto é que no meu método findBySpecification, eu vou passar a minha especificação e ele vai fazer uma busca aí em um array de users. A gente poderia estar pegando os dados do banco de dados, não interessa. E ele vai ver aqui se o usuário que está passando esse array atende àquela especificação. E qual é a especificação nesse caso? Que o e-mail do cara tem que bater com o e mail do objeto legal se bater ele está dando um push ou seja adicionando usuário no arrem e depois retornando esse a rede usuário aí no final então se você perceber o repositório ele pode você não necessariamente tá galera tem que utilizar uma especificação para utilizar repositórios você pode implementar find by id find by name você pode dar um delete você pode criar find by usuário maior que 10 você pode criar do jeito que você quiser o grande ponto é que quando você cria specifications, você tem mais flexibilidade. Então, mas de forma geral, aqui está o meu repositório concreto, aqui eu tenho a interface do meu repository, aqui eu tenho minha specification completa, e aqui eu tenho a interface da minha specification. Então, no final do dia, eu vou ter esse tipo de resultado, e a minha camada de domínio, ela não sabe como é a implementação do meu repositório, mas ela sabe quais são os métodos que os dados vão ser recuperados. Por isso que a gente diz que repositório é um serviço de domínio e não um serviço de aplicação. Então, essa que é a ideia básica que eu queria trazer de repositóio e não um serviço de aplicação. Legal? Então, essa que é a ideia básica aí que eu queria trazer de repositórios e, inclusive, aqui para a gente fechar um pouco essas histórias aqui de persistências e acesso a dados. Maravilha? Um grande abraço e é isso aí.