Was ist "lose Kupplung"? Bitte geben Sie Beispiele an


172

Ich kann das Konzept der "losen Kopplung" nicht verstehen. Ich nehme an, es hilft nicht, dass das Wort "lose" normalerweise eine negative Konnotation hat, deshalb vergesse ich immer, dass lose Kopplung eine gute Sache ist.

Kann jemand bitte einen "Vorher" - und "Nachher" -Code (oder Pseudocode) anzeigen, der dieses Konzept veranschaulicht?


Ich bin mir nicht sicher, wie dies von einer bestimmten Sprache getrennt werden kann, da ein Teil des Konzepts darin besteht, wie man eine Sprache verwendet, um zu verhindern, dass sich Codeeinheiten zu sehr miteinander verwickeln. Ich stelle auch fest, dass einige der Antworten auf Code zurückgreifen, um das Konzept zu veranschaulichen.
Onorio Catenacci

11
Nicht einverstanden, die praktischen Aspekte können in verschiedenen Sprachen unterschiedlich dargestellt werden, und dies zeigt sich insbesondere in dynamischen und kompilierten Sprachen. Aber das Konzept ist in beiden Fällen das gleiche.
Owen

Lose gegen enge und Kupplung gegen Entkopplung . Mitmachen ist nicht immer gut, manchmal gut / manchmal nicht gut ... Da wir unsere eigene Unabhängigkeit haben sollten , tun dies auch die Klassen.
BonCodigo

Antworten:


180

Stellen Sie sich eine einfache Warenkorbanwendung vor, die eine CartContents-Klasse verwendet, um die Artikel im Warenkorb zu verfolgen, und eine Bestellklasse, um einen Kauf zu verarbeiten. Die Bestellung muss den Gesamtwert des Inhalts im Warenkorb ermitteln. Dies kann folgendermaßen geschehen:

Eng gekoppeltes Beispiel:

public class CartEntry
{
    public float Price;
    public int Quantity;
}

public class CartContents
{
    public CartEntry[] items;
}

public class Order
{
    private CartContents cart;
    private float salesTax;

    public Order(CartContents cart, float salesTax)
    {
        this.cart = cart;
        this.salesTax = salesTax;
    }

    public float OrderTotal()
    {
        float cartTotal = 0;
        for (int i = 0; i < cart.items.Length; i++)
        {
            cartTotal += cart.items[i].Price * cart.items[i].Quantity;
        }
        cartTotal += cartTotal*salesTax;
        return cartTotal;
    }
}

Beachten Sie, wie die OrderTotal-Methode (und damit die Order-Klasse) von den Implementierungsdetails der CartContents- und CartEntry-Klassen abhängt. Wenn wir versuchen würden, diese Logik zu ändern, um Rabatte zuzulassen, müssten wir wahrscheinlich alle drei Klassen ändern. Wenn wir eine Listensammlung verwenden, um die Elemente zu verfolgen, müssen wir auch die Order-Klasse ändern.

Hier ist ein etwas besserer Weg, um dasselbe zu tun:

Weniger gekoppeltes Beispiel:

public class CartEntry
{
    public float Price;
    public int Quantity;

    public float GetLineItemTotal()
    {
        return Price * Quantity;
    }
}

public class CartContents
{
    public CartEntry[] items;

    public float GetCartItemsTotal()
    {
        float cartTotal = 0;
        foreach (CartEntry item in items)
        {
            cartTotal += item.GetLineItemTotal();
        }
        return cartTotal;
    }
}

public class Order
{
    private CartContents cart;
    private float salesTax;

    public Order(CartContents cart, float salesTax)
    {
        this.cart = cart;
        this.salesTax = salesTax;
    }

    public float OrderTotal()
    {
        return cart.GetCartItemsTotal() * (1.0f + salesTax);
    }
}

Die Logik, die für die Implementierung der Warenkorb-Werbebuchung oder der Warenkorbsammlung oder der Bestellung spezifisch ist, ist nur auf diese Klasse beschränkt. Wir könnten also die Implementierung einer dieser Klassen ändern, ohne die anderen Klassen ändern zu müssen. Wir könnten diese Entkopplung noch weiter vorantreiben, indem wir das Design verbessern, Schnittstellen usw. einführen, aber ich denke, Sie sehen den Punkt.


Könnten Sie die Antwort erweitern und eine weitere Entkopplung durch Abhängigkeitsinjektion einführen (obwohl der Konstruktor ideal sein sollte)?
BAD_SEED

4
@Wedge, ich sehe keinen Grund für die OrderKenntnis von a Cart. Live-Shopping und Facturation sind zwei verschiedene Kontexte. Wenn der Kunde bereit ist zu zahlen, könnten Sie einen Prozess haben, der dafür verantwortlich ist, CartEntries in etwas Bedeutendes für das zu übersetzen Order. Auf diese Weise würde die OrderKlasse auch ohne a instanziiert und verwendet Cart.
Plalx

@Wedge Könnten Sie bitte auf meinen Kommentar reagieren?
Plalx

