Wann ist die Efferente / Afferente Kopplung gut oder schlecht?

11

Ich habe diese Woche eine Softwaremusterprüfung und eines der Themen, die wir untersuchen werden, ist Efferente und Afferente Kopplung.

Ich verstehe, dass ein Paket einen hohen Ce (efferente Kopplung) hat, wenn es von einer Reihe anderer Typen abhängt.

Beispielsweise:

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

Diese Klasse hätte eine hochefferente Kupplung, da sie von den Typen Motor, Rad und Karosserie abhängt.

Während der Typ "Rad" einen hohen Ca-Wert (afferente Kopplung) aufweisen würde, wenn mehrere andere Pakete davon abhängen würden (Auto, Flugzeug, Fahrrad).

Eine der möglichen Fragen bei unserer Prüfung ist, wann die Efferent / Afferent-Kopplung gut oder schlecht ist. Dies erscheint mir seltsam, da ein Programm logischerweise Pakete / Klassen mit hoher Efferent / Afferent-Kopplung benötigen würde.

Hat jemand ein Beispiel dafür, wann / wo eine hochefferente oder afferente Kopplung gut / schlecht ist?

Vielen Dank !

Tom Selleck
quelle
4
Wenn sie nur verwirrendere Begriffe ausgewählt hätten, die noch ähnlicher klangen ...
user949300

Antworten:

11

Die afferente Kopplung kann am einfachsten dahingehend beurteilt werden, wie viel Schmerz sie aufgrund der Notwendigkeit oder Wahrscheinlichkeit einer Änderung verursacht / spart. Nehmen Sie zum Beispiel Ihre Radklasse und nehmen wir an, dass viele andere Module sie verwenden, um verschiedene Arten von Fahrzeugen zu bauen. Wenn die Radklasse extrem stabil ist, ist diese afferente Kupplung von Vorteil, da Fahrzeuge Räder benötigen und eine zuverlässige verwenden. Wenn andererseits die Radklasse in Bezug auf die Wartung volatil ist, wird diese afferente Kopplung ein Schmerzpunkt sein, wenn Sie wiederholt Änderungen an vielen Codes vornehmen.

Efferente Kopplung ist im Konzept ähnlich, aber Sie werden ein etwas anderes Wertversprechen betrachten. Wenn Sie eine Fahrzeugklasse haben, die direkt von vielen Einzelteilen abhängt (im Gegensatz zu "Motor" und "Fahrgestell", und sie bestehen aus anderen Unterteilen), macht die Klasse wahrscheinlich viel und kann daher eine sein Wartungsengpass. Änderungen an dieser Klasse sind aufgrund ihrer Komplexität wahrscheinlich schwierig und riskant. Auf der anderen Seite, wenn die efferente Kopplung hoch ist, aber tatsächlich ziemlich zusammenhängend und klar, dann haben Sie keine Hierarchie von Objekten und Beziehungen, über die Sie sich Sorgen machen müssen.

Wenn es um Architektur / Design geht, müssen Sie wirklich endlose Kompromisse berücksichtigen, und diese Metriken unterscheiden sich nicht. Wenn Sie ein Beispiel dafür finden möchten, dass etwas gut oder schlecht ist, spielen Sie das "Was wäre wenn" -Spiel. Stellen Sie sich ein Beispiel vor und sagen Sie: "Was wäre, wenn ich X machen wollte - wie viel würde das saugen?" Für X, wo die Antwort "viel" ist, haben Sie einen Nachteil und für X, wo die Antwort "das wäre wirklich sehr einfach" lautet, haben Sie einen Vorteil.

Erik Dietrich
quelle
5

Allgemein gesprochen, lose Kopplung:

positiv : Schützt einen Teil des Systems vor Änderungen an etwas, von dem es abhängt (afferente Kopplung)

negativ : Die Beziehung ist möglicherweise schwieriger zu verstehen

Wenn ich beispielsweise ein System entwickeln würde, das auf HTTTP basiert, würde ich entscheiden, ob ich mich eng oder locker an HTTP koppeln muss. Wenn ich dachte, dass das System wahrscheinlich zu einem anderen Protokoll wechseln würde, könnte ich mich dafür entscheiden, es lose zu koppeln. Wenn ich akzeptieren würde, dass HTTP mein Protokoll ist, könnte ich es zur Vereinfachung des Verständnisses eng mit diesem Protokoll koppeln.

Bedenken Sie, dass einige der Komplexitäten in WS * in der Entkopplung von HTTP als Protokoll liegen.

jayraynet
quelle
Kluge Antwort, aber ich sehe nicht, wie es mit der Frage zusammenhängt, bei der es um efferente / afferente Kopplung und nicht um enge / lose Kopplung ging.
lbalazscs
Sie sind richtig, @lbalazscs. Keine Ahnung, warum ich geantwortet habe, ohne die Frage zu beantworten!
Jayraynet
1

