Le couplage, la cohésion et la Loi de Demeter

la loi de Demeter indique que vous ne devez parler qu'à des objets que vous connaissez directement. C'est, ne pas effectuer la méthode de chaînage de parler à d'autres objets. Lorsque vous le faites, vous établissez des liens inappropriés avec les objets intermédiaires, de manière inappropriée coupler votre code à un autre code.

c'est mauvais.

la solution serait pour la classe que vous connaissez essentiellement exposer simples emballages qui en déléguer la responsabilité à l'objet de la relation.

c'est bien.

mais, cela semble avoir pour résultat la classe ayant faible cohésion . Elle n'est plus seulement responsable pour précisément ce qu'il fait, mais il a aussi les délégués que dans un sens, rendre le code moins cohésive en dupliquant des parties de l'interface de l'objet associé.

C'est un mauvais.

est-il vraiment baisser la cohésion? C'est le moindre de deux maux?

est-ce l'un de ces secteurs gris du développement, où vous pouvez débattre où la ligne est, ou y a-t-il des façons fortes, fondées sur des principes, de prendre une décision quant à savoir où tracer la ligne et quels critères pouvez-vous utiliser pour prendre cette décision?

62
demandé sur Diodeus - James MacFarlane 0000-00-00 00:00:00

5 réponses

Grady Booch dans "Analyse Orientée Objet et Design":

" l'idée de cohésion vient aussi du design structuré. En termes simples, la cohésion mesure le degré de connectivité entre les éléments d'un module unique (et pour la conception orientée objet, une seule classe ou d'un objet). La forme la moins désirable de la cohésion est une cohésion fortuite, dans laquelle des abstractions totalement indépendantes sont jeté dans la même classe ou le même module. Par exemple, considérez une classe comprendre les abstractions des chiens et des vaisseaux spatiaux, dont les comportements sont tout à fait indépendants. Le plus souhaitable forme de cohésion est la cohésion fonctionnelle, dans laquelle les éléments de une classe ou un module travaillent tous ensemble pour fournir un certain comportement bien délimité. Ainsi, le chien de classe est fonctionnellement cohésif si sa sémantique embrasse le comportement d'un chien, l'ensemble de chien, et rien que le chien."

chien Subsitute avec client dans le ci-dessus et il pourrait être un peu plus clair. De sorte que le l'objectif est simplement de viser une cohésion fonctionnelle et de s'éloigner le plus possible de la cohésion fortuite. Selon vos abstractions, cela peut être simple ou nécessiter un remaniement.

note la cohésion s'applique autant à un" module " qu'à une seule classe, c'est-à-dire un groupe de classes travaillant ensemble. Donc, dans ce cas, les classes de clients et de commandes ont encore une cohésion décente parce qu'ils ont cette relation forte, les clients créent des commandes, des commandes appartiennent aux clients.

Martin Fowler dit Qu'il serait plus à l'aise de l'appeler la "Suggestion de Demeter" (voir l'article les moqueries ne sont pas des chaumes ):

"Mockist testeurs ne parlons plus de prévenir le "déraillement" de la méthode des chaînes de style de get: ().getThat ().getTheOther(). Éviter les chaînes de méthode est également connu comme suit la Loi de Demeter. Tandis que les chaînes de méthode sont une odeur, le problème opposé des objets d'hommes moyens gonflé avec des méthodes de transport est aussi une odeur. (J'ai toujours pensé que je serais plus à l'aise avec la Loi de Demeter si elle s'appelait la Suggestion de Demeter .) "

qui résume bien d'où je viens: il est parfaitement acceptable et souvent nécessaire d'avoir un niveau de cohésion inférieur que le strict respect de la "loi" pourrait exiger. Évitez la cohésion fortuite et visez la cohésion fonctionnelle, mais ne vous accrochez pas à peaufiner où nécessaire pour s'intégrer plus naturellement à votre abstraction design.

45
répondu Ash 2008-10-09 10:00:05

si vous violez la Loi de Demeter en ayant""

int price = customer.getOrder().getPrice();

la solution n'est pas de créer un getOrderPrice() et de transformer le code en

int price = customer.getOrderPrice();

mais à la place de noter qu'il s'agit d'un odeur de code et de faire les changements pertinents qui, espérons-le, à la fois augmenter la cohésion et le couplage plus faible. Malheureusement, il n'y a pas de remaniement simple ici qui s'applique toujours, mais vous devriez probablement appliquer dire de ne pas demander

20
répondu Rasmus Faber 2017-05-23 12:10:39

je pense que vous avez peut-être mal compris ce que signifie cohésion. Une classe qui est mise en œuvre en fonction de plusieurs autres classes n'a pas nécessairement une faible cohésion, pour autant qu'elle représente un concept clair et qu'elle ait un but précis. Par exemple , vous pouvez avoir un class Person , qui est mis en œuvre en termes de classes Date (pour la date de naissance), Address , et Education (une liste des écoles où la personne est allée). Vous pouvez fournir des emballages dans Person pour obtenir l'année de naissance, la dernière école où la personne est allée, ou l'état où elle vit, pour éviter de révéler le fait que Person est mis en œuvre en termes de ces autres classes. Cela réduirait l'accouplement, mais cela rendrait Person non moins cohésif.

6
répondu Dima 2008-10-02 16:00:43

C'est une zone grise. Ces principes sont destinés à vous aider dans votre travail, si vous trouvez que vous travaillez pour eux (c'est-à-dire qu'ils se mettent en travers de votre chemin et/ou que vous trouvez que cela complique votre code) alors vous vous conformez trop dur et vous devez reculer.

faites que ça marche pour vous, ne travaillez pas pour ça.

4
répondu Binary Worrier 2008-10-02 16:01:42

Je ne sais pas si cela diminue réellement la cohésion.

agrégation / composition s'applique à une classe utilisant d'autres classes pour respecter le contrat qu'elle expose par ses méthodes publiques. La classe n'a pas besoin de copier l'interface de ses objets connexes. Il cache en fait toute connaissance sur ces classes agrégées à l'appelant de la méthode.

pour obéir à la loi de Demeter dans le cas de niveaux multiples de dépendance de classe, vous il suffit d'appliquer l'agrégation/composition et une bonne encapsulation à chaque niveau.

en d'autres termes, chaque classe a une ou plusieurs dépendances sur les autres classes, mais ce ne sont que des dépendances sur la classe référencée et non sur les objets retournés par les propriétés/méthodes.

1
répondu 2008-10-02 16:00:17