En parcourant le code que j'ai écrit, je suis tombé sur la construction suivante qui m'a fait réfléchir. À première vue, il semble assez propre. Oui, dans le code réel, la getLocation()
méthode a un nom légèrement plus spécifique qui décrit mieux exactement l'emplacement qu'elle obtient.
service.setLocation(this.configuration.getLocation().toString());
Dans ce cas, service
est une variable d'instance d'un type connu, déclarée dans la méthode. this.configuration
vient d'être passé au constructeur de classe, et est une instance d'une classe implémentant une interface spécifique (qui rend obligatoire une getLocation()
méthode publique ). Par conséquent, le type de retour de l'expression this.configuration.getLocation()
est connu; spécifiquement dans ce cas, c'est un java.net.URL
, alors que service.setLocation()
veut un String
. Étant donné que les deux types String et URL ne sont pas directement compatibles, une sorte de conversion est nécessaire pour adapter la cheville carrée dans le trou rond.
Toutefois , selon la loi de Déméter cité dans code propre , une méthode f dans la classe C ne devrait appeler des méthodes sur C , les objets créés par ou passés comme arguments à f et objets retenus en variables d'instance de C . Tout ce qui est au-delà (le dernier toString()
dans mon cas particulier ci-dessus, à moins que vous ne considériez un objet temporaire créé à la suite de l'invocation de la méthode elle-même, auquel cas toute la loi semble être théorique) est interdit.
Existe-t-il un raisonnement valable pour lequel un appel comme celui-ci, étant donné les contraintes énumérées, devrait être découragé ou même refusé? Ou suis-je juste trop nerveux?
Si je devais implémenter une méthode URLToString()
qui appelle simplement toString()
un URL
objet (tel que celui renvoyé par getLocation()
) qui lui est passé en tant que paramètre et retourne le résultat, je pourrais envelopper l' getLocation()
appel pour obtenir exactement le même résultat; efficacement, je voudrais simplement déplacer la conversion d'un pas vers l'extérieur. Serait-ce en quelque sorte acceptable? (Il me semble , intuitivement, que cela ne devrait pas faire de différence de toute façon, car cela ne fait que déplacer un peu les choses. Cependant, selon la lettre de la loi de Déméter citée, ce serait acceptable, car je fonctionnerait alors directement sur un paramètre d'une fonction.)
Cela ferait-il une différence s'il s'agissait de quelque chose d'un peu plus exotique que de faire appel toString()
à un type standard?
Lorsque vous répondez, gardez à l'esprit qu'il service
n'est pas pratique de modifier le comportement ou l'API du type de la variable. Aussi, pour les besoins de l'argument, disons que la modification du type de retour de getLocation()
est également impossible.
la source
La loi de Demeter est une directive de conception, pas une loi à suivre religieusement.
Si vous pensez que vos classes sont suffisamment découplées, il n'y a rien de mal à la ligne,
this.configuration.getLocation()
surtout si, comme vous le dites, il n'est pas pratique de changer d'autres parties de l'API.Je suis à peu près sûr que le client sera parfaitement heureux même si vous faites la loi de Demeter en pièces, tant que vous livrez ce qu'il veut et à temps. Ce qui n'est pas une excuse pour fabriquer de mauvais logiciels, mais un rappel pour être pragmatique lors du développement de logiciels.
la source
this.configuration
s'agit d'une variable d'instance d'un type d'interface connue, l'appel d'une méthode définie par cette interface semble correct, même selon une interprétation stricte. Oui, je sais que c'est une ligne directrice, tout comme KISS, SOLID, YAGNI et ainsi de suite. Il y a très peu ou pas de «lois» (au sens juridique) dans le développement général de logiciels.La seule chose à laquelle je peux penser de ne pas écrire de code comme celui-ci est que si
this.configuration.getLocation()
renvoie null? Cela dépend de votre code environnant et du public cible utilisant ce code. Mais comme le dit Marco - la loi de Demeter est une règle d'or - c'est bon à suivre, mais ne vous cassez pas le dos en le faisant inutilement.la source
this.configuration.getLocation()
retournait null, alors soit nous (a) n'aurions probablement jamais été aussi loin, soit (b) quelque chose de catastrophique s'est produit entre-temps, auquel cas je voudrais que le code échoue. Donc, bien que ce soit certainement un point valable en général, dans ce cas particulier, il est assez sûr de dire qu'il ne s'applique pas. En outre, tout cela et bien plus encore est entouré d'un gestionnaire d'exceptions spécialement conçu pour faire face à ce type d'échecs inattendus.Suivre strictement la loi de Demeter signifierait que vous devriez implémenter une méthode dans l'objet de configuration comme:
mais personnellement, cela ne me dérangerait pas parce que c'est une si petite situation, et de toute façon vos mains sont un peu liées à cause de l'API que vous ne pouvez pas changer. Les règles de programmation concernent ce que vous devez faire lorsque vous avez le choix, mais parfois vous n'avez pas le choix.
la source