Gut und einfach erklärt. Ich sah das Licht bei "..Beachten Sie, wie die OrderTotal-Methode (und damit die Order-Klasse) von den Implementierungsdetails der CartContents- und der CartEntry-Klasse abhängt .."
okey_on

Dieses Beispiel ist klar dargestellt. In diesen Tagen sind sich jedoch immer mehr Architekten einig, dass dieser übermäßig objektorientierte Stil eine schlechte Praxis ist. Es macht keinen Sinn, die "Implementierungs" -Details von CartEntryund zu verbergen CartContents. Da diese eine vollkommen klare Bedeutung haben, sollten sie einfach als tote Daten modelliert werden. In Bezug auf die Datenbank ist hier nur eine Tabelle erforderlichCREATE TABLE entry (price INTEGER, quantity INTEGER)
Jo So

160

Viele integrierte Produkte (insbesondere von Apple) wie iPods und iPads sind ein gutes Beispiel für eine enge Kopplung: Sobald der Akku leer ist, können Sie auch ein neues Gerät kaufen, da der Akku fest verlötet ist und sich nicht löst teuer. Ein lose gekoppelter Spieler würde es ermöglichen, die Batterie mühelos zu wechseln.

Gleiches gilt für die Softwareentwicklung: Es ist im Allgemeinen (viel) besser, lose gekoppelten Code zu haben, um das Erweitern und Ersetzen zu erleichtern (und um das Verständnis einzelner Teile zu erleichtern). In seltenen Fällen kann jedoch eine enge Kopplung vorteilhaft sein, da die enge Integration mehrerer Module eine bessere Optimierung ermöglicht.


Ist lose oder dichte Kupplung gut? Wie entscheidet man sich für eine lose oder enge Kupplung?
Sreekanth Karumanaghat

2
Vielen Dank für dieses großartige Beispiel. Ich verbrachte viel Zeit mit anderen Antworten, aber nicht so wert
Alamin

1
Sreekanth Karumanaghat, möchten Sie lieber weniger Geld nur für einen Akku ausgeben und wieder einen funktionierenden iPod haben, oder möchten Sie lieber viel Geld für einen ganzen iPod ausgeben?
Koshera

1
@SreekanthKarumanaghat In der Regel ist eine lose Kopplung besser, da sie die Modularität fördert und somit die Wartung des Codes erleichtert. Wenn Sie Ihre Klassen / Bibliotheken / Code eng miteinander verbinden, muss jede kleine Änderung, die Sie in einer Klasse vornehmen, in allen Klassen implementiert werden, die sie verwenden.
Kenny Worden

56

Ich werde Java als Beispiel verwenden. Nehmen wir an, wir haben eine Klasse, die so aussieht:

public class ABC
{
   public void doDiskAccess() {...}
}

Wenn ich die Klasse anrufe, muss ich so etwas tun:

ABC abc = new ABC();

abc. doDiskAccess();

So weit, ist es gut. Nehmen wir jetzt an, ich habe eine andere Klasse, die so aussieht:

public class XYZ
{
   public void doNetworkAccess() {...}
}

Es sieht genauso aus wie ABC, aber sagen wir, es funktioniert über das Netzwerk anstatt auf der Festplatte. Schreiben wir nun ein Programm wie das folgende:

if(config.isNetwork()) new XYZ().doNetworkAccess();
else new ABC().doDiskAccess();

Das funktioniert, ist aber etwas unhandlich. Ich könnte dies mit einer Schnittstelle wie dieser vereinfachen:

public interface Runnable
{
    public void run();
}

public class ABC implements Runnable
{
   public void run() {...}
}

public class XYZ implements Runnable
{
   public void run() {...}
}

Jetzt kann mein Code so aussehen:

Runnable obj = config.isNetwork() ? new XYZ() : new ABC();

obj.run();

Sehen Sie, wie viel sauberer und einfacher das zu verstehen ist? Wir haben gerade den ersten Grundgedanken der losen Kopplung verstanden: die Abstraktion. Der Schlüssel von hier aus ist sicherzustellen, dass ABC und XYZ nicht von Methoden oder Variablen der Klassen abhängen, die sie aufrufen. Dadurch können ABC und XYZ völlig unabhängige APIs sein. Mit anderen Worten, sie sind von den übergeordneten Klassen "entkoppelt" oder "lose gekoppelt".

Aber was ist, wenn wir Kommunikation zwischen den beiden brauchen? Dann können wir weitere Abstraktionen wie ein Ereignismodell verwenden, um sicherzustellen, dass der übergeordnete Code niemals mit den von Ihnen erstellten APIs gekoppelt werden muss.


2
Dieses Beispiel weist immer noch einen recht hohen Kopplungsgrad auf. Anstatt an eine einzelne Klasse gebunden zu sein, stehen gerade zwei zur Auswahl. In diesem Beispiel wird davon ausgegangen, dass immer nur zwei "ausführbare" Implementierungen verfügbar sind. In diesem Fall ist nicht einmal eine Schnittstelle erforderlich.
Owen

