Question

La loi de Demeter indique que vous ne devriez parler qu'aux objets que vous connaissez directement. Autrement dit, n'effectuez pas de chaînage de méthodes pour parler à d'autres objets. Lorsque vous le faites, vous établissez des liens incorrects avec les objets intermédiaires, couplage de manière inappropriée. code à un autre code.

C'est mauvais.

La solution serait que la classe que vous connaissez connaisse essentiellement les wrappers simples qui délèguent la responsabilité à l'objet avec lequel elle entretient la relation.

C'est bien.

Cela semble toutefois avoir pour résultat que la classe présente une cohésion faible. Il n’est plus simplement responsable de ce qu’il fait précisément, mais il a également demandé aux délégués que, dans un sens, rend le code moins cohérent en dupliquant des parties de l’interface de son objet associé.

C'est mauvais.

Cela a-t-il vraiment pour effet de réduire la cohésion? Est-ce le moindre de deux maux?

S'agit-il d'une de ces zones grises du développement, où vous pouvez débattre de la ligne de démarcation, ou existe-t-il des méthodes solides et fondées sur des principes permettant de décider où tracer la ligne de démarcation et quels critères vous pouvez utiliser pour prendre cette décision?

Était-ce utile?

La solution

Grady Booch dans "Analyse et conception orientées objet":

"L'idée de cohésion découle également d'un design structuré. En termes simples, la cohésion mesure le degré de connectivité entre les éléments d’un même module (et pour la conception orientée objet, une classe ou un objet unique). La forme la moins souhaitable 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érons une classe comprenant les abstractions de chiens et de vaisseaux spatiaux, dont les comportements sont totalement indépendants. le forme de cohésion la plus souhaitable est la cohésion fonctionnelle, dans laquelle les éléments de une classe ou un module travaillent tous ensemble pour fournir un comportement bien délimité. Ainsi, la classe Dog est fonctionnellement cohérente si sa sémantique embrasse le comportement d'un chien, le chien entier et rien que le chien. "

Substituez le chien au client dans ce qui précède et cela pourrait être un peu plus clair. L'objectif est donc simplement de viser la cohésion fonctionnelle et de s'éloigner autant que possible de la cohésion fortuite. En fonction de vos abstractions, cela peut être simple ou nécessiter une refactorisation.

Notez que la cohésion s’applique tout autant à un "module". qu’une seule classe, c’est-à-dire un groupe de classes travaillant ensemble. Donc, dans ce cas, les classes Client et Commande ont toujours une cohésion décente, car elles entretiennent une relation solide, les clients créent des commandes, les commandes appartiennent aux clients.

Martin Fowler a déclaré qu’il serait plus à l'aise d'appeler cela la "Suggestion de Demeter". (voir l'article les imitations ne sont pas des talons ):

"Les testeurs mocistes parlent davantage d'éviter les" épaves de train "- les chaînes de méthodes de style de getThis (). getThat (). getTheOther (). Éviter les chaînes de méthodes est également connu comme suit la loi de Demeter. Alors que les chaînes de méthodes sont une odeur, le problème opposé des objets intermédiaires, surchargés de méthodes de transmission, est également une odeur. (J'ai toujours pensé que je serais plus à l'aise avec la loi de Demeter si on l'appelait la suggestion de Demeter .) "

Cela résume bien d'où je viens: il est parfaitement acceptable et souvent nécessaire d'avoir un niveau de cohésion inférieur au strict respect de la "loi". pourrait nécessiter. Évitez la cohésion fortuite et visez la cohésion fonctionnelle, mais ne vous arrêtez pas pour peaufiner au besoin pour s’intégrer plus naturellement à votre conception abstraite.

Autres conseils

Si vous enfreignez 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 au lieu de noter qu'il s'agit d'un sent le code et apportez les modifications nécessaires qui, espérons-le, augmentent la cohésion et réduisent le couplage. Malheureusement, aucune refactorisation simple ne s'applique toujours ici, mais vous devriez probablement appliquer dites-leur qu'il ne faut pas demander

Je pense que vous avez peut-être mal compris ce que la cohésion signifie. Une classe implémentée par rapport à plusieurs autres classes n'a pas nécessairement une cohésion faible, tant qu'elle représente un concept clair et a un but clair. Par exemple, vous pouvez avoir une classe Person , qui est implémentée en termes de classes Date (pour la date de naissance), Adresse et code> Education (liste des écoles dans lesquelles la personne s'est rendue). Vous pouvez fournir des enveloppes dans Personne pour obtenir l'année de naissance, la dernière école où la personne est allée ou son état de résidence, afin d'éviter de révéler le fait que Personne est mis en œuvre en termes de ces autres classes. Cela réduirait le couplage, mais rendrait la Personne non moins cohérente.

Il s’agit d’une zone grise. Ces principes ont pour but de vous aider dans votre travail. Si vous constatez que vous travaillez pour eux (c.-à-d. Qu'ils se mettent sur votre chemin et / ou que vous le trouvez trop complique votre code), alors vous êtes se conformer trop fort et vous devez reculer.

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

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

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

Pour respecter la loi de Demeter dans le cas de plusieurs niveaux de dépendance de classe, il vous suffit d’appliquer une agrégation / composition et une bonne encapsulation à chaque niveau.

En d’autres termes, chaque classe a une ou plusieurs dépendances sur d’autres classes. Cependant, il ne s’agit que de dépendances à la classe référencée et non d’objets renvoyés à partir de propriétés / méthodes.

Dans les situations où il semble y avoir un compromis entre le couplage et la cohésion, je me demanderais probablement "si quelqu'un d'autre avait déjà écrit cette logique et que je cherchais un bug, où regarderais-je en premier ? "et écrivez le code de cette façon.

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top