Frage

Viele Menschen sind sich darüber einig, dass das Singleton-Muster eine Reihe von Nachteilen hat und einige sogar vorschlagen, das Muster ganz zu vermeiden. Es gibt eine ausgezeichnete Diskussion hier . Bitte richten Sie Ihre Kommentare über die Singleton-Muster auf diese Frage.

Meine Frage : Gibt es anderes Design-Muster, dass vermieden oder mit großer Sorgfalt verwendet werden soll

?
War es hilfreich?

Lösung

Muster sind komplex

Alles Design-Muster sollte mit Vorsicht verwendet werden. Meiner Meinung nach sollten Sie Refactoring in Richtung Muster , wenn es einen triftigen Grund, dies zu tun statt ein Muster sofort umzusetzen. Das allgemeine Problem mit Mustern besteht darin, dass sie die Komplexität hinzuzufügen. Die übermäßige Einsatz von Mustern macht eine bestimmte Anwendung oder ein System umständlich weiter zu entwickeln und zu pflegen.

die meiste Zeit gibt es eine einfache Lösung, und Sie werden keine spezifischen Muster anwenden müssen. Eine gute Faustregel ist, um ein Muster zu verwenden, wenn Teile des Codes neigen oft dazu, zu ersetzen oder geändert werden müssen, und auf dem Vorbehalt von komplexem Code nehmen hergestellt werden, wenn ein Muster verwendet wird.

Beachten Sie, dass Ihr Ziel sollte Einfachheit sein und ein Muster verwenden, wenn Sie sehen, eine praktische Notwendigkeit Änderung im Code zu unterstützen.

Grundsätze über Muster

Es mag wie ein strittigen scheinen Muster zu verwenden, wenn sie offenbar over-engineered und komplexe Lösungen führen können. Allerdings ist es stattdessen viel interessanter für einen Programmierer auf Design-Techniken zu lesen und Prinzipien , die die Grundlage legen für die meisten der Muster. In der Tat eine meiner auf ‚Design Patterns‘ betont diese durch wiederholte auf welchen Prinzipien sind anwendbar auf die Muster in Frage. Sie sind einfach genug, um nützlich zu sein als Muster in Bezug auf die Relevanz. Einige der Prinzipien sind allgemein genug, um mehr als die objektorientierte Programmierung (OOP) zu umfassen, wie zum Beispiel Liskov Substitutionsprinzip , so lange wie Sie Module des Codes erstellen können.

Es gibt eine Vielzahl von Design-Prinzipien, aber die in der erste Kapitel des GoF Buch sind sehr nützlich, mit zu beginnen.

  • Programm auf eine 'Schnittstelle', nicht eine 'Durchführung' (Gang of Four 1995: 18).
  • Favor 'Objekt-Komposition' über 'Klassenvererbung' (Gang of Four 1995: 20).

Lassen Sie diejenigen, sinken in auf Sie für eine Weile. Es ist zu beachten, dass, wenn GoF eine Schnittstelle geschrieben wurde alles bedeutet, dass eine Abstraktion ( was auch bedeutet, Superklassen), nicht zu verwechseln mit der Schnittstelle als Typ in Java oder C #. Das zweite Prinzip kommt aus der beobachteten Übernutzung der Vererbung, die leider ist heute noch üblich .

Von dort können Sie nachlesen auf SOLID Prinzipien , die von Robert Cecil Martin (aka. Onkel Bob) . Scott Hanselman interviewt Onkel Bob in einem Podcast über diese Prinzipien :

  • S ingle Prinzip Verantwortung
  • O Stift Geschlossen-Prinzip
  • L Iskov Substitutionsprinzip
  • I nterface Segregations Prinzip
  • D ependency Inversion Prinzip

Diese Grundsätze sind ein guter Anfang auf lesen und diskutieren Sie mit Ihren Kollegen. Sie können feststellen, dass die Prinzipien miteinander verweben und mit anderen Prozessen wie Trennung von Bedenken und Dependency Injection . Nachdem ich TDD für eine Weile auch finden können Sie, dass diese Grundsätze natürlich in der Praxis kommen, wie Sie brauchen, um folgen sie, um zu einem gewissen Grad zu erstellen getrennt und wiederholbar Unit-Tests.

Andere Tipps

Die eine, die die Autoren von Design Patterns sich die meisten Sorgen um die „Besucher“ Muster war.