Diese Run * - und Do * -benannten Methoden sind für mich ein riesiger Codegeruch. Sie können dies auch in IHandleStuff oder IFrobnicateThings umgestalten. Runnable ist in diesem Fall ein viel zu allgemeiner Begriff.
Wedge

8
Owen, Baby tritt mein Freund. Wenn er die Kopplung nicht versteht, wie wird er dann verstehen, was ihm ein Fabrikmuster kauft? Dieses Codebeispiel bringt ihn auf den richtigen Weg. Die Absicht ist, dass er das Problem besser versteht und erkennt, wie man die Erstellung der Objekte abstrahiert.
64BitBob

6
Wäre dies besser lesbar, wenn ABC und XYZ so etwas wie DiskAccessorund umbenannt würden NetworkAccessor? Ich weiß nicht, kein Java ...
MusiGenesis

Verwendet es auch ein Werksmuster? Weil wir je nach Bedarf neue XYZ- oder ABC-Objekte erstellen.
Munmunbb

37

Entschuldigung, aber "lose Kopplung" ist kein Codierungsproblem, sondern ein Designproblem. Der Begriff "lose Kopplung" steht in engem Zusammenhang mit dem gewünschten Zustand "hoher Kohäsion", der entgegengesetzt, aber komplementär ist.

Lose Kopplung bedeutet einfach, dass einzelne Designelemente so konstruiert werden sollten, dass weniger unnötige Informationen über andere Designelemente benötigt werden.

Hohe Kohäsion ist wie eine "enge Kopplung", aber hohe Kohäsion ist ein Zustand, in dem Designelemente, die wirklich voneinander wissen müssen, so gestaltet sind, dass sie sauber und elegant zusammenarbeiten.

Der Punkt ist, dass einige Designelemente Details über andere Designelemente kennen sollten, daher sollten sie auf diese Weise und nicht versehentlich entworfen werden. Andere Designelemente sollten keine Details zu anderen Designelementen kennen, daher sollten sie absichtlich und nicht zufällig auf diese Weise entworfen werden.

Die Implementierung bleibt dem Leser als Übung überlassen :).


33

Eng gekoppelter Code beruht auf einer konkreten Implementierung. Wenn ich eine Liste von Zeichenfolgen in meinem Code benötige und diese so deklariere (in Java)

ArrayList<String> myList = new ArrayList<String>();

dann bin ich abhängig von der ArrayList-Implementierung.

Wenn ich das in lose gekoppelten Code ändern möchte, mache ich meine Referenz zu einem Schnittstellentyp (oder einem anderen abstrakten Typ).

List<String> myList = new ArrayList<String>();

Dies hindert mich daran, eine Methode aufzurufen myList, die für die ArrayList-Implementierung spezifisch ist. Ich beschränke mich nur auf die Methoden, die in der List-Oberfläche definiert sind. Wenn ich später beschließe, dass ich wirklich eine LinkedList benötige, muss ich meinen Code nur an einer Stelle ändern, an der ich die neue Liste erstellt habe, und nicht an 100 Stellen, an denen ich ArrayList-Methoden aufgerufen habe.

Natürlich können Sie können eine Arraylist mit der ersten Erklärung instanziiert und zurückhalten , sich von keine Methoden , die nicht Teil der Liste Schnittstelle, aber die zweite Erklärung unter Verwendung macht den Compiler Sie ehrlich halten.


Dies bezieht sich kaum darauf, was "Kopplung" eigentlich ist . Einige gute Antworten finden Sie unter stackoverflow.com/questions/39946/coupling-and-cohesion .
Rogério

@ Rogerio: Ich denke, es bezieht sich. Vielleicht sind Sie durch andere Definitionen von "Kopplung" verwirrt, aber Sie sollten " Lose Kopplung " lesen . "Eine starke Kopplung tritt auf, wenn eine abhängige Klasse einen Zeiger direkt auf eine konkrete Klasse enthält, die das erforderliche Verhalten liefert ... Eine lose Kopplung tritt auf, wenn die abhängige Klasse nur einen Zeiger auf eine Schnittstelle enthält, die dann von einer oder mehreren konkreten Klassen implementiert werden kann . " In meinem Beispiel wäre mein Code über die List-Schnittstelle lose mit einer ArrayList verbunden.
Bill the Lizard

@ Bill: Danke für den Link, aber dieser Artikel scheint mir völlig falsch zu sein. Es scheint Ideen aus einem anderen Bereich (organisatorisches Verhalten) "neu zu interpretieren" und eine Definition von "loser Kopplung" zu geben, die der ursprünglichen softwarespezifischen Definition von Larry Constantine widerspricht: en.wikipedia.org/wiki/Coupling_(computer_science) .
Rogério

@ Rogerio: Constantines Artikel wurde 1974 geschrieben. Es ist wahrscheinlich, dass in den letzten 36 Jahren viel neu interpretiert wurde, aber ich glaube nicht, dass der Wikipedia-Artikel die Quelle ist. Zum Beispiel basieren Muster wie Dependency Injection auf Schnittstellen, um die Kopplung zu lösen, wie ich es in meiner Antwort beschrieben habe.
Bill the Lizard

