La loi de Déméter stipule ce qui suit:
- 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.
C # 6.0 a introduit un nouvel opérateur appelé opérateur conditionnel nul . À mon humble avis, il facilite le codage et améliore la lisibilité. Mais cela facilite également l'écriture de code couplé, car il est plus facile de parcourir les champs de classe, en vérifiant déjà la nullité (quelque chose comme var x = A?.B?.C?.D?.E?.F?
).
Est-il exact de dire que ce nouvel opérateur va à l'encontre de la loi de Déméter?
c#
design-patterns
object-oriented-design
Arthur Rizzo
la source
la source
A?.B?.C?.D?.E?.F?
cela le violerait - LoD ne concerne pas le nombre de points et si la méthode appelante possède de telles informations sur la structure qui ne sont pas en violation avec ses points, un tel appel serait parfaitement acceptable. Qu'un tel code puisse violer LoD ne suffit pas à dire que toutes les utilisations de celui -ci violent LoD.X.Y.Z.W.U
est une violation de la "loi". Mais, dans mon expérience avec le code, 90% du temps, il s'agit simplement de code couplé laid..?
plus LoD que constitue une violation+
ou-
fait.Réponses:
Non *
* L'opérateur conditionnel nul est un outil du langage et du framework .NET. Tout outil peut être utilisé de manière abusive et utilisée de manière à nuire à la maintenabilité d'une application donnée.
Mais le fait qu'un outil puisse être maltraité ne signifie pas nécessairement qu'il doit être maltraité, ni que l'outil viole un ou des principes particuliers pouvant être détenus.
La loi de Demeter et d'autres sont des directives sur la façon dont vous devez écrire votre code. Il est destiné aux humains, pas aux outils. Ainsi, le fait que le langage C # 6.0 dispose d'un nouvel outil n'affecte pas nécessairement la façon dont vous devez écrire et structurer votre code.
Avec tout nouvel outil, vous devez évaluer comme ... si le gars qui finit par le maintien de votre code sera un psychopathe violent ... . Notez à nouveau qu'il s'agit d'un guide pour la personne qui écrit le code et non des outils utilisés.
la source
foo = new FiveDMatrix(); foo.get(0).get(0).get(0).get(0).set(0,1);
serait bien (et pas pire quefoo[0][0][0][0][0] = 1
) ... et beaucoup d'autres situations où cela ne viole pas LoD.Dom file = prase("some.xml"); file.get(tag1).getChild().get(tag2).getChild() ...
- c'est une question de traitement de la structure d'un code stupide. Ce n'est pas un étranger ... c'est juste stupide. Le.?
devient très utile dans de telles structures.Sorte de.
Si vous ne faites qu'un seul accès (
a?.Foo
), cela équivaut à:que la plupart des gens conviendraient ne constitue pas une violation de la loi de Déméter. À ce stade, il ne s'agit que de sucre syntaxique pour améliorer la lisibilité.
Rien de plus que cela, et cela violerait probablement la loi de Demeter, et cette fonctionnalité a tendance à promouvoir ce type d'utilisation. Je dirais même que le "bon" usage ci-dessus ne suffit pas à lui seul à justifier ce type de changement de langage, donc je m'attends à ce qu'il soit fait pour supporter le moins clairement bon usage.
Cela dit, il convient de rappeler que la loi de Déméter n'est pas une loi en soi, mais plutôt une ligne directrice. Beaucoup de code le viole et fonctionne bien. Parfois, la simplicité de conception ou de code vaut plus que le risque posé par la violation de la loi de Déméter.
la source
a?.Func1(x)?.Func2(y)
L'opérateur de coalescence nul est autre chose.Considérons à la fois l'opérateur seul et l'utilisation fortement enchaînée que vous en avez.
En soi, cela
.?A
dépend de la même quantité de connaissance de la classe que la valeur de gauche est et du type retourné par la méthode comme le.A != null
fait, à savoir. Il doit savoir que laA
propriété existe et renvoie une valeur qui peut être comparéenull
.Nous ne pouvons affirmer que cela viole la loi de Demeter que si les propriétés typées le font. Nous ne sommes même pas obligés d'avoir
A
un type concret (sa valeur pourrait être de type dérivé). Le couplage ici est minime.Voyons maintenant
var x = A?.B?.C?.D?.E?.F
.Ce qui signifie que cela
A
doit être d'un type qui pourrait être nul, ou pourrait avoir uneB
propriété, qui doit être d'un type qui pourrait être nul ou avoir uneC
propriété, et ainsi de suite jusqu'à ce que le type de laE
propriété soit quelque chose qui pourrait être nul ou pourrait avoir uneF
propriété.En d'autres termes, nous devons le faire avec un langage à typage statique ou avoir appliqué une contrainte sur les types qui peuvent être renvoyés si le typage est lâche. Dans la plupart des cas, C # utilise le typage statique, nous n'avons donc rien changé.
Si nous avions alors le code suivant violerait également la loi:
C'est exactement pareil . Ce code qui utilise le couplage de différents éléments doit "connaître" la chaîne complète de couplage, mais il utilise un code qui ne viole pas la loi de Déméter pour ce faire, chaque unité ayant un couplage bien défini avec le suivant.
la source
var x = A?.B?.C?.D?.E?.F
tous ces if / elses même s'ils sont finalement les mêmes.A?.B?.C?.D?.E?.F
car il y en a moins qui peut être mauvais; soit nous devrions essayer de passerF
par ce chemin, soit nous ne devrions pas, alors que le formulaire plus long pourrait contenir des erreurs ainsi que l'erreur de ne pas être la bonne chose à faire.A.B.C.D
. Il est beaucoup plus simple d'avoir une seule chose à rechercher (accès à la propriété chaînée) plutôt que deux choses différentes qui dépendent d'un détail assez peu pertinent (vérification nulle)L'objet peut être créé dans le but d'encapsuler des comportements ou de conserver des données, et des objets peuvent être créés dans le but d'être partagés avec du code extérieur ou détenus en privé par leur créateur.
Les objets créés dans le but d'encapsuler un comportement (qu'il soit partagé ou non), ou pour être partagés avec du code extérieur (qu'ils encapsulent un comportement ou des données) doivent généralement être accessibles via leur interface de surface. Cependant, lorsque des objets contenant des données sont créés pour être utilisés exclusivement par leur créateur, les raisons normales de la loi de Demeter pour éviter un accès "profond" ne s'appliquent pas. Si une partie d'une classe qui stocke ou manipule des données dans l'objet est modifiée d'une manière qui nécessiterait l'ajustement d'un autre code, il sera possible de garantir que tout ce code est mis à jour car - comme indiqué ci-dessus - l'objet a été créé pour l'utilisation exclusive d'une classe.
Alors que je pense que le?. L'opérateur aurait peut-être pu être mieux conçu, il y a suffisamment de situations où les objets utilisent des structures de données imbriquées que l'opérateur a de nombreux cas d'utilisation qui ne violeraient pas les principes exprimés par la loi de Demeter. Le fait qu'il puisse être utilisé pour violer la LoD ne doit pas être considéré comme un argument contre l'opérateur, car il n'est pas pire que le "." opérateur à cet égard.
la source