Es ist ein „notwendige Übel“ - aber oft über gebrauchte und die Notwendigkeit, es zeigt oft einen grundlegenden Fehler in Ihrem Design

.

Ein alternativer Name für die „Besucher“ Muster „Multi-Dispatch“, weil das Besuchermuster ist das, was Sie am Ende mit, wenn Sie wünschen, eine sorte Dispatch OO-Sprache verwenden, um den Code zu wählen, basierend auf dem verwenden Typ von zwei (oder mehr) verschiedenen Objekten.

Das klassische Beispiel dafür ist, dass Sie die Kreuzung zwischen zwei Formen haben, aber es gibt einen noch einfacheren Fall, die oft übersehen wird:. Die Gleichheit von zwei heterogenen Objekten Vergleich

Wie auch immer, oft am Ende mit etwas wie folgt auf:

interface IShape
{
    double intersectWith(Triangle t);
    double intersectWith(Rectangle r);
    double intersectWith(Circle c);
}

Das Problem dabei ist, dass Sie alle Ihre Implementierungen von „IShape“ gekoppelt sind zusammen. Sie haben angedeutet, dass, wenn Sie eine neue Form der Hierarchie hinzufügen möchten, müssen Sie auch alle anderen „Shape“ Implementierungen ändern.

Manchmal ist dies das richtige minimalistische Design - aber denken Sie es durch. Gibt es in Ihrem Design wirklich Mandat, das Sie auf zwei Arten versenden? Sind Sie bereit, jede der kombinatorischen Explosion von Multi-Methoden zu schreiben?

Oft durch ein anderes Konzept zur Einführung können Sie die Anzahl von Kombinationen reduzieren, die Sie tatsächlich schreiben, gehen zu müssen:

interface IShape
{
    Area getArea();
}

class Area
{
    public double intersectWith(Area otherArea);
    ...
}

Natürlich hängt es - manchmal wirklich brauchen Sie Code zu schreiben, all diese verschiedenen Fälle zu behandeln - aber es lohnt Pause zu nehmen und eine Meinung haben, bevor sie den Sprung und mit Besucher. Es könnte Ihnen eine Menge Schmerz spart später.

Singletons -. Eine Klasse mit Singletons X hat eine Abhängigkeit von ihm, das ist schwer zu sehen, und hart für die Prüfung zu isolieren

Sie sind sehr häufig verwendet, weil sie bequem und einfach zu verstehen, aber sie können wirklich Tests erschweren.

Siehe Singletons sind Pathologische Liars .

Ich glaube, die Template Method-Muster im Allgemeinen ein sehr gefährliches Muster ist.

  • Eine Menge Zeit verwendet sie Ihre Vererbungshierarchie für „den falschen Gründen“ auf.
  • Basisklassen haben eine Tendenz, mit allen Arten von unerelated Code verunreinigten zu werden.
  • Es zwingt Dich Design zu sperren, oft schon früh im Entwicklungsprozess. (Vorzeitige Sperre nach unten in vielen Fällen)
  • Ändern diese zu einem späteren Zeitpunkt wird nur härter und härter.

Ich glaube nicht, sollten Sie Design Patterns (DP) zu vermeiden, und ich glaube nicht, sollten Sie sich zwingen, DPs zu verwenden, wenn Ihre Architektur Planung. Wir sollten nur DPs verwenden, wenn sie natürlich aus unserer Planung entstehen.

Wenn wir von Anfang an zu definieren, dass wir einen bestimmten DP verwenden möchten, werden viele unserer zukünftigen Design-Entscheidungen sein Einfluss durch diese Wahl, ohne Garantie, dass die DP wählten wir für unsere Bedürfnisse geeignet ist.

Eine Sache sollten wir auch nicht tun, ist ein DP als unveränderliche Einheit zu behandeln, sollten wir das Muster auf unsere Bedürfnisse anpassen.

Also, sumarizing, ich glaube nicht, dass wir DPs vermeiden sollten, wir sollten sie annehmen, wenn sie bereits Gestalt in unserer Architektur einnehmen.