2
@ Bill: Sicher, Constantines Arbeit an strukturiertem Design ist altes Zeug, aber ich sehe keinen Grund, es ungültig zu machen oder radikal neu zu interpretieren. Die ursprünglichen Konzepte von Kohäsion und Kopplung bilden ebenso den Kern des objektorientierten Designs wie Vererbung und Polymorphismus. DI (ein besserer Artikel ist martinfowler.com/articles/injection.html ) ist lediglich eine Technik für die externe Konfiguration von Plug-Ins (abstrakte Schnittstellen zu Implementierungen, die zur Laufzeit über den Konfigurationscode ausgewählt werden). Eine andere solche Technik ist das Service Locator-Muster. DI und Kopplung sind unabhängige Konzepte.
Rogério

26

Der Grad der Unterschiede zwischen den Antworten zeigt, warum es schwierig wäre, ein Konzept zu verstehen, es aber so einfach auszudrücken, wie ich es beschreiben kann:

Damit ich weiß, dass wenn ich einen Ball zu dir werfe, du ihn fangen kannst, muss ich wirklich nicht wissen, wie alt du bist. Ich muss nicht wissen, was du zum Frühstück gegessen hast, und es ist mir wirklich egal, wer dein erster Schwarm war. Ich muss nur wissen, dass du fangen kannst. Wenn ich das weiß, ist es mir egal, ob du es bist. Ich werfe dir oder deinem Bruder einen Ball.

Mit nicht dynamischen Sprachen wie c # oder Java usw. erreichen wir dies über Schnittstellen. Nehmen wir also an, wir haben die folgende Schnittstelle:

public ICatcher
{
   public void Catch();
}

Nehmen wir an, wir haben folgende Klassen:

public CatcherA : ICatcher
{
   public void Catch()
   {
      console.writeline("You Caught it");
   }

}
public CatcherB : ICatcher
{
   public void Catch()
   {
      console.writeline("Your brother Caught it");
   }

}

Jetzt implementieren sowohl CatcherA als auch CatcherB die Catch-Methode, sodass der Dienst, der einen Catcher benötigt, eine dieser Methoden verwenden kann und sich nicht wirklich darum kümmert, um welche es sich handelt. Ein eng gekoppelter Dienst könnte also direkt einen gefangenen dh auslösen

public CatchService
{
   private CatcherA catcher = new CatcherA();

   public void CatchService()
   {
      catcher.Catch();
   }

}

Der CatchService kann also genau das tun, was er sich vorgenommen hat, verwendet jedoch CatcherA und verwendet immer CatcherA. Es ist hart codiert, also bleibt es dort, bis jemand kommt und es umgestaltet.

Nehmen wir nun eine andere Option, die Abhängigkeitsinjektion:

public CatchService
{
   private ICatcher catcher;

   public void CatchService(ICatcher catcher)
   {
      this.catcher = catcher;
      catcher.Catch();
   }
}

Der Calss, der CatchService auslöst, kann also Folgendes tun:

CatchService catchService = new CatchService(new CatcherA());

oder

CatchService catchService = new CatchService(new CatcherB());

Dies bedeutet, dass der Catch-Service weder mit CatcherA noch mit CatcherB eng verbunden ist.

Es gibt mehrere andere Strategien für lose Kopplungsdienste wie diesen, wie die Verwendung eines IoC-Frameworks usw.


1
Ich mag dieses Beispiel besser als die anderen, da so etwas in der Geschäftswelt jeden Tag passiert. Wenn Class Person läuft, Class Cat läuft, Class Dog läuft usw. Es wäre ein riesiges Programm, alle Klassen, die ausgeführt werden, detailliert darzustellen. Die Verwendung einer Schnittstelle namens "Läufe", bei der jede Klasse dasselbe tut, macht Ihr Programm jedoch viel flexibler und verwaltbarer. :)
sksallaj

Wirklich gut erklärt, Sir, nur um im letzten Beispiel zu verdeutlichen, dass Sie es mit Abhängigkeitsinjektion gemacht haben, und das erste Beispiel ist auch lose gekoppelt?
Ali Sajid

Wow, alte Antwort kommentiert :). Die Antwort lautet also nein, das erste Beispiel hat eine starke Abhängigkeit von CatcherA, so dass sie stark gekoppelt sind
Owen

23

Sie können sich (enge oder lockere) Kopplung buchstäblich als den Aufwand vorstellen, den Sie benötigen würden, um eine bestimmte Klasse von ihrer Abhängigkeit von einer anderen Klasse zu trennen. Wenn zum Beispiel jede Methode in Ihrer Klasse unten einen kleinen Block blockiert hat, in dem Sie Log4Net aufgerufen haben, um etwas zu protokollieren, würden Sie sagen, dass Ihre Klasse eng mit Log4Net verbunden ist. Wenn Ihre Klasse stattdessen eine private Methode namens LogSomething enthielt, die der einzige Ort war, an dem die Log4Net-Komponente aufgerufen wurde (und die anderen Methoden stattdessen alle LogSomething), würden Sie sagen, dass Ihre Klasse lose mit Log4Net gekoppelt war (weil es nicht viel dauern würde versuchen, Log4Net herauszuziehen und durch etwas anderes zu ersetzen).


