Olá pessoal, tudo bem? Sejam todos muito bem-vindos a mais uma aula. E na aula de hoje a gente vai dar continuidade à modelagem das nossas entidades de domínio. Não só entidades como o Valley Objects, como o VOS, raízes de agregação, os agregados. Então a gente vai dar continuidade aqui no mapeamento deles, a gente vai mapear os Events e a gente vai mapear os Tickets tambémamento deles. A gente vai mapear os events. E a gente vai mapear os tickets também. Ticket passa a ser um agregado agora. E vou explicar o porquê. Mas antes, algumas considerações. O value object de name realmente é necessário? Tem literatura que fala que não precisa. Tem literatura que fala que não precisa. Tem literatura que fala que é bacana. O que você deve levar em conta? Por que a gente está encapsulando ele em um value object? Normalmente, a gente encapsula algo em um value object quando ele é composto quando o seu valor é quem define a igualidade dele e ele é imutável a string ela já é o name poderia ser só uma string dentro de customer e partner? poderia ainda mais que a gente não tem tanta validação a gente só verifica se é nulo, se for nulo não pode ter, diferente do cps por exemplo que a gente colocou uma validação, a gente só verifica se é nulo, se for nulo, não pode ter diferente do CPS, por exemplo, que a gente colocou uma validação mínima aqui do CNPJ também, a gente colocou uma validação mínima que faz sentido estar encapsulada aqui nesses objetos de valor o name, por exemplo, não justifica, então poderia ser uma string fora ali no customer ou no partner mas como a gente já tava praticando, não tem problema deixar assim. Aqui no customer, vamos ver, aqui no customer a gente tem em todas as entidades, todas as entidades, sendo ela raiz de agregação ou não, o identificador tem que ser final. Por quê? Porque o identificador não pode mudar nunca ok? E eu havia esquecido de colocar aqui os finals, né? Pela sua própria característica, uma entidade cuja sua igualidade é comparada através do seu identificador, que todos os atributos podem mudar ela automaticamente já é entendido que ela precisa ter o seu identificador protegido de qualquer mudança. Então, é esse ajuste. Aí aquiza, então era só isso de considerações por hora. Beleza, então vamos lá, o que a gente vai fazer? Agora a gente vai mapear a nossa entidade de evento, vamos corrigir o caso de uso e corrigir o teste. E a de ticket, como essa de evento provavelmente vai durar mais tempo, possivelmente a de ticket vai ficar pra próxima aula. Mas não se preocupem que tem muita coisa bem legal aí. Então, vamos lá. Create event use case. Ó, tudo aqui, ó, isso aqui vai pra vala, né? Vamos começar com esses dois aqui. Só que pra, antes de excluir eles a gente precisa criar o nosso repositório mas antes precisa criar nossa entidade obviamente vamos lá vamos criar vamos começar com a entidade aqui ó event a gente já sabe que ela é uma entidade então ela vai ter o event id é uma outra consideração esse esse event id, ele necessariamente precisa estar mapeado aqui como uid? Não necessariamente, tá gente? Isso aqui poderia ser uma string, porque o próprio event já tem essa semântica de encapsular o identificador e é aqui por exemplo a gente colocar em um toString e aqui depois de verificar que de fato é um identificador válido através do uid fromString a gente colocar toString novamente tá só que por hora como já tá assim o uid vamos vamos manter nesse padrão, né? Ou a gente corrigir pra tudo? Não, vamos fazer o seguinte, vamos corrigir pra tudo e aí, acho que vai ficar mais interessante. Porque daí a gente tira aqueles value to string lá de outros casos de uso, ó. Customer ID, aqui também, event que já foi, e aqui, string to string string string beleza e se a gente ver aqui no useCase vamos rodar ele vai quebrar né porque alguns casos de uso estão esperando por exemplo useCase createCustom customer esse cara aqui a two string quer dizer ele não vai quebrar justamente por conta da redundância que é permitida né o two string do two string mas when o parametro is null where enfim aqui no get a mesma coisa a gente pode tirar isso aqui e aqui no get a mesma coisa a gente pode tirar isso aqui beleza, então agora voltando lá pro nosso event event id a gente vai colocar aqui event id, aqui event id, ele já está com uma string, beleza. Agora vamos lá, private, final, event id e event id. O que a gente mais vai ter aqui? Vamos lá dar uma olhada no event, só para colar. Então a gente tem name, data, total spots, partner e tickets. Só que tem um detalhe, tá? Isso aqui representa a tabela do banco. Isso aqui é a tabela do banco. O ticket, ele não vai ser pra gente, agora que a gente está aplicando um EDD, a gente está aplicando uma layer de domínio, ele não vai ser para a gente, agora que a gente está aplicando um EDD, a gente está aplicando uma layer de domínio, ele não vai ser para nós uma simples entidade aqui. Por que ele não vai ser uma simples entidade? Porque pelo fato de ser uma lista e cada ticket ter a sua propriedade mutada de maneira independente uma da outra e concorrente, inclusive, porque pessoas podem comprar tickets para o mesmo evento ao mesmo tempo, muito próximo e podem vir eventos para alterar propriedades de cada ticket. Então, o nível de concorrência é alto para a gente manter o ticket como sendo uma simples entidade dentro do evento. Vai haver uma probabilidade de ter problema de concorrência muito grande. Porque, se ele está dentro do evento, a gente precisa obter o evento, obter todos os tickets, alterar um único ticket e persistir tudo de novo. Do ponto de vista de performance e de armazenamento não tem cabimento algum por isso que o ticket vai se tornar um agregado porque a gente quer poder manipular cada um deles individualmente e aí a validação da quantidade de evento da venda de quantidade de evento versus a quantidade de tickets disponível a gente vai fazer depois através de domain events vamos lá, vamos colocar da venda de quantidade de eventos versus a quantidade de tickets disponível, a gente vai fazer depois através de domain events. Então, vamos lá, vamos colocar isso que eu acabei de falar em prática. Name, a gente sabe que a gente já tem o value object. Local date já é um próprio value object. E int, está tudo bem a gente usar int aqui porque não tem muito o que encapsular em total spots. Além disso, a gente vai ter o partner ID aqui Beleza Agora, o que a gente vai fazer? Vamos criar o construtor com todos eles Só que aqui é string Aqui também é string, né? Vamos colocar integer aqui E o partner ID Aqui, beleza Quer dizer Afim de proteção Esse cara até pode ser uma string Afim de proteção Poderia ser uma string Poderia ser uma string Mas Não tem problema Vou manter como partner id aqui e se event id é igual a nulo, a gente vai lançar um throw e o validation exception e aí deixa eu copiar a mensagem dos demais aqui por exemplo só para manter o mesmo padrão event id invalidade for event beleza que mais name não precisa validar porque name já vai ser automaticamente validado aqui. Date, date também não precisa validar, porque ele vai ser validado aqui com o DateTimeFormat isLocalDate. Deixa eu ver se é essa mesmo aqui, beleza. se for requires a new message formatter entendi, muito interessante essa mensagem então vamos validar date sim invalid date for event deixa até colapsar esses ifs aqui vamos colar aqui agora total spot invalid total spot for event e por último o nosso querido partner o partner aqui show de bola então já estamos validando garantindo que nenhum desses caras que não podem ser nulos estão nudos né agora o que a gente vai colocar aqui? Public, static, event, new event. Quem que o novo evento recebe? O novo evento, ele vai receber basicamente, isso aqui tudo. Deixa eu ver se eu coloquei nos demais aqui. Tudo final, final, final. Aqui faltou. Mas ok, né? Então como eu falei pra vocês Eu gosto de colocar final em tudo É um Um bom hábito que cada um de vocês pode Pode adquirir Return new Event Event id unique Aí name Date, total spots Partner id Beleza Unique Name, Date Total Spot Partner ID Beleza Aqui tem um detalhe, a gente pode receber O Partner ID Ou a gente pode receber o Partner E pegar o Partner ID dele No Implementing Domain Driven Design Você vai ver Que o Van Vernon Vernon usa dessa forma. Ele recebe o outro agregado e depois só usa o identificador dele. Tem outros autores, como por exemplo o do Learning Domain Driven Design, o Vlad. ele comenta, ele não comenta tanto sobre isso, mas também deixa aberto para cada um colocar o que quiser. O Rodrigo Branas, por exemplo, ele gosta de só mapear o identificador aqui. Então, você só passa o identificador. Por que eu gosto dessa abordagem? Porque obriga, de fato, a passar uma instância de partner, passar o agregado partner construído, e assim a gente garante a sua invariância, a gente garante que ele está perfeito para ser realmente utilizado aqui nesse evento. Mas, se quiser mapear só o identificador, mapeie só o identificador. Beleza, então já temos o nosso evento aqui, pelo menos o básico dele. Agora o que a gente vai fazer aqui? A gente vai criar o repositório. Então vamos criar aqui, event repository. Tudo que for partner vai se tornar event. E aqui a mesma coisa. E aí esses dois valem. Beleza. Agora vamos lá no caso de uso, né? Vamos trabalhar nele porque 12 minutos, 13 minutos de aula, então agora a gente faz ele, corrige os testes e depois a gente faz tudo o ticket. Então, event repository na verdade eu deixo fazer o seguinte eu deixo substituir isso aqui só selecionar esses dois event repository eu vou pá pá pá event repository beleza agora aqui também par repositor e aqui o repouso de torre bem mais rápido né tira o importe não estamos usando a gente já do parque para construir o evento. Então a gente vai precisar dele aqui na frente. Então, ó. É partner of id. Aqui a gente está recebendo date, string, string, long. Não é mais long. Agora é string, partner id e integer total spots. E aqui também o retorno não é mais long, é string. E aqui é string. Então, ó. Partner with. e aqui é string então ó partner with or else throw e ele demanda um supplier disso aqui e a gente vai usar a ideia pra reduzir aqui, legal final var a partner então já temos o nosso partner aqui agora a gente pode chamar event. Ah, o event está importando errado, a única coisa de infrastructure aqui então vamos importar o certo de application e aí event new event input.name, input.date, input.totalSpots e aPartner. Beleza. Instanciamos. Agora a gente pode chamar o repository, repository, né? anEvent, var, opa, anEvent e aqui é basicamente create passando isso aqui ponto e vírgula no final beleza, então aqui a gente tem a nossa instância de evento já criada a gente pode utilizá-la aqui, id event id .value input date a gente vai usar o do da própria data mesmo porque já está vindo um formato válido event.name .value event.total spot event.partnerId.value E aí a gente pode aqui, por exemplo, quebrar as linhas só para ficar mais fácil de ler. Beleza, então criamos nosso evento aqui. Beleza, então criamos nosso evento aqui. Agora, a gente pode corrigir o teste do CreateEventUseCase. Vamos lá, deveria criar um evento. Data, nome, total spots, partner, id. Ah tá, isso aqui já não é mais válido então a gente pode usar por exemplo partner id.unique e é porque não tem mais partner service aqui, agora é partner repository event repository, então event repository partner repository, deixa eu só ver, ah, a gente criou em memória, né, para os outros aqui é podemos continuar com essa abordagem então vamos lá o partner repository na real já existe o new partner repository new in memory partner repository a gente só precisa criar um pro evento Então vamos criar aqui InMemory Event Repository Aí a gente tem Events E aí a gente só tem esse Events Ele implementa Event Repository Vamos mudar ele implementa event repository vamos mudar aqui ó, isso aqui tudo que é ele vai virar event de application import event id beleza event require plan ponto toString esse cara, opa esse, o cacete esse toString aqui não precisa mais ele retorna um event isso aqui não tem e esse aqui tem outro nome, event of id e aqui a gente vai colocar event event esse aqui tem outro nome evento of id e aqui a gente vai colocar event.event.valet e a gente vai passar o event aqui ele só precisa atualizar um único index aqui ó, pá aqui a mesma coisa beleza, vamos saber se tem alguma coisa de customer, não tem nada de customer, então aqui ó, agora a gente também não precisa mais do moquito, new in memory in memory event repository, ó aí o que que a gente precisa só vamos subir isso aqui pra cá partner find by id então na verdade o que a gente vai fazer é partner repository.create Create new partner com o nome, pode ser John Doe, CNPJ. Vamos lá no partner para pegar esse valor aqui, esse CNPJ. E o último é e-mail, vamos pegar um e-mail no partner também partner e-mail bacana inclusive partner id na verdade a gente pode fazer o seguinte, expected, vamos duplicar essa linha, aPartner, e aí vamos colocar isso aqui pra cima, vou quebrar uma linha aqui e vou utilizar esse cara ponto parte da lei de futebol a gente manda criar aqui agora beleza event de lancer isso aqui não precisa mais event repository partner repository papa pax pack partner id ponto velho e o partnerId.Valley opa, peraí .Valley inclusive já que é .Valley a gente pode usar .Valley ali também beleza não deve criar um evento quando o partner não for encontrado ok, então vamos fazer a mesma coisa aqui distanciar partnerId não for encontrado ok então vamos fazer a mesma coisa aqui ó distanciar partner id a gente vai colocar aqui um partner id.unique.value isso aqui não precisa mais e a gente só vai passar e 20 repositorio e partner repositorio aqui e a gente vai rodar os testes para ver o pa um cliente event resolver partner a tap que agora ele estava esperando um long mas na verdade o partner é uma string agora. Aqui já mudou, aqui vai quebrar porque a gente ainda não tem esses caras. Então vamos só copiar aqui, fix dependence, que a gente vai corrigir isso aqui na hora que formos mexermos nos secondary actors. Tá bom então agora é o integration test ele já tem o event repository e o partner repository, só que esse repositório é outro cara Mas ok Ó, vamos por enquanto Deixar aqui ó O toString CreatePartner Não, se bem que a gente tem Ah tá É porque esse aqui Ele já tá, o teste integrado do caso de uso, ele não consegue ser... A gente não consegue utilizá-lo ainda justamente porque... Deixa eu ver se eu corrigi esse aqui. Customer repository, hexagonal application infrastructure. É, exato. A gente não consegue corrigir ainda porque a gente não tem todas as partes do nosso caso de uso dentro do framework a gente precisa ainda implementar a última ponta, então obviamente ele ainda não vai funcionar mas vamos corrigir só o build aqui partnerid.unique.value Disney.toString Disney.toString event.long.partilong Só para continuar funcionando, né? e event long.parse long só pra continuar funcionando, né? Beleza. Tá bom. Só tá quebrado os testes integrados. Se a gente rodar só o nosso creative end-to-use case test, ele tá passando bonitamente. E aí na próxima aula a gente vai fazer a parte do domínio do ticket e depois fazer essa última ponta, que é a parte dos secondary drivers, secondary actors, os driven actors. E aí a gente depois vai trabalhar com o domain events. Então vamos lá. Vejo vocês na próxima aula.