La «loi de Demeter» est-elle applicable aux signatures de méthodes publiques / API?

10

Étant donné que les modifications apportées à la signature API / méthode publique devraient être minimes pour éviter de casser les codes clients qui utilisent ces méthodes, je me demandais si la loi de Demeter est moins applicable à ceux-ci.

Un exemple simple:

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

Notez que la méthode de débit transmet l'objet Transaction plutôt que simplement le double du montant (la `` Loi de Déméter '', si je comprends bien, dirait de simplement passer les informations requises, dans ce cas, juste le montant, pas l'objet Transaction ... ). La raison derrière cela est que la méthode à l'avenir pourrait nécessiter d'autres propriétés de transaction en dehors du montant. D'après ce que je comprends, cela empêchera de casser la signature de la méthode en ajoutant un nouveau paramètre à l'avenir.

Est-ce que cela en fait un choix judicieux? Ou est-ce que je manque quelque chose?

Carlos Jaime C. De Leon
la source

Réponses:

3

Mais cela ne viole pas la loi de Déméter.

Plus formellement, la loi de Déméter pour les fonctions exige qu'une méthode M d'un objet O ne puisse invoquer que les méthodes des types d'objets suivants:

  • O lui-même
  • Paramètres de M
  • tout objet créé / instancié dans M
  • Objets composants directs d'O
  • une variable globale, accessible par O, dans le cadre de M

Wikipédia: Loi de Déméter

La transaction est un argument de la méthode de débit, donc appeler t.getAmount () est très bien.

Edit: mal lu, vous dites que le LoD vous ferait passer le montant de la transaction, pas un objet de transaction. Si tel est le cas, alors oui, je pense que c'est un bon endroit pour le casser, sachant que vous aurez besoin de plus de l'objet Transaction à l'avenir. En outre, l'encapsulation de primitives dans des objets de niveau domaine est une autre bonne pratique de programmation.

Edit 2: Après avoir lu le pourrait avoir besoin de plus à l'avenir, on pourrait également voir cela comme un placage d'or inutile. Fournir une méthode qui prend un double maintenant (ou mieux une classe Money) est suffisant. Si vous avez besoin d'un argument Transaction plus tard, il n'est pas désastreux de fournir une deuxième signature prenant une transaction, mais continuez à prendre en charge la signature d'origine. Ce n'est pas comme si vous mettiez en œuvre deux méthodes, l'une appellerait l'autre.

Sean
la source
Merci pour votre contribution. Je suis d'accord sur les primitives d'encapsulation dans les objets de domaine. Cependant, juste votre point dans Edit 2, vous dites qu'il n'est pas désastreux d'ajouter une nouvelle 2e signature, mais cela signifierait un changement de code en code client qui devrait maintenant passer 2 paramètres au lieu d'un. Ce 2e point, j'hésite un peu à m'entendre ...
Carlos Jaime C. De Leon
L'édition 2 est subjective, je suis d'accord.
Sean
0

Si vous envisagez d'élargir la Accountclasse à l'avenir, je dirais que c'est une situation où rendre l' Transactionobjet plus général serait une bonne flexion des règles de la loi.

Par exemple:

public class Amount {

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

public abstract class Transaction {

    public String getType();

}

Je pense que je m'éloigne en quelque sorte de la question initiale, mais mon argument est que, même si vous craignez que vous vous éloigniez de la loi de Déméter, les avantages de le faire l'emportent sur les négatifs.

chooban
la source