1
"Locker gekoppelt" bedeutet also tatsächlich weniger Abhängigkeiten? Hab ich recht?
user314362

4
Es hängt nicht wirklich mit der Gesamtzahl der Abhängigkeiten zusammen, die eine bestimmte Klasse hat. Die Kopplung (eng oder locker) ist eigentlich eine Eigenschaft der Beziehung zwischen zwei Klassen. Sie können also eine Klasse haben, die lose mit 100 anderen Klassen verbunden ist, oder eine andere Klasse, die eng mit nur zwei anderen Klassen verbunden ist (zum Beispiel).
MusiGenesis

2
Schlechtes Beispiel, ich würde sagen: Was Sie haben, ist Code-Duplizierung, keine enge Kopplung. Und mit einem guten Refactoring-Tool können solche Duplikate in Sekundenschnelle beseitigt werden.
Rogério

@ Rogerio: Es ist wahrscheinlich nicht das beste Beispiel. Ich selbst mag 64BitBobdie Antwort besser.
MusiGenesis

12

Definition

Im Wesentlichen ist die Kopplung, wie sehr ein bestimmtes Objekt oder eine bestimmte Objektgruppe von einem anderen Objekt oder einer anderen Objektgruppe abhängt, um seine Aufgabe zu erfüllen.

Hohe Kopplung

Denken Sie an ein Auto. Damit der Motor anspringt, muss ein Schlüssel in die Zündung gesteckt, gedreht, Benzin vorhanden sein, ein Funke entstehen, Kolben müssen zünden und der Motor muss lebendig werden. Man könnte sagen, dass ein Automotor stark an mehrere andere Objekte gekoppelt ist. Dies ist eine hohe Kopplung, aber keine schlechte Sache.

Lose Kopplung

Stellen Sie sich ein Benutzersteuerelement für eine Webseite vor, mit der Benutzer bestimmte Informationen veröffentlichen, bearbeiten und anzeigen können. Mit dem einzelnen Steuerelement kann ein Benutzer eine neue Information veröffentlichen oder eine neue Information bearbeiten. Das Steuerelement sollte für zwei verschiedene Pfade freigegeben werden können - neu und bearbeiten. Wenn das Steuerelement so geschrieben ist, dass es Daten von den Seiten benötigt, die es enthalten, kann man sagen, dass es zu stark gekoppelt ist. Das Steuerelement sollte nichts von seiner Containerseite benötigen.


7

Es ist ein ziemlich allgemeines Konzept, daher geben Codebeispiele nicht das ganze Bild wieder.

Ein Mann hier bei der Arbeit sagte zu mir: "Muster sind wie Fraktale. Sie können sie sehen, wenn Sie ganz nah heran zoomen und wenn Sie weit auf die Architekturebene hinauszoomen."

Das Lesen der kurzen Wikipedia-Seite kann Ihnen einen Eindruck von dieser Allgemeinheit vermitteln:

http://en.wikipedia.org/wiki/Loose_coupling

Soweit ein bestimmtes Codebeispiel ...

Hier ist eine lose Kopplung, mit der ich kürzlich gearbeitet habe, aus dem Microsoft.Practices.CompositeUI-Material.

    [ServiceDependency]
    public ICustomizableGridService CustomizableGridService
    {
        protected get { return _customizableGridService; }
        set { _customizableGridService = value; }
    }

Dieser Code deklariert, dass diese Klasse von einem CustomizableGridService abhängig ist. Anstatt nur direkt auf die genaue Implementierung des Dienstes zu verweisen, wird lediglich angegeben, dass eine EINIGE Implementierung dieses Dienstes erforderlich ist. Zur Laufzeit löst das System diese Abhängigkeit auf.

Wenn das nicht klar ist, können Sie hier eine ausführlichere Erklärung lesen:

http://en.wikipedia.org/wiki/Dependency_injection

Stellen Sie sich vor, ABCCustomizableGridService ist die Implementierung, die ich hier anschließen möchte.

Wenn ich möchte, kann ich das herausziehen und durch XYZCustomizableGridService oder StubCustomizableGridService ersetzen, ohne die Klasse mit dieser Abhängigkeit zu ändern.

Wenn ich direkt auf ABCCustomizableGridService verwiesen hätte, müsste ich Änderungen an diesen / diesen Referenzen vornehmen, um eine andere Service-Implementierung auszutauschen.


6

Die Kopplung hat mit Abhängigkeiten zwischen Systemen zu tun, bei denen es sich um Codemodule (Funktionen, Dateien oder Klassen), Tools in einer Pipeline, Server-Client-Prozesse usw. handeln kann. Je weniger allgemein die Abhängigkeiten sind, desto "enger gekoppelt" werden sie, da das Ändern eines Systems das Ändern der anderen Systeme erfordert, die darauf angewiesen sind. Die ideale Situation ist die "lose Kopplung", bei der ein System geändert werden kann und die davon abhängigen Systeme ohne Änderung weiterarbeiten.

