web-dev-qa-db-fra.com

Quand est un couplage efferent / afférent bien ou mauvais?

J'ai un examen de modèles de logiciels cette semaine et l'un des sujets que nous devons étudier est un couplage efferent et afférent.

Je comprends qu'un paquet a une haute CE (couplage efferent) si cela dépend d'un certain nombre d'autres types.

Par exemple:

class Car{
    Engine engine;
    Wheel wheel;
    Body body;
}

Cette classe aurait un couplage à fort effet car cela dépend du moteur, des types de roue et de corps.

Alors que la "roue" de type aurait une ca (couplage afférente) si plusieurs autres emballages en dépendaient (voiture, plan, vélo).

Une des questions possibles à notre examen est, quand est-ce que le couplage efférent/afférent est bon ou mauvais? Cela me semble étrange parce que logiquement un programme nécessiterait des forfaits/classes avec un couplage à deux niveaux et à un accouplement efferent.

Quelqu'un a-t-il un exemple de quand/où un couplage élevé efferent ou afférent est bon/mauvais ??

Merci !

11
TomSelleck

Le couplage afférent peut être très facilement évalué en termes de douleur qu'il cause/sauvegarde en raison de la nécessité ou de la probabilité. Par exemple, prenez votre classe de roue et disons que beaucoup d'autres modules l'utilisent pour créer divers types de véhicules. Si la classe de roue est extrêmement stable, cet accouplement afférent est bénéfique car les véhicules ont besoin de roues et qu'ils utilisent une fiable. Si, d'autre part, la classe de roue est volatile en termes de maintenance, cet accouplement afférent sera un point de douleur lorsque vous introduisez des modifications de rupture de manière répétée à beaucoup de code.

Le couplage efferent est similaire dans le concept, mais vous allez regarder une proposition de valeur légèrement différente. Si vous avez une classe de voiture qui dépend directement de nombreuses parties individuelles (par opposition à dire "moteur" et "châssis", et ils se composent d'autres sous-parties), la classe fait probablement beaucoup et peut donc être une goulot d'étranglement de maintenance. Les modifications apportées à cette classe sont susceptibles d'être difficiles et risquées en raison de sa complexité. D'autre part, si le couplage efferent est élevé, mais il est réellement assez cohérent et clair, alors vous n'avez pas de hiérarchie d'objets et de relations à craindre.

En ce qui concerne l'architecture/design, ce que vous devez vraiment prendre en compte, ce sont à peu près des compromis sans fin et ces mesures ne sont pas différentes. Si vous voulez comprendre un exemple de quelque chose d'être bon ou mauvais, jouez le jeu "Et si". Imaginez un exemple et dites "Et si je voulais faire x - combien ça voudrait-il sucer?" Pour x où la réponse est "Beaucoup", vous avez un désavantage et pour x où la réponse est "qui serait vraiment vraiment facile", vous avez un avantage.

11
Erik Dietrich

Parlant en général, couplage lâche:

positif: protège une partie du système des modifications de quelque chose qui dépend de (couplage afférent)

négatif: la relation peut être plus difficile à comprendre

Par exemple, si je développais un système composé de HTTTP, je déciderais de décider si j'ai besoin de coupler étroitement ou de manière vague à HTTP. Si je pensais que le système était susceptible de passer à un protocole différent, je peux choisir de vous coupler de manière lâche, tandis que si j'y avais accepté que HTTP était mon protocole, je pouvais coupler étroitement à ce protocole pour la simplicité de la compréhension.

Considérez que certaines des complexités de WS * sont dans son découplage de HTTP en tant que protocole.

5
jayraynet

Afférent

Si quelque chose utilise un tas de choses différentes (nombre élevé d'accouplements afférents), il pourrait être sujette à la pause si l'une de ces choses change.

Instabilité = 1

enter image description here

efferent

Si quelque chose est utilisé par un tas de choses différentes (nombre élevé d'accouplements efferents), il pourrait être sujette à briser beaucoup de choses si elle change.

Instabilité = 0

enter image description here

Stabilité

La définition de la "stabilité" de Martin est un mélange exotique entre "difficile à changer" et "avoir peu de raisons de changer". Pourtant, son métrique d'instabilité décrit uniquement la "difficulté de changement". "Raisons de changement" auront beaucoup plus de choses à voir avec des facteurs qui ne peuvent pas être facilement calculés, comme la simple conception de vos interfaces de manière appropriée, à un niveau d'abstraction approprié et de comprendre les exigences de fin d'utilisateur plus clairement.

Un couplage si élevé à faible teneur d'un couplage afférent de faible stabilité (comme dans quelque chose de difficile à changer puisqu'il brisera un tas de choses), l'instabilité des rendements opposés (comme dans quelque chose de facile à changer car il ne brisera pas de trucs) .

Un grand nombre d'accouplements afférents pourrait être un indicateur que votre conception manque de concentration - il utilise tout un tas de choses différentes, donc peut-être qu'il manque de responsabilité claire et singulière.

Un grand nombre d'accouplements effersents pourraient être interprétés d'abord comme une très bonne chose, car il indique que votre conception est utilisée. Pourtant, ce serait mauvais si vous vous sentez tenté de changer de conception souvent d'une manière qui brise tout. Ainsi, avec un grand nombre d'accouplements effersents, la nécessité de ces emballages ait "peu de raisons de changer". Les conceptions doivent être stables dans le sens idéal de ne pas avoir des raisons de changer, car ils seront également très difficiles à changer.

Principe d'abstraction stable

Les concepts comme l'inversion de dépendance (qui appelle naturellement une injection de dépendance) et SAP (principe d'abstractions stables) suggèrent que les dépendances coulent vers des abstractions. Et il y a une raison simple pour laquelle lorsque vous envisagez la "stabilité" dans le contexte d'avoir "peu de raisons de changer". Une interface abstraite n'engage aucun détail concrete, il ne se concentre que sur "Que faire" au lieu de "quelles choses", et a donc moins de raisons de changer. Le port graphique accéléré de nos cartes mères (interface Abstract) a moins de raisons de subir un changement de conception que le GPU qui se connecte à celui-ci (un détail concret).

réutilisabilité vs réutilisation

Une sorte de métrique personnelle de ma part si je peux suggérer un qui collide quelque peu avec Martin's est cette notion que j'aime pousser que les bibliothèques les plus réutilisables devraient chercher à réutiliser au minimum autre code. Cela pousse l'instabilité vers un dur 0. C'est pour les raisons pratiques d'avoir des raisons minimales de changer, mais aussi de promouvoir la bibliothèque la plus facile à déployer. Une bibliothèque à usage général, largement utilisée qui dépend d'une douzaine de bibliothèques différentes a de nombreuses raisons de changer, ainsi qu'une répartition emballée maladroite qui peut être difficile à déployer. La différence ici est que "les raisons de changer" dans mon cas s'étend même à la mise en œuvre, car elle provient d'une vue orientée de la bibliothèque qui cherche à libérer des versions stables de la bibliothèque. Martin pourrait réaliser la mise en œuvre comme une partie très séparée et considérer uniquement les métriques associées à l'interface de la bibliothèque (qui pourrait être beaucoup plus stable que sa mise en œuvre).

À partir d'un point de vue de distribution, de la mise en œuvre et de l'interface flou ensemble pour produire des dépendances des utilisateurs à une bibliothèque stable ou instable. À partir d'un point de vue de l'interface, seule l'interface est utilisée et les détails de mise en œuvre associés sont complètement séparés.

1
user204677