Princípios de OOP: A lei de Demeter (LoD)

Assim como qualquer área, os profissionais envolvidos em desenvolvimento de software devem ter uma formação muito bem direcionada e aplicada ao mercado atual.
Em muitas ocasiões faço entrevistas com profissionais que se auto-intitulam arquitetos (aqueles famosos desenvolvedores sêniors), ou desenvolvedores plenos com alto conhecimento em Orientação a Objetos, entre outros. E o que eu posso concluir com tudo isso é que muitos desses profissionais não sabem qual é o nível de conhecimento deles mesmos.

E não podemos culpá-los. Seria uma injustiça se interpretássemos este ato como uma tentativa de fraudar o processo seletivo, ou então de garantir uma vaga ou salário em alguma empresa. No Brasil – e isso vem desde os primordios – nós não encontramos facilmente uma boa formação acadêmica em Orientação a Objetos, Padrões ou Princípios. Simplesmente temos a matéria básica (Encapsulamento, Abstração, Herança, Polimorfimos) e voilà, temos um novo profissional. Calma lá… nós temos que saber que Orientação a Objetos e seus princípios não sei baseiam apenas nisto. Existem muitos experimentos, leis e princípios que merecem nossa atenção, até mesmo na faculdade, por que não?

E uma destas leis (ou princípio como veremos no fim deste post) que gostaria de escrever sobre é a “Law of Demeter”.

Introdução

A lei de Demeter foi desenvolvida em 1988 por Karl Lieberherr e Ian Holland, da Northeastem Univerity, com uma idéia extremamente simples: organizar e reduzir dependências entre classes.

Mas antes seria interessante definirmos o que é uma dependência.

Dependência entre classes

Podemos citar que existe uma dependência entre classes quando uma classe faz referência a outra, através de execução de algum método seu.

Esta dependência pode causar alguns “prejuízos” ao projeto. Analise os seguintes pontos causados por uma alta dependência entre classes:

  1. Rigidez: uma mudança em uma classe afeta muitas outras partes do sistema;
  2. Fragilidade: quando você realiza uma alteração, partes inesperadas no sistema falham;
  3. Imobilidade: não é possível reutilizar partes de uma aplicação em outra, por não ser possível desacoplar este código.

A lei

Na classe C, para todos os métodos M definidos em C, todos os objetos com o qual M se comunica deve ser:

  • Argumento de M
  • Um membro de C
Objetos criados por M, por métodos que M invoca ou objetos de escopo global na classe são considerados argumentos de M.

Esta lei tem dois propósitos primários:

  1. Simplificar modificações;
  2. Simplificar a complexidade da programação.

Utilizando C#, podemos entender esta lei atráves do exemplo abaixo:

Considere um trecho de código na classe Carrinho que verifica o valor de desconto dos produtos em um carrinho:

   1: public decimal ObterDescontos()
   2: {
   3:     decimal totalDesconto = 0;
   4:  
   5:     for (int i = 0; i < this.LineItems.Count; i++)    
   6:     {
   7:         totalDesconto += this.LineItems[i].Desconto.Total;
   8:     }
   9:  
  10:     return totalDesconto;
  11: }

Neste exemplo, nossa classe Carrinho não segue a lei de Demeter, já que o método ObterDesconto acessa outros objetos que não fazem parte dos argumentos do método ou membros da própria classe (neste caso, Desconto).

Uma abordagem correta para este caso seria:

   1: public decimal ObterDesconto()
   2: {
   3:     decimal totalDesconto = 0;
   4:  
   5:     for (int i < 0; i < this.LineItems.Count; i++)
   6:     {
   7:         totalDesconto += this.LineItems[i].ObterDesconto();
   8:     }
   9:  
  10:     return totalDesconto;
  11: }

Agora o método ObterDesconto segue a lei, visto que ela acessa membros da classe Carrinho apenas.

Muitas pessoas, com o objetivo de simplificar, resumem esta lei como “nunca devemos utilizar mais de um ponto na chamada de um método (desprezando o this, claro). Portanto, o método acima está dentro desta definição também, já que utiliza LineItems[i].ObterDesconto() para obter o valor desejado.

Exceções

O que é muito importante saber é que talvez seja necessário que o objeto C saiba detalhes da implementação de outro objeto através de métodos M de sua definição. Em algumas situações, forçar a aplicação da lei de Demeter pode não ter valor maior do que manter as regras do domínio da aplicação.

Alteração no Nome

O nome “Law of Demeter” foi alterado, tempos depois, para “Principle of Least Knowledge”. Algumas pessoas justificam que esta alteração se deve ao fato da definição desta lei (ou princípio) não se aplicar a todos os casos, e portanto a definição de princípio se aplica de forma mais adequada para este caso. Além disso, o conteúdo deste princípio é um pouco diferente da lei – motivo pelo qual não concordo em utilizar este novo nome :)

Conclusão

Claro que a lei não se resume apenas a isso. Isso foi uma breve (mas muito breve) introdução. Pesquise mais sobre o assunto e leia as referências, com certeza você encontrará muito mais material que imagina.

Referências

http://en.wikipedia.org/wiki/Law_of_Demeter
http://www.cmcrossroads.com/bradapp/docs/demeter-intro.html
http://www.ccs.neu.edu/research/demeter/
http://www.ccs.neu.edu/research/demeter/papers/publications.html
Assuring Good Style for Object-Oriented Programs
http://www.ccs.neu.edu/research/demeter/demeter-method/LawOfDemeter/paper-boy/demeter.pdf

1 Comment

Comments have been disabled for this content.