Der allgemeine Weg, um eine lose Kopplung zu erreichen, führt über gut definierte Schnittstellen. Wenn die Interaktion zwischen zwei Systemen gut definiert ist und auf beiden Seiten eingehalten wird, ist es einfacher, ein System zu ändern und gleichzeitig sicherzustellen, dass die Konventionen nicht verletzt werden. In der Praxis kommt es häufig vor, dass keine genau definierte Schnittstelle eingerichtet wird, was zu einem schlampigen Design und einer engen Kopplung führt.

Einige Beispiele:

  • Die Anwendung hängt von einer Bibliothek ab. Bei enger Kopplung bricht die App bei neueren Versionen der Bibliothek ab. Google für "DLL Hell".

  • Die Client-App liest Daten von einem Server. Bei enger Kopplung erfordern Änderungen am Server Korrekturen auf der Clientseite.

  • Zwei Klassen interagieren in einer objektorientierten Hierarchie. Bei enger Kopplung erfordern Änderungen an einer Klasse, dass die andere Klasse entsprechend aktualisiert wird.

  • Mehrere Befehlszeilentools kommunizieren in einer Pipe. Wenn sie eng miteinander verbunden sind, führen Änderungen an der Version eines Befehlszeilentools zu Fehlern in den Tools, die die Ausgabe lesen.


5

Kopplung bezieht sich darauf, wie eng verschiedene Klassen miteinander verbunden sind. Eng gekoppelte Klassen enthalten eine hohe Anzahl von Interaktionen und Abhängigkeiten.

Locker gekoppelte Klassen sind insofern das Gegenteil, als ihre Abhängigkeiten voneinander auf ein Minimum beschränkt sind und stattdessen auf den genau definierten öffentlichen Schnittstellen voneinander beruhen.

Legos, das Spielzeug, das SNAP zusammenhält, wird als lose gekoppelt betrachtet, da Sie die Teile einfach zusammenschnappen und das gewünschte System erstellen können. Ein Puzzle hat jedoch Teile, die fest miteinander verbunden sind. Sie können ein Teil eines Puzzles (Systems) nicht nehmen und in ein anderes Puzzle einrasten lassen, da das System (Puzzle) sehr stark von den sehr spezifischen Teilen abhängt, die für dieses bestimmte „Design“ spezifisch gebaut wurden. Die Legos sind allgemeiner gebaut, so dass sie in Ihrem Lego House oder in meinem Lego Alien Man verwendet werden können.

Referenz: https://megocode3.wordpress.com/2008/02/14/coupling-and-cohesion/


4

Zwei Komponenten sind eng miteinander verbunden, wenn sie von einer konkreten Umsetzung abhängen.

Angenommen, ich habe diesen Code irgendwo in einer Methode in meiner Klasse:

this.some_object = new SomeObject();

Jetzt hängt meine Klasse von SomeObject ab und sie sind stark gekoppelt. Angenommen, ich habe eine Methode InjectSomeObject:

void InjectSomeObject(ISomeObject so) { // note we require an interface, not concrete implementation
  this.some_object = so;
}

Dann kann das erste Beispiel einfach injiziertes SomeObject verwenden. Dies ist beim Testen hilfreich. Im normalen Betrieb können Sie schwere, datenbank- und netzwerkbenutzende Klassen usw. verwenden, während Sie für Tests eine leichte, nachgebildete Implementierung bestehen. Mit eng gekoppeltem Code können Sie das nicht tun.

Sie können einige Teile dieser Arbeit vereinfachen, indem Sie Abhängigkeitsinjektionscontainer verwenden. Weitere Informationen zu DI finden Sie unter Wikipedia: http://en.wikipedia.org/wiki/Dependency_injection .

Es ist manchmal leicht, dies zu weit zu bringen. Irgendwann müssen Sie die Dinge konkretisieren, sonst ist Ihr Programm weniger lesbar und verständlich. Verwenden Sie diese Techniken also hauptsächlich an der Komponentengrenze und wissen Sie, was Sie tun. Stellen Sie sicher, dass Sie die lose Kupplung nutzen. Wenn nicht, brauchen Sie es wahrscheinlich nicht an diesem Ort. DI kann Ihr Programm komplexer machen. Stellen Sie sicher, dass Sie einen guten Kompromiss eingehen. Mit anderen Worten, halten Sie ein gutes Gleichgewicht. Wie immer beim Entwerfen von Systemen. Viel Glück!


3

Betrachten Sie eine Windows-App mit FormA und FormB. FormA ist das primäre Formular und zeigt FormB an. Stellen Sie sich vor, FormB muss Daten an sein übergeordnetes Element zurückgeben.

Wenn Sie dies getan haben:

class FormA 
{
    FormB fb = new FormB( this );

    ...
    fb.Show();
}

class FormB 
{
    FormA parent;

    public FormB( FormA parent )
    {
        this.parent = parent;
    }     
}

