Selon la loi de Demeter, une classe est-elle autorisée à renvoyer un de ses membres?
Oui, certainement.
Regardons les points principaux :
- Chaque unité ne devrait avoir qu'une connaissance limitée des autres unités: seules les unités "étroitement" liées à l'unité actuelle.
- Chaque unité ne devrait parler qu'à ses amis; ne parlez pas à des étrangers.
- Ne parlez qu'à vos amis immédiats.
Tous les trois vous laissent poser une question: qui est un ami?
Au moment de décider quoi retourner, la loi de Déméter ou le principe de la moindre connaissance (LoD) ne dicte pas que vous vous défendez contre les codeurs qui insistent pour le violer. Cela veut dire que vous ne forcez pas les codeurs à le violer.
Obtenir ces confus est exactement pourquoi tant de gens pensent qu'un setter doit toujours retourner nul. Non. Vous devez autoriser un moyen d'effectuer des requêtes (getters) qui ne modifient pas l'état du système. C'est la séparation de requête de commande de base .
Cela signifie-t-il que vous êtes libre de vous plonger dans une base de code enchaînant ce que vous voulez? Non. N'enchaînez que ce qui devait être enchaîné. Sinon, la chaîne pourrait changer et soudainement votre matériel est cassé. C'est ce que l'on entend par amis.
De longues chaînes peuvent être conçues pour. Les interfaces fluides, iDSL, une grande partie de Java8 et le bon vieux StringBuilder sont tous destinés à vous permettre de construire de longues chaînes. Ils ne violent pas LoD parce que tout dans la chaîne est censé fonctionner ensemble et a promis de continuer à travailler ensemble. Vous violez Demeter lorsque vous enchaînez des choses qui n'ont jamais entendu parler les unes des autres. Les amis sont ceux qui ont promis de faire fonctionner votre chaîne. Les amis des amis ne l'ont pas fait.
En dehors des classes qui ont été spécifiquement désignées pour renvoyer des objets - telles que les classes d'usine et de constructeur - est-il acceptable qu'une méthode renvoie un objet, par exemple un objet détenu par l'une des propriétés de la classe ou cela violerait-il la loi de Demeter (1) ?
Cela ne crée qu'une occasion de violer Demeter. Ce n'est pas une violation. Ce n'est même pas nécessairement mauvais.
Et si elle viole la loi de déméter, cela importerait-il si l'objet retourné est un objet immuable qui représente une donnée et ne contient que des getters pour ces données (2)?
Immuable est bon mais hors de propos ici. Obtenir des trucs à travers une chaîne plus longue ne fait pas mieux. Ce qui le rend meilleur, c'est de séparer l'obtention de l'utilisation. Si vous utilisez, demandez ce dont vous avez besoin comme paramètre. N'allez pas à sa recherche en plongeant dans les getters d'étrangers.
En pseudo code:
Je soupçonne que la loi de Demeter interdit un modèle tel que ci-dessus. Que puis-je faire pour garantir que doSomethingElse () puisse être appelé sans violer la loi (3)?
Avant de parler de x.doSomethingElse(a)
comprendre que vous avez écrit simplement
b.getA().doSomething()
Maintenant, LoD n'est pas un exercice de comptage de points . Mais lorsque vous créez une chaîne, vous dites que vous savez comment obtenir un A
(en utilisant B
) et que vous savez comment utiliser un A
. Eh bien maintenant A
et B
il vaut mieux être des amis proches parce que vous venez de les coupler.
Si vous venait de demander quelque chose à la main vous une A
comme chose que vous pouvez utiliser A
et n'aurait pas pris soin d' où il vient et B
pourrait vivre une vie heureuse et libre de votre obsession à obtenir A
de B
.
En ce qui concerne x.doSomethingElse(a)
sans détails x
sur l'origine, LoD n'a rien à dire à ce sujet.
LoD peut encourager la séparation de l'utilisation de la construction . Mais je soulignerai que si vous traitez religieusement chaque objet comme non convivial, vous serez coincé à écrire du code dans des méthodes statiques. Vous pouvez construire un graphique d'objet merveilleusement complexe de cette façon, mais vous devez finalement appeler une méthode pour démarrer la chose. Vous devez simplement décider qui sont vos amis. Il n'y a pas moyen de s'en sortir.
Alors oui, une classe est autorisée à renvoyer un de ses membres sous LoD. Lorsque vous le faites, vous devez indiquer clairement si ce membre est ami avec votre classe, car si ce n'est pas le cas, certains clients peuvent essayer de vous coupler à cette classe en vous utilisant pour l'obtenir avant de l'utiliser. C'est important car maintenant ce que vous retournez doit toujours supporter cette utilisation.
Il existe de nombreux cas où ce n'est tout simplement pas un problème. Les collections peuvent ignorer cela simplement parce qu'elles sont censées être amies avec tout ce qui les utilise. De même, les objets de valeur sont conviviaux avec tout le monde. Mais si vous avez écrit un utilitaire de validation d'adresse qui exigeait un objet employé dont il a extrait une adresse, plutôt que de simplement demander l'adresse, vous feriez mieux d'espérer que l'employé et l'adresse proviennent tous deux de la même bibliothèque.