Afferent

Wenn etwas eine Reihe verschiedener Dinge verwendet (hohe Anzahl afferenter Kopplungen), kann es leicht brechen, wenn sich eines dieser Dinge ändert.

Instabilität = 1

Geben Sie hier die Bildbeschreibung ein

Efferent

Wenn etwas von einer Reihe verschiedener Dinge verwendet wird (hohe Anzahl von efferenten Kopplungen), kann es dazu neigen, viele Dinge zu zerbrechen, wenn es sich ändert.

Instabilität = 0

Geben Sie hier die Bildbeschreibung ein

Stabilität

Martins Definition von "Stabilität" ist eine exotische Mischung zwischen "schwer zu ändern" und "nur wenige Gründe zu ändern". Seine Instabilitätsmetrik beschreibt jedoch nur "Schwierigkeit der Veränderung". "Gründe für Änderungen" haben viel mehr mit Faktoren zu tun, die nicht einfach zu berechnen sind, z. B. das angemessene Entwerfen Ihrer Schnittstellen auf einer angemessenen Abstraktionsebene und ein klareres Verständnis der Anforderungen des Benutzers im Voraus.

Eine hochefferente Kopplung mit einer niedrigen afferenten Kopplung führt zu Stabilität (wie bei etwas, das schwer zu ändern ist, da es ein paar Dinge zerbricht), das Gegenteil führt zu Instabilität (wie bei etwas, das leicht zu ändern ist, da es ein paar Dinge nicht bricht). .

Eine große Anzahl afferenter Kopplungen könnte ein Indikator dafür sein, dass Ihr Design nicht fokussiert ist - es verwendet eine ganze Reihe verschiedener Dinge, sodass es möglicherweise an einer klaren, einzigartigen Verantwortung mangelt.

Eine große Anzahl von efferenten Kupplungen könnte zunächst als eine wirklich gute Sache interpretiert werden, da dies darauf hinweist, dass Ihr Design weit verbreitet (wieder) verwendet wird. Das wäre jedoch schlecht, wenn Sie versucht wären, das Design häufig so zu ändern, dass alles kaputt geht. Mit einer großen Anzahl von efferenten Kupplungen kommt daher die Notwendigkeit, dass solche Pakete "wenige oder keine Gründe für eine Änderung" haben. Die Designs sollten im idealen Sinne stabil sein, da sie keine Gründe für Änderungen haben, da sie ebenfalls sehr schwer zu ändern sind.

Prinzip der stabilen Abstraktionen

Konzepte wie die Abhängigkeitsinversion (die natürlich eine Abhängigkeitsinjektion erfordert) und SAP (Prinzip der stabilen Abstraktion) legen nahe, dass Abhängigkeiten in Richtung Abstraktionen fließen. Und es gibt einen einfachen Grund, warum, wenn man die "Stabilität" im Zusammenhang mit "wenigen Gründen zur Änderung" betrachtet. Eine abstrakte Schnittstelle erwähnt keine konkreten Details, sie konzentriert sich nur auf "was zu tun ist" anstatt auf "was Dinge sind" und hat daher weniger Gründe, sich zu ändern. Der beschleunigte Grafikport auf unseren Motherboards (abstrakte Benutzeroberfläche) hat weniger Gründe für eine Designänderung als die GPU, die daran angeschlossen wird (ein konkretes Detail).

Wiederverwendbarkeit vs. Wiederverwendung

Eine persönliche Art von Metrik, wenn ich eine vorschlagen kann, die etwas mit Martins kollidiert, ist diese Vorstellung, die ich gerne vorantreibe, dass die wiederverwendbarsten Bibliotheken versuchen sollten, anderen Code minimal wiederzuverwenden. Dies führt dazu, dass die Instabilität auf eine harte 0 steigt. Dies geschieht aus praktischen Gründen, um minimale Gründe für Änderungen zu haben, aber auch, um die am einfachsten zu implementierende Bibliothek zu fördern. Eine universell einsetzbare, weit verbreitete Bibliothek, die von einem Dutzend verschiedener Bibliotheken abhängt, hat viele Gründe für Änderungen sowie eine umständlich gebündelte Distribution, deren Bereitstellung schwierig sein kann. Der Unterschied besteht darin, dass sich "Gründe für Änderungen" in meinem Fall sogar auf die Implementierung erstrecken, da sie aus einer bibliotheksorientierten Sicht stammen, die stabile Versionen der Bibliothek veröffentlichen möchte. Martin könnte die Implementierung als einen sehr separaten Teil abwerten,

Aus Sicht der Verteilung verschwimmen Implementierung und Schnittstelle, um Benutzerabhängigkeiten zu einer stabilen oder instabilen Bibliothek zu erhalten. Aus Sicht der Schnittstelle wird nur die Schnittstelle verwendet und die zugehörigen Implementierungsdetails sind vollständig getrennt.

ChrisF
quelle