Kurz gesagt, wenn Sie "new" verwenden, koppeln Sie die Klasse, die diesen Code enthält, eng mit dem zu erstellenden Objekt. Um eines dieser Objekte zu instanziieren, muss die Klasse, die die Instanziierung durchführt, über die konkrete Klasse Bescheid wissen, die instanziiert wird. Wenn Sie also "neu" verwenden, sollten Sie überlegen, ob die Klasse, in der Sie die Instanziierung platzieren, ein "guter" Ort für dieses Wissen ist und Sie bereit sind, Änderungen in diesem Bereich vorzunehmen, wenn die Form der Das zu instanziierende Objekt sollte sich ändern.
Enge Kopplung, dh ein Objekt mit Kenntnis einer anderen konkreten Klasse, ist nicht immer zu vermeiden; Irgendwann muss etwas, irgendwo, wissen, wie man dieses Objekt erstellt, auch wenn sich alles andere mit dem Objekt befasst, indem man ihm eine Kopie von irgendwo anders gibt. Wenn sich die zu erstellende Klasse ändert, muss jedoch jede Klasse, die über die konkrete Implementierung dieser Klasse Bescheid weiß, aktualisiert werden, um die Änderungen dieser Klasse korrekt zu verarbeiten.
Die Frage, die Sie sich immer stellen sollten, lautet: "Wird es zur Pflicht, wenn diese Klasse weiß, wie diese andere Klasse erstellt wird, wenn Sie die App warten?" Die beiden wichtigsten Entwurfsmethoden (SOLID und GRASP) antworten normalerweise aus subtil unterschiedlichen Gründen mit "Ja". Es handelt sich jedoch nur um Methoden, und beide haben die äußerste Einschränkung, dass sie nicht auf der Grundlage der Kenntnis Ihres einzigartigen Programms formuliert wurden. Als solche können sie nur zur Vorsicht neigen und davon ausgehen, dass ein Punkt mit fester Kopplung EVENTUELL ein Problem verursacht, wenn Änderungen an einer oder beiden Seiten dieses Punkts vorgenommen werden. Sie müssen eine endgültige Entscheidung treffen, wenn Sie drei Dinge wissen; die theoretische Best Practice (dh alles locker zu koppeln, weil sich alles ändern kann); die Kosten für die Implementierung der theoretischen Best Practice (die mehrere neue Abstraktionsebenen umfassen kann, die eine Art von Änderung erleichtern und eine andere behindern); und die reale Wahrscheinlichkeit, dass die Art von Änderung, die Sie erwarten, jemals notwendig sein wird.
Einige allgemeine Richtlinien:
Vermeiden Sie eine enge Kopplung zwischen kompilierten Codebibliotheken. Die Schnittstelle zwischen DLLs (oder einer EXE-Datei und ihren DLLs) ist der Hauptort, an dem eine enge Kopplung einen Nachteil darstellt. Wenn Sie eine Änderung an einer Klasse A in DLL X vornehmen und Klasse B in der Haupt-EXE-Datei über Klasse A Bescheid weiß, müssen Sie beide Binärdateien neu kompilieren und freigeben. Innerhalb einer einzelnen Binärdatei ist eine engere Kopplung im Allgemeinen zulässig, da die gesamte Binärdatei ohnehin für jede Änderung neu erstellt werden muss. Manchmal ist es unvermeidlich, mehrere Binärdateien neu zu erstellen, aber Sie sollten Ihren Code so strukturieren, dass Sie ihn nach Möglichkeit vermeiden können, insbesondere in Situationen, in denen die Bandbreite knapp ist (z. B. beim Bereitstellen mobiler Apps; das Pushen einer neuen DLL in einem Upgrade ist weitaus günstiger als das gesamte Programm schieben).
Vermeiden Sie eine enge Kopplung zwischen den wichtigsten "Logikzentren" Ihres Programms. Sie können sich ein gut strukturiertes Programm vorstellen, das aus horizontalen und vertikalen Segmenten besteht. Horizontale Schichten können herkömmliche Anwendungsebenen sein, wie z. B. Benutzeroberfläche, Controller, Domäne, DAO, Daten; Vertikale Segmente können für einzelne Fenster oder Ansichten oder für einzelne "User Stories" definiert werden (wie das Erstellen eines neuen Datensatzes eines Grundtyps). Wenn Sie einen Anruf tätigen, der sich in einem gut strukturierten System nach oben, unten, links oder rechts bewegt, sollten Sie diesen Anruf im Allgemeinen abstrahieren. Wenn die Validierung beispielsweise Daten abrufen muss, sollte sie keinen direkten Zugriff auf die Datenbank haben, sondern eine Schnittstelle zum Abrufen von Daten aufrufen, die von dem tatsächlichen Objekt unterstützt wird, das dies weiß. Wenn eine UI-Steuerung eine erweiterte Logik mit einem anderen Fenster ausführen muss, es sollte die Auslösung dieser Logik über ein Ereignis und / oder einen Rückruf abstrahieren; Es muss nicht bekannt sein, was als Ergebnis ausgeführt wird. So können Sie die Ausführung ändern, ohne das Steuerelement zu ändern, das sie auslöst.
Überlegen Sie auf jeden Fall, wie einfach oder schwierig eine Änderung sein wird und wie wahrscheinlich diese Änderung sein wird. Wenn ein Objekt, das Sie erstellen, immer nur von einer Stelle aus verwendet wird und Sie diese Änderung nicht vorhersehen, ist eine enge Kopplung im Allgemeinen zulässiger und kann in dieser Situation sogar einer losen Kopplung überlegen sein. Lose Kopplung erfordert Abstraktion. Dies ist eine zusätzliche Ebene, die Änderungen an abhängigen Objekten verhindert, wenn sich die Implementierung einer Abhängigkeit ändern muss. Wenn sich jedoch die Schnittstelle selbst ändern muss (Hinzufügen eines neuen Methodenaufrufs oder Hinzufügen eines Parameters zu einem vorhandenen Methodenaufruf), erhöht eine Schnittstelle tatsächlich den Arbeitsaufwand, der für die Änderung erforderlich ist. Sie müssen die Wahrscheinlichkeit abwägen, dass verschiedene Arten von Änderungen das Design beeinflussen.