[MÚSICA] [MÚSICA] Olá, bem vindo ao curso de Orientação a Objetos com Java. Eu sou o Clovis Fernandes. Hoje iremos mostrar a Law of Demeter, a Lei de Demeter para abaixar ou impedir que acoplamentos ou dependências indevidas sejam feitas entre classes. Esse é o objetivo então, mostrar a lei, Law of Demeter, mostrar como é que ela, o que é que ela, esse princípio o que que é que ele propugna e como isso pode ser feito na prática para diminuir esse, acoplamentos desse tipo. Anteriormente nós examinamos o uso indevido de getters que devolvem objetos da sua classe de aplicação e mostramos que isso causa número grande de dependências. A ideia é não criar essas dependências assim que você produz o seu software, ou se algum momento você produzir vai precisar fazer uma refaturação, mexer no seu código para aperfeiçoá-lo, para retirar essas dependências. Uma solução para casos desse tipo é aplicar uma combinação dos princípios Tell, don't ask, redirecionamento ou delegação, e a Law of Demeter. Quer dizer essas 3 coisas vão ajudar você a produzir software com menos dependências, só com aquilo que é extremamente essencial, ou aperfeiçoar código antigo ou código já feito que tinha essas dependências e mostra então como você pode eliminar essas dependências. A Law of Demeter, foi criada num projeto do mesmo nome, final da década de 80, e o artigo, foram pioneiros nessa área de orientação a objetos, o link está logo ali baixo. É projeto que teve uma duração muito grande e eles tiveram impacto muito grande na área de desenvolvimento de objetos adaptativos e flexíveis e etc., mas dos grandes legados deles foi a publicação de 1988 explicando, depois de uma pesquisa intensa de uso e verificação do que estava atrapalhando, fazer o desenvolvimento, a manutenção, o reuso e mudanças de requisitos, eles perceberam, não é, concluíram que alguma coisa tinha sido descoberto e essa coisa é o que eles denominaram de Law of Demeter. Eles perceberam que o que estava causando essas problemas todos, essa dificuldade, dependências muito grandes, acoplamentos muito grandes entre as classes, era a forma desordenada de passar mensagens de objeto para outro objeto. Então eles perceberam que ao limitar, para dado método, poderia lá dentro do seu código, da sua lógica ali dentro, poderia mandar mensagens para outro objeto, para quais objetos poderia ser mandado mensagens? Então isso foi uma coisa muito importante porque ajuda a definir, tanto na hora quando você, usando uma metodologia CRC ou usando qualquer metodologia para projetar as classes, você consegue seguindo esse princípio, você não vai produzir dependências está muito bom, isso é ótimo, uma coisa bem clara. E de outra forma, se você já tem código, que já está cheio de dependências, feito por alguém ou por você mesmo sem ter aplicado esse princípio, você vai ter uma forma bem clara do que é que está ocorrendo. No caso, uma coisa que fica patente, é que eles perceberam que quando você manda mensagens indiscriminadamente e você tem acesso a classes que não deveria ter acesso, por causa da exposição que acaba ocorrendo, principalmente de getters de objetos, você acaba então se comunicando com quem não deveria. Então, se você vai se comunicar você vai ter conjunto de amigos, quem são esses amigos? É isso que a gente vai mostrar agora, examinando o que é que é a Law of Demeter, carinhosamente chamada de LoD aqui por nós, determina. Então nós vamos nos centrar mostrar os envios de mensagens, as invocações de serviços de outras classes. Quais são os objetos que dado método de dado objeto, pode invocar? Então, a LoD determina que ele só pode invocar métodos de 5 tipos de objetos. Desses 5, 4 são ainda considerados próprios, o quinto a gente vai descartar, eu vou mostrar e falar daqui a pouco. Então, o primeiro é o próprio objeto, se eu preciso da colaboração de algum método da minha própria classe, isso, fora de dúvida, eu posso usar. Tanto métodos privados, protegidos ou públicos da minha própria classe, eu posso usar. O segundo tipo que eu posso usar, são os parâmetros do método que eu estou definindo. Então, se o método define que uma classe A vai ser passada como parâmetro, então, eu posso mandar mensagens para objetos dessa classe A que eu estou recebendo como parâmetro. E o terceiro, quaisquer objetos que você pode instanciar. Por exemplo, a qualquer momento eu posso usar por exemplo, String que é objeto de uma classe String de Java. Se eu posso usar de Java, eu posso usar de outros métodos da minha aplicação. Geral, naquele momento, eles vão ser objetos auxiliares, eles fazem alguma colaboração e eu vou usá-los, não está impedido de fazer esse uso, de acordo com a necessidade. O quarto tipo, são os objetos que estão lá nas variáveis de instância e que são variáveis de instância de relacionamento, ou seja, são objetos de classes da minha aplicação, não valem aqueles objetos que são auxiliares da classe Java. O quinto, que hoje não é mais considerado aceitável, não é uma boa prática, seriam o uso de objetos globais. Como o professor Guerra já mostrou outras aulas, usar objetos globais não é uma coisa aceitável atualmente, porque embaralha muita coisa no programa, causa problema muito sério, então isso não se usa. Eu vou exemplificar aqui, estou exemplificando aqui, conjunto de classes são, é conjunto fictício, mas é só para mostrar, que eu tenho aqui as classes A está se relacionando explicitamente com a classe B, ou seja, a classe B, vocês percebam que ele é atributo lá de A, não é, está certo, tem relacionamento explícito. A classe E, aliás, o A tem relacionamento com o próprio A, está certo, com a classe E e com a classe D. Ele não tem relacionamento explícito com as classes F, C e G. Logo aí baixo, eu mostro a lógica do método mA1, como parâmetro da classe D, na classe A, é o método mA1, parâmetro D, nesse momento é argumento D, que não volta nada, na classe A, vamos examinar isso mais de perto. Eu aproveitei para numerar de 1, 2, 3, 4 e 5, que o 5 eu já estou dizendo: não é para usar porque se refere a varável global. Então, enquanto na época de 1988, isso ainda era comum, se usar muito variável global, e era herança da programação estruturada e de linguagens da época, que favoreciam esse uso de variáveis globais, hoje não é recomendado, então isso está fora e não vou mais comentar sobre isso. Eu numerei então, 1, 2, 3 e 4, para exemplificar. O número 1 é porque a regra lá do LoD, estava dizendo que eu posso mandar mensagens para o próprio objeto, então está aí this, eu estou mandando para o mA2, esse método é o mA1, como está aí no topo. Eu estou mandando para outro objeto da classe A. O 2, eu vou mostrar daqui a pouco, ele se refere a atributo, está aí cima, não é? Como a gente viu o mA1, o atributo D, então ele é atributo e eu posso mandar mensagens para ele. O 3, a classe E, eu estou criando, porque eu preciso fazer algum serviço que o E presta para mim, ele vai me fazer uma colaboração, que só ele pode me fazer essa colaboração, então eu estou usando, eu posso. E o 4, é usando o objeto B que é objeto, que é uma variável de instância da classe A. Então, agora identificando no diagrama, pelo número 1, vocês percebem que existe uma dependência recursiva, ou seja, o objeto A depende do próprio A, que sentido é que ele depende? Na lógica dele, o método mA1 está fazendo uso do método mA2. Então, isso é uso reflexivo relação à classe, não é, está certo, é outro método da classe. O 2 vocês percebam que o D é argumento lá do método mA1 então eu posso enviar mensagens para o objeto que está sendo passado como parâmetro para mim. O 3 é é uma dependência que eu tenho do objeto da classe E, simplesmente ele tem serviço que eu quero realizar e eu posso realizar, isso está perfeitamente, é aceitável. E o 4 é quando, é uma variável de instância. Então B, vocês podem dizer que o bêzinho ali, ele é do tipo B, então existe relacionamento forte, ele é uma variável de instância então essa, essa dependência aí é explícita. Na classe mA1 eu só estou colocando aquilo que eu posso fazer, eu só posso me comunicar com o que eu vou chamar os amigos do A, aqueles que o, a Lei de Demeter, a Law de Demeter me permite que é próprio B, o E e o D, eu não posso falar com F, o C e o G. Mas, vejam aí essas setas vermelhas apontando aí, existem métodos que devolvem E por exemplo, logo cima a classe E, o método mE2 ele me devolve alguma coisa, objeto da classe F. Na classe B, o método mB3 me devolve alguma coisa que é objeto da classe C e o método na classe D, o mD2 me devolve uma, objeto da classe G. Normalmente eles são getters de objetos não necessariamente getters simples, às vezes são métodos mais complicados que voltam, devolvem como parâmetro os objetos da classe F, C e G, então não necessariamente são getters puros. Vocês vejam aí que os dados, se eu usar esses getters eu acabo tendo uma exposição de quem é, quem são as classes F, objeto da classe F, objeto da classe G, porque os dados que são no caso objetos, estão expostos, então lá na classe A eu vou ter acesso a todos esses dados. Eu vou exemplificar aqui só criando a classe A, E e F exemplificando que o método mA1 da classe A ele tem uma ação desejada que é realizada pelo, se eu considerar que E é o amigo de A, ou seja tem acesso direto ao E, aí por intermédio do E e através do getters que é o mE2, eu obtenho objeto da classe F que faz a minha ação desejada, ele faz o que eu desejo. Posso chamar o mF1 já que o mE.mE2 me devolve objeto da classe F e aí eu posso então mandar a mensagem mF maiúsculo. Então se eu considerar que o E é amigo do A, porque é nele que eu tenho acesso direto, o F é o amigo do amigo de A e isso aqui não é uma coisa boa, eu não posso considerar que o amigo do amigo do A seja uma coisa boa, no nosso projeto aqui não é coisa boa. O LoD tem outro nome que é o Don't Talk to Strangers, Não Fale com Estranhos e o amigo do amigo vai ser estranho para você porque você vai ter uma dependência. Vocês percebe que existe uma seta saindo do A até ao F que é uma dependência indevida, redundante, porque eu estou, eu tenho uma forma de acessá-lo através do E, porque é que eu vou precisar ter essa redundância de dependências entre o A e o E e o A e F se eu precisei do E só para acessar direto F, não tem sentido isso. Então a gente vai carimbar isso como sendo Não fale com Estranhos. Isso é a essência da Lei, da Law of Demeter, da LoD. é o, na verdade muitos chamam que o princípio é Don't Talk to Strangers ou Princípio a Law of Demeter. O princípio Don't Talk to Strangers que personifica a Law of Demeter, a LoD, ele deve ser seguido tanto para eliminar essas dependências quando elas já existem já estão colocadas no meu código, mas principalmente, isso é muito importante, principalmente para eu evitar produzir isso quando estiver projetando as minhas classes, quando estiver projetando as responsabilidades, as colaborações, as classes, as lógicas das responsabilidades. Nessa hora de estar pensando a lógica da responsabilidade eu vou estar pensando seriamente nesses princípios: Tell, Don't ask, Law of Demeter porque vou estar organizando e automaticamente produzindo código melhor, de qualidade melhor, Então isso é importante. diagrama do meu exemplo, no fundo o que ele está querendo dizer é, eu coloquei aí quadrado reticulado separando quem pode conversar com o A e quem não pode. Quem está dentro desse quadrado, que é o próprio A, eu posso conversar com ele mesmo, não é, está certo? Na verdade eu posso conversar também com as super classes do A, que eu não estou colocando aqui, a Law of Demeter faz uma certa separação sobre isso, nós estamos usando a forma mais fraca da Law of Demeter. A classe E, a classe B e a classe D são os amigos do A então estão aqui, esses eu posso conversar. Agora conversar com lá fora eu não posso, então do jeito que o código está aqui, por convenção eu não estaria usando algumas coisas, como por exemplo na classe E o método mE2 que me volta objeto da classe F. Espera mas se eu estou fazendo isso por convenção, não vou usar, porque é que eu pus então esse método lá não ter esse tipo de coisa. Então o LoD oferece uma solução de 2 passos que você vai ficar aplicando todas as ocorrências. Eu vou mostrar no exemplo de leitura a aplicação naquele sistema de logística que eu vou mostrar isso sendo aplicado passo a passo e você vai usar o princípio Tell Don't Ask e o Redirecionamento Delegação. O que é que é o Redirecionamento Delegação? Normalmente você vai encontrar isso sendo tratado como delegação, que é alguém faz alguma coisa para você, ou seja, você precisa de uma colaboração você passa para a outra classe fazer isso para você, então a gente chama de delegação. Normalmente quando o método que você está delegando tem o mesmo nome do método que está invocando aquele outro, aí é redirecionamento, é o mesmo nome, então pode ocorrer as duas coisas na verdade. Determinado momento eu uso redirecionamento porque eu vou chamar o próprio, no meu exemplo a seguir eu vou usar redirecionamento porque eu vou usar o mesmo nome do método, quando eu for resolver no Tell Don't Ask porque eu tenho lá uma ação desejada, não é, eu quero transferir isso para outro lugar e aí eu faço redirecionamento, eu simplesmente chamo o mesmo nome do método e aí fica mais simples. Então essa combinação, isso e a Law of Demeter quando o código já está cheio ou corre o risco de estar cheio de acoplamentos, dependências. A Law of Demeter também tem o lado de projeto, quando eu vou criar pensando nessas restrições e não produz essas dependências indevidas. Voltando aqui no meu exemplo das classes A, E e F, se vocês olharem antes do jeito que estava eu tenho duas dependências, não é? Nesse exemplo que estou dando aqui, que eu faço com que o mA1, o método mA1 do A, ele acessa a classe E, manda uma mensagem mE2 e volta objeto F, aí eu posso mandar o método mF1 para esse objeto F, que é essa segunda seta que tenho, vermelha que está apontando a dependência aí. Então eu tenho duas dependências, então se eu estiver no meu sistema como todo isso aí eu posso ter muitas dependências desse tipo, a toda a hora pode ocorrer dependências desse tipo. Como é que eu resolvo? O Tell Don't Ask, a ação desejada que está aqui na lógica do mA1 eu passo para o E e é redirecionamento que eu vou chamar lá o novo método que vai encampar esse E.mE2.mF1 eu vou dar o mesmo nome que é no mA1 só que vai estar lá na classe E. Eu estou supondo aqui só que é nome qualquer, está certo, ou seja há uma repetição desse nome, porque ao repetir o nome você está repetindo a responsabilidade daquele, correspondente aquele método. e a responsabilidade do mA1 vai ser a mesma do, de A, vai ser a mesma do mA1 e eu estou transferindo para E. Como é que eu faço isso agora, olha, se vocês olharem agora aqui, que é que aconteceu comparação ao anterior? Olha, tinha 2 dependências setas vermelhas, agora eu tenho uma dependência só se vocês olharem, vamos olhar para a lógica do mA1 da classe A, agora ele simplesmente faz assim E.ma1, ou seja eu transferi lá para o E, vocês podem ver que lá no E agora tem método mA1, e esse mA1 faz exatamente aquilo que eu estava fazendo na minha classe anterior no método de A. Está aí do lado, na nota, mostrando o código do mA1 de E. E no código de mA1 da classe A eu simplesmente redireciono por isso que eu estou chamando de redirecionamento, eu redireciono. Pronto, simples, ou seja eu estou aplicando, ao fazer essa, esse redirecionamento eu estou aplicando simultaneamente o princípio Tell Don't Ask lembrando que às vezes pode valer a pena não fazer redirecionamento, ser uma delegação quando o método é diferente. Aí eu mostro o antes no mA1(D) e o depois no mA1(D), todos da classe A. Pode ver que claramente houve uma mudança não é, eu estou simplesmente fazendo redirecionamento lá para a classe E do método mA1. Eu estou simbolizando que chamo o mesmo método da classe A só para dizer que é redirecionamento o nome é o mesmo. Com isso pessoal nós mostramos a Lei de Demeter, Law of Demeter, a LoD, ela tem papel de diminuir o acoplamento entre classes. Eu posso fazer isso desde o projeto projetando seguindo aquelas regras, que aí eu já vou só conversando com os amigos daquele objeto do qual eu estou projetando, daquela classe da qual estou projetando as suas responsabilidades, as lógicas das suas responsabilidades, vendo quem são as suas colaborações, seguindo isso e o princípio Tell Don't Ask, eu estou num bom caminho. Agora se eu não, não seguir isso eu estou com código na mão que tem muitas dependências eu vou aplicar agora, como eu mostrei, uma combinação do Tell Don't Ask e do Redirecionamento Delegação e faço com que a minha aplicação seja mais flexível, tenha menos dependência e seja, tenha código mais fácil de manter. Obrigado! [MÚSICA] [MÚSICA]