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?

Carlos Jaime C. De Leon
fonte

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.

Sean
fonte
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.

chooban
fonte