Object Calisthenics: LEI DE DEMETER - A Técnica Para Eliminar DEPENDÊNCIAS Ocultas no seu Código!

16.07k views3637 WordsCopy TextShare
Renato Augusto
📚 Leituras Recomendadas: 🔗 Aprenda Domain-driven Design: Alinhando Arquitetura de Software e Estra...
Video Transcript:
Falando sobre boas práticas de programação e objectics, temos a Lady Demitter, que foi criada em 1987 por Ian Holland no projeto Demiter do MIT. E a ideia era conseguir promover baixo acoplamento e alta coesão no design de software orientado a objetos. E é essa lei poderosa que eu vou te ensinar no vídeo de hoje e também como que você consegue aplicar ela no seu cônico.
Fala pessoal, Renato Augusto aqui de novo e dessa vez para te ensinar a lei de demit que está relacionada a uma das nove regras do objectalistenics. Essa lei também é conhecida como princípio do menor conhecimento e é uma prática recomendada que visa reduzir o acoplamento entre os nossos objetos, fazendo com que eles interajam apenas com os seus vizinhos imediatos e não com objetos que estejam além do seu alcance direto. Então, sem mais enrolação, bora pra tela.
Vamos entender como que a gente consegue aplicar essa lei no nosso código e qual é a relação que ela tem com as nove regras do Objectistenics. Bora lá. Bom, então vamos lá.
Para você que ainda não conhece ou nunca ouviu falar de Objactistenics, basicamente são esse conjunto de nove regras aqui que foram criadas por Jeffb estão descritas neste livro aqui. Esse calistênix vem literalmente da palavra calistenia, ou seja, exercitar a nossa orientação a objetos e com isso tem um código com muito mais maturidade, muito mais próximo dos princípios sólidos e também das boas práticas de programação. Nos vídeos passados, eu já te mostrei todas as regrinhas aqui que estão em verde.
Te mostrei também as técnicas para você implementar cada uma delas e o problema que cada uma delas tem caso você não siga. Então, se você não assistiu, depois que acabar esse vídeo aqui, dá um confere lá. Vou deixar um card aqui em cima e o link na descrição.
E não existe uma cronologia para você poder assistir. Você pode assistir esse vídeo aqui e depois você assiste os outros, não tem problema nenhum. No vídeo de hoje a gente vai falar da regra de número cinco, que diz que a gente só deve ter apenas um ponto por linha.
Eu vou te mostrar no código o que que é esse ponto aqui e que isso tá relacionado à lei de Demitter que diz que não devemos falar com estranhos. E aí quando a gente não segue essas regrinhas aqui, principalmente a lei Demitter, que basicamente são a mesma coisa. A lei de Demitter quanto a regra de número cinco são a mesma coisa, só que a lei de Demitter foi criada muito antes do Object Calistenics, mas como era um conceito que não era tão difundido assim na época, o Jeff Bay pegou essa lei e acabou incorporando aqui no Object Calistenics como mais uma das regras ali para ser seguidas.
Então, como consequência da gente não seguir isso aqui, a gente vai ter a quebra do encapsulamento, a gente vai gerar um alto acoplamento entre as nossas classes, a gente vai ter dificuldade de manutenção, a gente vai prejudicar os nossos testes unitários e isso tem uma relação muito próxima com o agregate root do domain driven design. Então, se você nunca ouviu falar de agregate root ou de modelagem tática do domain driven design, eu vou passar bem por alto ali, e vou te mostrar a leve relação que essas coisas aqui tem. É, como eu sempre digo, orientação a objetos está muito próximo de domain driven design, de clean architecture.
E tudo isso eu te mostro aqui vídeo a vídeo. Então, sem mais enrolação, bora pra tela. Vamos entender como que a gente consegue aplicar isso aqui no nosso código e vamos sair daqui com um código muito mais orientado a objetos e muito mais próximo das boas práticas.
Bora lá. Bom, então vamos lá. Indo direto ao ponto para você entender qual que é a motivação e quais são os problemas que a lei de demiter resolve.
Eu vou te mostrar alguns exemplos de código aqui. E lembrando que tudo que eu te ensinar aqui é completamente agnóstico de linguagem de programação. Então tu vai conseguir implementar no Java, no PHP, no Typescript, no Python, onde você quiser, desde que a tua linguagem dê suporte ao paradigma orientado ao objeto, porque tudo que eu te mostro aqui é fundamento, é princípio básico das boas práticas e da arquitetura de software.
Beleza? Então vamos lá. O que que a gente tem aqui?
A gente tem aqui três classezinhas bem simples, tá? Classes de exemplo aqui que a gente vai fazer uma pequena simulação aqui que a gente tá trabalhando no e-commerce. Então, começando aqui por essa classe order aqui, que representa um pedido no nosso sistema.
Ela é uma classe bem inxuta, tem apenas um customer aqui que representa um cliente, ou seja, o cliente que fez esse pedido. E a gente tem aqui um get customer aqui que retorna esse cliente aqui para quem chamar essa classe aqui, quem quiser utilizar. Beleza?
A gente tem o nosso customer aqui que representa o cliente no nosso sistema e esse cliente ele tem um relacionamento aqui com o endereço. No endereço aqui a gente tem aqui duas propriedadezinhas que é o zip code e a cidade. Esse zip code aqui representa o CP, né?
E aqui, logicamente a gente poderia ter mais propriedades, assim como nas outras classes. Então, por exemplo, aqui no pedido, a gente logicamente deveria ter o valor desse pedido, os produtos ou os itens que compõem esse pedido. Só que a ideia aqui é justamente exemplificar, é tornar a coisa simples para que você consiga entender qual é o problema que a lei de Demit resolve e como que você consegue implementar isso no teu dia a dia, beleza?
Então, voltando aqui no nosso endereço, a gente tem aqui o nosso zip code e a cidade e a gente tem aqui um getter aqui para cada um deles. Beleza? Tudo muito simples, tudo muito básico, tudo muito padrão.
Agora vamos imaginar o seguinte, vamos imaginar que a gente tá trabalhando nesse nosso e-commerce aqui e o pessoal de produto, pessoal de negócio, chegou na gente e falou: "Pessoal, o seguinte, a gente precisa de uma funcionalidade agora para calcular o frete". Então, a gente precisa calcular o frete do pedido, né? Para saber quanto que vai ficar para poder mandar isso lá pro endereço do cliente.
Então, beleza? Então, o que que a gente faz? A gente vem aqui e começa a criar aqui e desenvolver.
Logicamente isso aqui é de exemplo, tá? Então vou criar aqui um shipping calculator e nesse shipping calculator aqui eu vou criar um método calculate aqui que vai receber um pedido e eu não vou retornar nada porque isso aqui mais uma vez isso é exemplo, tá? E aqui a gente teria uma lógica, uma suposta lógica para poder calcular o valor desse frete.
Beleza? Só que aqui dentro dessa classe, independente de se a gente vai chamar um serviço externo, alguma empresa que já faz esse cálculo, a gente chamar algum API, alguma coisa assim do tipo, a gente vai precisar pegar o CEP do cliente que fez esse pedido e mandar o CEP, enviar o CEP para poder realizar esse cálculo. Beleza?
Só que é muito comum a gente ver esse tipo de abordagem aqui, ó. Eu vou chamar aqui o zip code. E aí do order o cara pega o customer, depois ele pega o get address e depois ele chama o zip code.
E ele faz essas chamadas encadeadas. E qual que é o problema dessa abordagem aqui? Vamos lá.
A primeira coisa que você tem que perceber é o seguinte. A classe shipping calculator aqui, ela conhece a classe order. Ela recebe uma classe order aqui.
Então existe um acoplamento entre a classe shipping calculator e a order. E é natural que a minha classe de calcular um frete aqui, ela consiga conversar com a classe order, ela saiba que existe um get customer aqui. Mas não é natural que a minha classe de calcular um frete saiba que a partir desse get customer, eu vou obter um objeto do tipo customer, que esse objeto customer possui aqui um método chamado get address, que esse get address vai retornar um objeto do tipo endereço e que esse objeto do tipo endereço possui um método chamado get zip code.
Então você vê que a gente tá quebrando da forma mais brutal possível o encapsulamento. A minha classe shipping calculator, ela tá conhecendo detalhes de implementação internos demais de classes que ela nem conhece, que ela nem sabe que existe ou que ela nem deveria saber que existem. Fora isso, a gente tá criando também um autoacoplamento entre a classe shipping calculator e várias outras classes que ela não deveria conhecer.
Então, se por algum motivo esse método aqui falhar ou quebrar, vai quebrar o meu chiping calculator. Isso não deveria ser possível. Se o Get Chip Code deixar de existir amanhã ou mudar a implementação dele lá dentro, vai quebrar o chiping calculator.
Então, além de existir esse autoacoplamento, a gente também está ferindo o encapsulamento. A minha classe aqui, ela tá conhecendo detalhes demais. Isso aqui, uma analogia com o mundo real para você entender um pouco melhor o que tá acontecendo aqui, é literalmente você tá tentando pegar o pote de maionese que tá dentro da geladeira sem abrir a geladeira.
Isso no mundo real seria praticamente impossível você pegar um pote que tá dentro da geladeira sem abrir a geladeira. E é o que tá acontecendo aqui. A minha classing calculator para pegar o zip code, para pegar o CP desse cliente, ela tá acessando diretamente classes que ela não deveria conhecer.
E é exatamente isso que diz a Lady Demitter. Não fale com estranhos. A minha classe aqui, ela tá conversando com classes que ela não pode conversar.
A ideia da Lady Demitter é literalmente essa, você conversar com o seu vizinho mais próximo, com a classe à qual você tem acesso. E ela é quem tem que repassar a chamada para outras classes. E é literalmente isso que diz a regra do Objectenics, que fala que a gente só deve ter apenas um ponto por linha.
O que que seria esse ponto? Seria essas chamadas aqui, ó. Aqui no PHP é uma seta, mas em outras linguagens são um ponto.
Então a ideia é que a gente tem apenas um ponto por linha. E lógico que isso aqui não se aplica naquelas chamadas encadeadas de setters, né, que tu retorna ali o próprio objeto e tudo mais e faz aquelas chamadas encadeadas ali para você poder fazer atribuições. Isso aí eu posso trazer em um outro vídeo, mas a ideia aqui é você não conversar com objetos com classes que você não conhece.
Então de alguma forma a gente vai ter que reduzir isso aqui para apenas um ponto por linha. E como que a gente resolve esse problema aqui? Vamos lá.
Entendendo o problema que a gente tem, a gente precisa acessar o CP. A gente precisa do CP para bater num API, para enviar isso para algum lugar para poder calcular esse frete. Beleza?
Então, a partir do meu pedido, eu preciso acessar o CP. Que que a gente pode fazer aqui? Será que daqui do meu pedido eu posso chamar aqui um GET zip code direto a partir do pedido?
Vamos tentar essa abordagem e eu vou te mostrar aqui mais alguns detalhes. Vamos lá. Então, do meu order, eu quero chamar o CP.
Beleza? Então, aqui no meu order, o que que a gente tem? A gente tem esse get customer aqui, que eu vou remover esse get custom Customer e vou criar aqui o nosso GET zip code que vai retornar pra gente uma string.
Beleza? Então, o que que eu vou fazer? Eu vou acessar o meu customer.
Do meu customer eu vou pegar o get address e do meu get address eu vou chamar o get zip code. Só que repara que nós causamos um problema aqui. Já vou falar sobre isso.
Voltando aqui no shipping calculator, já tá funcionando. Parou de dar o errinho aqui e tudo mais e tal. Então, se a gente pegar esse zip code aqui, a gente consegue enviar isso para qualquer lugar, para qualquer API e tudo mais e trabalhar.
Por quê? Porque o meu order agora retorna o zip code. E eu também já vou te explicar o por que a gente pode retornar um CP de dentro do pedido.
Vou te mostrar a relação que isso tem também com domain driven design e um conceitozinho da modelagem tática ali que remete a isso aqui. Mas vamos voltar aqui no order. Se do meu order eu consigo acessar agora o Get Zip Code, eu tenho um outro problema.
Por quê? O meu order aqui, ele conhece o customer, ele tem um acoplamento aqui entre o order e o customer. Então é natural que o meu pedido ele consiga conversar com o customer, ele consiga conversar com o cliente.
Então é natural que o meu pedido saiba chamar esse método get address aqui do customer. Show de bola. Só que não é natural que a minha classe de pedido saiba que esse get address vai retornar um head que o address possui o get zip code.
Então a gente trouxe o problema para cá. Então mais uma vez temos que dar um jeito de levar isso lá pra ponta, lá pros relacionamentos mais internos, pra gente encapsular esse comportamento e de uma ponta a gente conseguir chamar a propriedade da outra. Então calma que isso aqui vai ficar mais claro.
Vamos lá. Que que eu preciso fazer aqui? Já que o meu pedido só conhece o customer, então eu posso simplesmente aqui no meu customer chamar esse get zip code.
Posso remover o que tá no meio e manter as duas pontas se comunicando. Só que aí a gente vai encadeando o encapsulamento. Calma que isso vai ficar mais claro.
O meu customer aqui agora, ele vai ter que ter um método chamado get zip code. Se a gente entrar aqui dentro do customer, ele tem o get address que retornava aquele objeto. Então o que que eu posso fazer?
Posso remover esse objeto daqui e chamar aqui um get zip code, que vai retornar uma string. Então, repara, o meu customer conhece o address, então é natural que ele saiba que existe um método get zip code. Então aqui eu posso retornar aqui o meu address e chamar o get zip code dele.
Então agora nós conseguimos encaixar as chamadas, né, fazer o uso ali de um ponto por linha. E logicamente que isso aqui não se aplica nisso aqui, tá? Esse ponto por linha é a partir do objeto e chamar as chamadas encadeadas.
Isso aqui é apenas a questão da propriedade aqui da classe, então isso aqui não conta como um ponto. O ponto começa a contar a partir daqui. Então nós já estamos seguindo aqui a lei de demitter e a regra do objectics na classe customer.
No address aqui nada mudou, então a gente continua com o nosso get zip code. No nosso order aqui a gente continua aqui também com um ponto por linha. E no nosso shipping calculator a gente conseguiu resolver.
E aí você deve estar estranhando o seguinte: "Pô Renato, mas pera aí, tem alguma coisa que não tá tão coerente assim, que é o pedido, ele não tem um zip code. Não é natural que um pedido tenha um CP. Será que faz sentido um pedido ter um CP?
" É aí que vai entrar um outro conceito. Vamos lá. Se você quer melhorar isso aqui e deixar mais semântico, que é o que eu faria, eu faria mais ou menos isso aqui, ó.
Eu renomearia esse cara aqui para get customer zip code. Então eu viria aqui e renomearia aqui também. Beleza?
Nada mudou, tá? A gente só renomeou esse método aqui. Internamente o encapsulamento a gente não vai mexer em nada, mas a gente pode retornar aqui um nome mais amigável.
Então agora parece que faz um pouco mais de sentido, pô. Get customer zip code. Então eu sei que é o zip code o cp daquele cliente que tá relacionado com o pedido.
Faz mais sentido. Show de bola. Agora voltando aqui no order, eu vou te ensinar um conceitozinho aqui que é o seguinte.
Existe no domain driven design um conceito chamado de agregate root, que seria raiz agregadora. O que que seria essa raiz agregadora? Pensa assim, ó.
No nosso sistema, no nosso domínio, principalmente quando a gente tá desenvolvendo, orientado a domínio, que seria o domain even design, a gente sempre tem entidades muito importantes e entidades menos importantes, vamos se dizer assim. No nosso sistema de e-commerce, é natural que o order, né, que uma classe, que uma entidade chamada de pedido, seja algo muito importante no nosso sistema, porque faz parte do domínio da nossa aplicação, do coração da nossa aplicação, um pedido, porque a gente lida com vendas, a gente lida com pedidos. Então essa entidade de pedido ela é muito importante.
Então no domain design, esse conceito chamado de agregate root, ele é basicamente uma raiz de agregação de todos os objetos relacionados a partir de um único objeto. Então como que seria isso aqui a partir desse nosso order aqui, desse nosso pedido? é literalmente a gente conseguir acessar os objetos que se relacionam com o pedido através do próprio pedido.
A gente não conversa com objetos mais internos ou objetos menos importantes ou objetos que ficam orbitando esse pedido. A gente trata ele como uma entidade muito importante. Então vou te mostrar uma imagem aqui que isso vai ficar mais claro.
Aqui nessa imagem nós temos aqui o color aqui que seria o objeto que vai chamar, né, o chamador ou o código cliente, né, aquele nosso chip calculator lá. Ele é o código cliente do nosso order. Então, o nosso order é uma entidade, só que ela é uma entidade raiz, ela é uma entidade muito importante.
Então, se porventura eu quiser conversar com alguém que se relaciona com esse order, eu vou conversar através do order, através do pedido. Então, é por isso que talvez você esteja estranhando ainda que um pedido pode retornar um zip code. E eu sei que esse conceito é um pouco avançado demais, mas repara, foi basicamente isso que a gente fez.
A gente tem um color aqui, que é o nosso código cliente, que conversa com o pedido. A gente tem uma entidade aqui que se relaciona com esse pedido e essa entidade aqui, muito provavelmente no nosso cenário, é o customer. E o customer tinha o seu endereço ali, né, um objeto chamado endereço.
Então, através do meu agregate root aqui, através da minha do meu pedido, né, da minha raiz agregadora, eu conversei com customer que conversou com o endereço, né, e que o endereço retornou ali o seu CP. Então, isso aqui é uma técnica um pouco mais avançada. Se deixar nos comentários, eu gravo um vídeo sobre modelagem tática aí do domain driven design.
Tem uma outra imagem aqui que a gente pode ver também que é o seguinte. Aqui a gente tem um contexto bancário. Então, por exemplo, a gente tem um account aqui que é uma conta, né, uma conta bancária e que num contexto de banco é uma entidade muito importante e essa entidade se relaciona, logicamente com um balance aqui, que seria o saldo ali dessa conta e as transações também.
Então, toda conta tem as suas transações, só que quem é o mais importante de todos eles é aqui o account, é a conta bancária. Então, se o meu código cliente quiser saber as transações de uma conta bancária, ele fale com o account. Se ele quiser saber o saldo, ele fala com o account.
Ele não busca diretamente um balance aqui do banco de dados lá pelo ID. É por isso que eu sempre insisto em dizer orientação a objetos, domain driven design, clean architecture, boas práticas, object calistenics, tudo isso é agnóstico de tecnologia. Então você não pensa primeiro em framework, em banco de dados, em ID de tabela, nem nada do tipo para depois pensar no domínio.
Primeiro você desenvolve o domínio da aplicação, depois você fala de tecnologia. Tecnologia são detalhes, framework, banco, mensageria, tudo isso é detalhe. Tudo isso é coisas que orbitam o domínio da sua aplicação.
O coração da sua aplicação está no domínio, está nas regras de negócio, nas entidades que você cria. Então isso aqui são conceitos mais avançados, mas logicamente eu usei aqui para te mostrar que mesmo sem querer a gente acaba implementando algumas coisas mais avançadas, mesmo que seja seguindo regras básicas aqui, técnicas básicas aqui de object calistenics e a lei deitter aqui, que basicamente a gente só melhorou o encapsulamento aqui e delegou a responsabilidade de chamar os objetos para quem é de direito. Beleza?
Bom, e agora que tu aprendeu mais uma regra do Object Calistics e também aprendeu a lei de Demitter e um pouquinho sobre domain driven design, deixa teu like aí, se inscreve no canal, ativa o sininho para tu não perder nenhuma notificação. Vou deixar na descrição desse vídeo aqui alguns conteúdos que podem te ajudar na busca pelo código de alta qualidade. Se ficou qualquer dúvida, deixa nos comentários abaixo que eu prometo que eu tiro um tempo para te responder.
Por fim, eu vou ficando por aqui. Um forte abraço para você e nos vemos em breve. M.
Related Videos
Exporting CSV from Postgres in Node.js efficiently
37:31
Exporting CSV from Postgres in Node.js eff...
Rocketseat
12,918 views
Object Calisthenics: Increase the COHESION of your CLASSES with these Two Rules! | Object Orienta...
27:01
Object Calisthenics: Increase the COHESION...
Renato Augusto
16,019 views
Object Calisthenics: Técnicas Para Eliminar o ELSE do Seu Código | Boas Práticas de Programação
25:02
Object Calisthenics: Técnicas Para Elimina...
Renato Augusto
37,134 views
UMA API PARA ANALISAR DADOS DE 100 MIL USUÁRIOS - 1 sênior vs. 3 júniors - Codecon
24:39
UMA API PARA ANALISAR DADOS DE 100 MIL USU...
Codecon
124,910 views
But what is quantum computing?  (Grover's Algorithm)
36:54
But what is quantum computing? (Grover's ...
3Blue1Brown
342,941 views
Como CRIAR seu servidor MCP (Fácil)
22:46
Como CRIAR seu servidor MCP (Fácil)
Ronnald Hawk
16,736 views
PARE de Sabotar Seu Código com ABSTRAÇÕES ERRADAS! Domine o Interface Segregation Principle | SOLID
22:44
PARE de Sabotar Seu Código com ABSTRAÇÕES ...
Renato Augusto
7,972 views
Why the Most Foolish People End Up in Power – Machiavelli Knew This
28:45
Why the Most Foolish People End Up in Powe...
Philosophy Coded
665,205 views
Yamal Stars In Game Of The Season 😮‍💨 | Barcelona 3-3 Inter | UEFA Champions League Highlights
5:30
Yamal Stars In Game Of The Season 😮‍💨 | ...
TNT Sports
693,052 views
This Kid Made his Own Laptop and it’s AMAZING!
24:19
This Kid Made his Own Laptop and it’s AMAZ...
Linus Tech Tips
1,943,457 views
The Most Dangerous Building in Manhattan
33:39
The Most Dangerous Building in Manhattan
Veritasium
8,218,728 views
querem migrar pra JAVA.. JAVA
16:50
querem migrar pra JAVA.. JAVA
Lucas Montano
60,377 views
Object Calisthenics: A ARMADILHA dos TIPOS PRIMITIVOS! Seu código está FRÁGIL por causa disso!
28:30
Object Calisthenics: A ARMADILHA dos TIPOS...
Renato Augusto
43,576 views
Veritasium: What Everyone Gets Wrong About AI and Learning – Derek Muller Explains
1:15:11
Veritasium: What Everyone Gets Wrong About...
Perimeter Institute for Theoretical Physics
1,632,896 views
Eu não sabia o que era Docker até agora...
25:12
Eu não sabia o que era Docker até agora...
Augusto Galego
114,515 views
Padrão de Projeto Decorator: O Design Pattern que Flexibiliza seu Código com Orientação a Objetos!
25:05
Padrão de Projeto Decorator: O Design Patt...
Renato Augusto
14,753 views
I installed Linux (so should you)
22:53
I installed Linux (so should you)
PewDiePie
4,462,490 views
Build Epic Startups: NotebookLM + Gemini 2.5 Workflow
19:57
Build Epic Startups: NotebookLM + Gemini 2...
Blazing Zebra
109,787 views
James May has bought a new car!
13:25
James May has bought a new car!
James May’s Planet Gin
323,907 views
SOFT SKILLS: The Secret of Successful PROGRAMMERS: Develop These Skills and Stand Out!
10:56
SOFT SKILLS: The Secret of Successful PROG...
Renato Augusto
10,800 views
Copyright © 2025. Made with ♥ in London by YTScribe.com