Ich denke, dass Active Record ein übertriebenes Muster ist, die Business-Logik mit dem persistance Code fördert das Mischen. Es ist nicht eine sehr gute Arbeit der Speicher Implementierung von der Modellschicht versteckt und bindet die Modelle in einer Datenbank. Es gibt viele Alternativen (beschrieben in PoEAA) wie Table Data Gateway, Row Data Gateway und Data Mapper, die häufig eine bessere Lösung bieten und sicherlich helfen, eine bessere Abstraktion Lagerung zu liefern. Auch Ihr Modell sollte nicht Notwendigkeit in einer Datenbank gespeichert werden; was sie als XML speichern oder sie Web-Services zugreifen? Wie leicht wäre es den Speichermechanismus Ihrer Modelle zu ändern?

Das heißt, Active Record nicht immer schlecht ist und ist ideal für einfachere Anwendungen, bei denen die anderen Optionen zu viel des Guten wäre.

Es ist einfach ... Design Patterns vermeiden, die nicht klar Sie oder solche, die Sie sich nicht wohl fühlen in .

einige nennen ...

gibt es einige unpraktische Muster , wie z.

  • Interpreter
  • Flyweight

es gibt auch einige schwerer zu fassen , wie z.

  • Abstract Factory - Full Abstrakte Fabrik mit den Familien der erstellten Objekte ist nicht so eine Brise, wie es scheint zu sein,
  • Bridge - Kann zu abstrakt bekommen, wenn Abstraktion und Implementierung sind zu Teilstrukturen aufgeteilt, aber es ist sehr brauchbar Muster in einigen Fällen
  • Visitor - Double-Dispatch-Mechanismus Verständnis ist wirklich ein Muss

und es gibt einige Muster, die sehen furchtbar einfach , aber ist nicht so klare Wahl aus verschiedenen Gründen im Zusammenhang mit ihrem Prinzip oder Umsetzung:

  • Singleton - nicht wirklich total schlecht Muster, einfach zu überstrapaziert (oft dort, wo es nicht geeignet ist)
  • Observer - große Muster ... nur machen Code viel schwieriger zu lesen und zu debuggen
  • Prototype - handelt Compiler prüft, ob Dynamik (die gut oder schlecht sein kann ... hängt)
  • Chain of responsibility - zu oft nur gezwungenermaßen / künstlich in die Konstruktion geschoben

Für die „unpraktische ones“, soll man wirklich darüber nachdenken, bevor sie verwendet wird, weil es irgendwo in der Regel elegantere Lösung ist.

Für die „schwerer zu fassen“ Einsen ... sie sind wirklich eine große Hilfe, wenn sie an geeigneten Stellen verwendet werden, und wenn sie gut umgesetzt ... aber sie sind Alptraum, wenn falsch verwendet werden.

Nun, was kommt als nächstes ...

Ich hoffe, ich werde nicht zu viel geschlagen werden für diese. Christer Ericsson schrieb zwei Artikel ( ein , zwei ) zum Thema Design Patterns in seinem Echt Zeit Kollisionserkennung Blog . Sein Ton ist ziemlich hart, und vielleicht ein wenig provokativ, aber der Mann kennt sich aus, also würde ich es als Hirngespinste eines Wahnsinnigen nicht entlassen.

Einige sagen, dass Service Locator ist ein Anti-Muster.

Ich glaube, das Beobachter-Muster eine Menge zu verantworten hat, ist es in sehr allgemeinen Fällen funktioniert, aber als Systeme immer komplexer werden wird es einen Alptraum, um OnBefore (), OnAfter () Benachrichtigungen und oft Entsendung von asynchronen Aufgaben Neueintritt vermeiden. Eine viel bessere Lösung ist es, ein System der automatischen Abhängigkeitsanalyse Instrumente zu entwickeln, die alle Objektzugriffe (mit Lesesperren) während der Berechnungen und erzeugt automatisch eine Kante in einem Abhängigkeitsgraphen.

Eine Ergänzung zu Spoike der Post, Refactoring zu Patterns ist eine gute Lese .

Iterator ist ein weiteres GoF-Muster zu vermeiden oder zumindest zu verwenden nur, wenn keine Alternativen verfügbar sind.

Alternativen sind:

  1. foreach-Schleife. Diese Konstruktion ist in den meisten Mainstream-Sprachen vorhanden und können verwendet werden Iteratoren in der Mehrzahl der Fälle zu vermeiden.

  2. Selektoren à la LINQ oder jQuery. Sie sollen verwendet werden, wenn for-each nicht geeignet ist, da nicht alle Objekte aus dem Container verarbeitet werden soll. Im Gegensatz zu Iteratoren ermöglichen Selektoren an einem Ort zu manifestieren, welche Art Objekte verarbeitet werden.

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top