quarta-feira, 20 de maio de 2009

Princípios de projeto - Parte V - A Lei de Demeter

A Lei de Demeter foi concebida por volta de 1987, definindo uma forma de desenvolver, também conhecida por Princípio do Mínimo Conhecimento (Principle of Least Knowledge). A lei tem origem em bla bla bla, e seu nome deriva de bla bla bla

Formalmente falando, um método M de um objeto O só pode consumir serviços dos seguintes tipos de objetos:

  1. Do próprio objeto O;
  2. Parâmetros de M;
  3. Qualquer objeto criado/instanciado por M;
  4. Componentes diretos de O.
Existe teoria abundante na Internet sobre a Lei. Os objetivos desse post são: mostrar/lembrar aos leitores desse blog que a Lei existe; criar uma referência centralizada para posts futuros e..... mostrar o exemplo do cachorro na prática. Exemplo do cachorro?!?!!

A grande maioria do material sobre a lei na Internet, usa o exemplo do cachorro:

Quando você precisa que um cachorro ande, você dá a ordem para as pernas diretamente, ou para o cachorro? Obviamente que para o cachorro e este sabe o que precisa ser acionado para andar.

Vamos demonstrar essa teoria:

package br.com.celsomartins.cachorro;
import java.util.ArrayList;
import java.util.List;

public class Cachorro {

private List <Pata> patas = new ArrayList <Pata>();

  public boolean andar() {
      for (Pata pata: patas) {
           if (!pata.andar()) {
               return false;
           }
       }
       return true;
  }
}


package br.com.celsomartins.cachorro;

public class Pata {
 
  public boolean andar() {
    return true;
  }
}

O que a Lei de Deméter diz é para não enviarmos mensagens para Pata e sim para Cachorro, que fará a delegação para as patas e estas para as classes que forem necessárias para fazer o cachorro andar.

A diferença é clara:

disso:

...
for (Pata pata: cachorro.getPatas()){
 pata.andar();
}

para isso:

cachorro.andar();

Dá para notar a facilidade de manutenção nesse exemplo? Posso alterar o comportamento das patas e o cão continua andando, sem afetar o cliente da classe Cachorro. O cachorro pode ter perdido uma das patas e andar com apenas três, isso não é importante para o cliente da classe.

A complexidade da ação está encapsulada. Não é preciso ninguém saber quais músculos, ossos, tendões, etc estão envolvidos na ação. Isso não é problema de quem está dando a ordem para o cão. Com a complexidade encapsulada, reduzimos dependências desnecessárias, facilitando a manutenção, aumentando a flexibilidade do nosso sistema.

Outro exemplo prático podemos encontrar nesse artigo.

Até a próxima.


Parte I - Introdução
Parte II - Correção
Parte III - Design por contrato
Parte IV - Flexibilidade
Parte VI - Eficiência
Parte VII - Coesão
Parte VIII - Usabilidade
Parte IX - Relacionamento entre classes

4 comentários:

  1. Gostei demais dos artigos de Pincipios de Projetos, parabéns, muito bom mesmo.
    Gostei também do Widget do evento, vai no Falando em Java?
    []sss

    ResponderExcluir
  2. Muito obrigado!!

    Vou sim. A previsão da minha chegada a SP é 6hs. Vou sair do RJ as 0hs. Nos encontramos lá.

    Abraços!

    ResponderExcluir
  3. ótimo post. realmente a qualidade do blog é indiscutivel.

    Outro beneficio da lei de demeter é evitar a navegação transitiva. ex:

    obj1.getObj2().getObj4().fazAlgo();

    além de criar um codigo longo o cliente deste codigo fica conhecendo mais objetos do que deveria, causando alto acoplamento.

    Imagine que houve uma mudança no modelo e agora quem contem o obj4 é o obj3. Seria necessaria uma busca por todas as ocorrencias do codigo acima para adicionar o obj3 as chamadas:

    obj1.getObj2().getOjb3().getObj4().fazAlgo();

    O correto seria:
    obj1.fazAlgo() e dentro deste metodo ele faz as chamadas aos demais objetos.

    grande abrasss e sucesso!!!

    ResponderExcluir
  4. Oi @Renan.
    Obrigado pelo elogio e pela participação.

    Você tem razão. Muito bom o seu comentário.

    Abraços

    ResponderExcluir