FormB ist eng an FormA gekoppelt. FormB kann kein anderes übergeordnetes Element als das vom Typ FormA haben.

Wenn Sie andererseits FormB ein Ereignis veröffentlichen lassen und FormA dieses Ereignis abonnieren lässt, kann FormB Daten durch dieses Ereignis an den Abonnenten dieses Ereignisses zurücksenden. In diesem Fall weiß FormB nicht einmal, wie es mit seinem Elternteil spricht. Durch die lose Kopplung spricht das Ereignis einfach mit den Abonnenten. Jeder Typ kann jetzt FormA übergeordnet sein.

rp


3

In der Informatik gibt es eine andere Bedeutung für "lose Kopplung", über die hier noch niemand geschrieben hat, also ... Hier geht's - hoffentlich geben Sie mir ein paar Stimmen, damit dies nicht am Ende des Haufens verloren geht! Sicherlich gehört das Thema meiner Antwort in jede umfassende Antwort auf die Frage ... Das heißt:

Der Begriff "Loose Coupling" wurde erstmals als Adjektiv für die CPU-Architektur in einer Konfiguration mit mehreren CPUs verwendet. Sein Gegenbegriff ist "enge Kopplung". Lose Kopplung ist, wenn CPUs nicht viele Ressourcen gemeinsam nutzen, und enge Kopplung ist, wenn sie dies tun.

Der Begriff "System" kann hier verwirrend sein. Bitte analysieren Sie die Situation sorgfältig.

Normalerweise, aber nicht immer, sind mehrere CPUs in einer Hardwarekonfiguration, in der sie in einem System vorhanden sind (wie in einzelnen "PC" -Boxen), eng miteinander verbunden. Mit Ausnahme einiger Super-Hochleistungssysteme mit Subsystemen, die den Hauptspeicher tatsächlich über "Systeme" hinweg gemeinsam nutzen, sind alle teilbaren Systeme lose miteinander verbunden.

Die Begriffe "eng gekoppelt" und "lose gekoppelt" wurden eingeführt, bevor Multithread- und Multi-Core-CPUs erfunden wurden. Daher benötigen diese Begriffe möglicherweise einige Begleiter, um die heutige Situation vollständig zu artikulieren. Und tatsächlich kann man heute sehr wohl ein System haben, das beide Typen in einem Gesamtsystem umfasst. In Bezug auf aktuelle Softwaresysteme gibt es zwei gemeinsame Architekturen, eine von jeder Sorte, die häufig genug sind, um bekannt zu sein.

Erstens, da es sich um die Frage handelte, einige Beispiele für lose gekoppelte Systeme:

  • VaxClusters
  • Linux-Cluster

Im Gegensatz dazu einige eng gekoppelte Beispiele:

  • Semetrical-Multi-Processing (SMP) -Betriebssysteme - z. B. Fedora 9
  • Multithread-CPUs
  • Multi-Core-CPUs

In der heutigen Datenverarbeitung sind Beispiele für beide, die in einem einzigen Gesamtsystem arbeiten, keine Seltenheit. Nehmen Sie zum Beispiel moderne Pentium-Dual- oder Quad-Core-CPUs mit Fedora 9 - dies sind eng gekoppelte Computersysteme. Kombinieren Sie dann mehrere davon in einem lose gekoppelten Linux-Cluster, und Sie haben jetzt sowohl lose als auch eng gekoppelte Computer im Gange! Oh, ist moderne Hardware nicht wunderbar!


3

In einfacher Sprache bedeutet lose gekoppelt, dass es nicht von einem anderen Ereignis abhängt. Es wird unabhängig ausgeführt.


1
Das ist nicht wirklich wahr - wie in anderen Beispielen erwähnt, geht es nicht so sehr darum, ob eine Beziehung zwischen Entitäten (Modulen, Klassen) besteht oder nicht, sondern ob sie leicht gegen andere Klassen ausgetauscht werden können, die dieselbe Funktionalität implementieren. Beispiel: Ein ViewModel funktioniert möglicherweise mit verschiedenen Modellen, aber ohne eines funktioniert es definitiv nicht
Hayden Crocker

eh, nicht sehr hilfreich
brgs

2

Einige lange Antworten hier. Das Prinzip ist jedoch sehr einfach. Ich reiche die Eröffnungserklärung von Wikipedia ein :

"Lose Kopplung beschreibt eine belastbare Beziehung zwischen zwei oder mehr Systemen oder Organisationen mit einer Art Austauschbeziehung.

Jedes Ende der Transaktion macht seine Anforderungen explizit und macht nur wenige Annahmen über das andere Ende. "


1
Wenn es so einfach wäre, hätten wir diese Diskussion nicht.
Brgs

2

Ich schlage einen sehr einfachen Test der Codekopplung vor :

  1. Teil A des Codes ist eng mit Teil B des Codes gekoppelt, wenn eine mögliche Änderung am Teil B vorliegt, die Änderungen in Teil A erzwingen würde, um die Richtigkeit zu gewährleisten.

  2. Teil A des Codes ist nicht eng mit Teil B des Codes verbunden, wenn keine mögliche Änderung an Teil B vorliegt, die eine Änderung an Teil A erforderlich machen würde.

