A 'Lei de Demeter' é aplicável às assinaturas de método público / API?


10

Dado que as alterações na assinatura da API / método público devem ser mínimas para evitar a quebra dos códigos dos clientes que usam esses métodos, fiquei pensando se a Lei de Demeter é menos aplicável a eles.

Um exemplo simples:

class Account() {
   double balance;
   public void debit(Transaction t) {
      balance -= t.getAmount();
   }
}

Observe que o método de débito passa o objeto Transaction em vez de apenas o dobro da quantia (a 'Lei de Demeter', como eu o entendo, diria apenas passar as informações necessárias, neste caso, apenas a quantia, não o objeto Transaction ... ) A razão por trás disso é que o método no futuro pode exigir outras propriedades de Transação além do valor. Pelo que entendi, isso impedirá a quebra da assinatura do método adicionando um novo parâmetro no futuro.

Isso faz com que seja uma escolha sensata, então? Ou eu estou esquecendo de alguma coisa?

Respostas:


3

Mas isso não viola a Lei de Demeter.

Mais formalmente, a Lei de Demeter para funções exige que um método M de um objeto O possa invocar apenas os métodos dos seguintes tipos de objetos:

  • O próprio
  • Parâmetros de M
  • quaisquer objetos criados / instanciados dentro de M
  • Objetos de componentes diretos de O
  • uma variável global, acessível por O, no escopo de M

Wikipedia: Lei de Demeter

Transação é um argumento para o método de débito, portanto, chamar t.getAmount () é bom.

Edit: Leia errado isso, você está dizendo que o LoD faria você passar a quantia da transação, não um objeto Transaction. Se for esse o caso, então sim, acho que este é um bom lugar para resolvê-lo, sabendo que você precisará mais do objeto Transaction no futuro. Além disso, encapsular primitivas em objetos no nível do domínio é outra boa prática de programação.

Edit 2: Depois de ler o que pode precisar de mais no futuro, também se pode ver isso como revestimento de ouro desnecessário. Fornecer um método que tome um dobro agora (ou melhor, uma classe Money) é suficiente. Se você precisar de um argumento de transação posteriormente, não é desastroso fornecer uma segunda assinatura para uma transação, mas continue a oferecer suporte à assinatura original. Não é como se você estivesse implementando dois métodos, um chamaria o outro.


Obrigado pela sua contribuição. Eu concordo com as primitivas encapsulantes em objetos de domínio. No entanto, apenas o seu ponto no Edit 2, você diz que não é desastroso adicionar uma nova 2ª assinatura, mas isso significaria mudança de código no código do cliente que agora deve passar 2 parâmetros em vez de um. Esse segundo ponto, eu sou abit hesitante em acordo sobre ...
Carlos Jaime C. De Leon

Editar 2 é subjetivo, eu concordo.
23412 Sean

0

Se você planeja expandir a Accountclasse no futuro, eu diria que essa é uma situação em que tornar o Transactionobjeto um propósito mais geral seria uma boa distorção das regras da Lei.

Por exemplo:

public class Amount {

    public void process( Transaction t ) {
        ....
    }
}

public abstract class Transaction {

    public String getType();

}

Eu acho que estou me afastando da questão original, mas o que quero dizer é que, embora você possa estar preocupado com o fato de estar se afastando da Lei de Demeter, as vantagens de fazê-lo superam os negativos.

Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.