Auf diese Weise können Sie überprüfen, wie viel Kopplung zwischen den Teilen Ihres Codes besteht. Weitere Informationen hierzu finden Sie in diesem Blogbeitrag: http://marekdec.wordpress.com/2012/11/14/loose-coupling-tight-coupling-decoupling-what-is-that-all-about/


2

Wenn Sie ein Objekt einer Klasse mit erstellen new Schlüsselwort in einer anderen Klasse , führen Sie tatsächlich eine enge Kopplung durch (schlechte Praxis). Stattdessen sollten Sie eine lose Kopplung verwenden, was eine gute Praxis ist

--- A.java ---

package interface_package.loose_coupling;

public class A {

void display(InterfaceClass obji)
{
    obji.display();
    System.out.println(obji.getVar());
}
}

--- B.java ---

package interface_package.loose_coupling;

public class B implements InterfaceClass{

private String var="variable Interface";

public String getVar() {
    return var;
}

public void setVar(String var) {
    this.var = var;
}

@Override
public void display() {
    // TODO Auto-generated method stub
    System.out.println("Display Method Called");
}
}

--- InterfaceClass ---

package interface_package.loose_coupling;

public interface InterfaceClass {

void display();
String getVar();
}

---Hauptklasse---

package interface_package.loose_coupling;

public class MainClass {

public static void main(String[] args) {
    // TODO Auto-generated method stub

    A obja=new A();
    B objb=new B();
    obja.display(objb);     //Calling display of A class with object of B class 

}
}

Erläuterung:

Im obigen Beispiel haben wir zwei Klassen A und B.

Klasse B implementiert Interface, dh InterfaceClass.

InterfaceClass definiert einen Vertrag für die B-Klasse, da InterfaceClass über abstrakte Methoden der B-Klasse verfügt, auf die jede andere Klasse zugreifen kann, z. B. A.

In Klasse A haben wir eine Anzeigemethode, die Objekte der Klasse ausschließen kann, die InterfaceClass implementieren (in unserem Fall ist es die Klasse B). Und für dieses Objekt ruft die Methode der Klasse A display () und getVar () der Klasse B auf

In MainClass haben wir ein Objekt der Klassen A und B erstellt und die Anzeigemethode von A aufgerufen, indem wir ein Objekt der Klasse B übergeben haben, dh objb. Die Anzeigemethode von A wird mit einem Objekt der Klasse B aufgerufen.

Ich spreche jetzt von loser Kopplung. Angenommen, Sie müssen in Zukunft den Namen der Klasse B in ABC ändern, dann müssen Sie den Namen in der Anzeigemethode der Klasse B nicht ändern. Erstellen Sie einfach das Objekt new (ABC-Klasse) und übergeben Sie es an die Anzeigemethode in MailClass. In Klasse A müssen Sie nichts ändern

ref: http://p3lang.com/2013/06/loose-coupling-example-using-interface/


0

Sie können mehr über das generische Konzept der "losen Kopplung" lesen .

Kurz gesagt, es handelt sich um eine Beschreibung einer Beziehung zwischen zwei Klassen, bei der jede Klasse am wenigsten über die andere weiß und jede Klasse möglicherweise weiterhin einwandfrei funktioniert, unabhängig davon, ob die andere vorhanden ist oder nicht, und ohne Abhängigkeit von der jeweiligen Implementierung der anderen Klasse.


-8

Die lose Kopplung besteht im Allgemeinen aus zwei Akteuren, die unabhängig voneinander an derselben Arbeitslast arbeiten. Wenn Sie also zwei Webserver haben, die dieselbe Back-End-Datenbank verwenden, würden Sie sagen, dass diese Webserver lose miteinander verbunden sind. Eine enge Kopplung würde durch zwei Prozessoren auf einem Webserver veranschaulicht. Diese Prozessoren sind eng gekoppelt.

Hoffe das ist etwas hilfreich.


1
Ich verstehe, was Sie vorhaben, aber es ist immer noch keine sehr gute Möglichkeit zu erklären, dass eng gekoppelt ist, wenn zwei 'Dinge' voneinander abhängig sind, im Vergleich zu lose gekoppelt, wenn zwei 'Dinge' unabhängig voneinander existieren - wo ein 'Ding' kann ohne Änderungen am anderen 'Ding' ausgetauscht werden ...
Bryan Rehbein

Steve, du hast GENAU Recht - du hast KEINE der Abstimmungen verdient. Es ist nur so, dass Ihr Publikum nicht bereit für Ihre Terminologie war und zu viele auf dieser Website die Angewohnheit haben, abzustimmen, was sie nicht verstehen oder was ihnen unbekannt ist. -shrug-
Richard T

Ich denke, Steve hat den Punkt verpasst. Eine lose Kopplung bedeutet nicht immer, dass zwei Akteure unabhängig voneinander an derselben Arbeitslast arbeiten.
Rob
Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.