Welche Entwurfsmuster sind am schlechtesten oder am engsten definiert? [geschlossen]

28

Bei jedem Programmierprojekt versuchen Manager mit früherer Programmiererfahrung zu glänzen, wenn sie einige Entwurfsmuster für Ihr Projekt empfehlen. Ich mag Entwurfsmuster, wenn sie sinnvoll sind oder wenn Sie eine skalierbare Lösung benötigen. Ich habe zum Beispiel Proxies, Observers und Command Patterns positiv eingesetzt und tue dies jeden Tag. Aber ich zögere wirklich, ein Factory-Muster zu verwenden, wenn es nur eine Möglichkeit gibt, ein Objekt zu erstellen, da eine Factory in Zukunft möglicherweise alles einfacher macht, aber den Code kompliziert und nur mit Overhead verbunden ist.

Meine Frage bezieht sich also auf meine zukünftige Karriere und meine Antwort auf Managertypen, die zufällige Musternamen herumwerfen:

Welche Designmuster haben Sie verwendet, die Sie insgesamt zurückgeworfen haben? Welches sind die schlechtesten Entwurfsmuster , die Sie berücksichtigen sollten, außer in einer einzigen Situation, in der sie sinnvoll sind (lesen Sie: Welche Entwurfsmuster sind sehr eng definiert)? (Es ist, als ob ich nach den negativen Bewertungen eines insgesamt guten Amazon-Produkts gesucht hätte, um zu sehen, was die Leute am meisten daran hinderte, Designmuster zu verwenden.) Und ich spreche hier nicht von Anti-Mustern, sondern von Mustern, die normalerweise als solche angesehen werden "gute" Muster.

Bearbeiten: Wie einige geantwortet haben, ist das Problem meistens, dass Muster nicht "schlecht", sondern "falsch verwendet" sind. Wenn Sie Muster kennen, die häufig missbraucht oder sogar schwierig zu verwenden sind, eignen sie sich auch als Antwort.

Akku
quelle
Die meisten Muster vereinfachen zukünftige Änderungen auf einigen Änderungsachsen, aber sie können Änderungen auf anderen Änderungsachsen erschweren. Die Bande von vier Büchern kann besonders gut sagen, wann ein Muster anwendbar ist. Viele nachfolgende Bücher über Muster übersehen diesen Punkt. Nehmen Sie das Besuchermuster als Beispiel. Es erleichtert das Hinzufügen neuer Algorithmen zum Durchlaufen von Bäumen, erschwert jedoch das Hinzufügen neuer Arten von Knoten zum Baum. Außerdem können sich die Traversal-Algorithmen auf einer höheren Ebene als der Baum befinden. Sie müssen berücksichtigen, welche Änderungsachse am wenigsten stabil ist, und das Design anpassen, um Änderungen entlang dieser Achse zu vereinfachen.
Theodore Norvell
Alle im 'Gang of Four'-Buch.
Miles Rout

Antworten:

40

Ich glaube nicht an schlechte Muster, ich glaube, dass Muster schlecht angewendet werden können!

  • IMHO ist der Singleton das am meisten missbrauchte und am meisten falsch angewendete Muster. Menschen scheinen an einer Singleton-Krankheit zu leiden und sehen überall Möglichkeiten für Singletons, ohne Alternativen in Betracht zu ziehen.
  • Das Besuchermuster der IMHO wird am engsten genutzt und die zusätzliche Komplexität wird so gut wie nie gerechtfertigt sein. Ein schönes PDF kann hier abgerufen werden . Nur wenn Sie über eine Datenstruktur verfügen, von der Sie wissen, dass sie durchlaufen wird, während Sie verschiedene Vorgänge an der Datenstruktur ausführen, ohne alle Möglichkeiten im Voraus zu kennen, können Sie dem Besuchermuster eine Chance zum Kampf geben. Es ist aber schön :)

Bei dieser Antwort habe ich nur die GOF-Muster berücksichtigt. Ich kenne nicht alle möglichen Muster gut genug, um sie auch zu berücksichtigen.

KeesDijk
quelle
Ich sehe sehr wenige Verwendungen für Besucher. Singletons ... bring mich nicht zum Laufen. Wenn die Situation für einen nicht perfekt ist, benutze sie nicht.
Michael K
1
Es gibt zwar nur sehr wenige Verwendungszwecke für Visitor, aber wenn doch, löst es sicherlich Probleme. Nach meinem Verständnis ist Vistor für LINQ von wesentlicher Bedeutung.
Quentin-Starin
12
Das Besuchermuster ist entscheidend für die Reduzierung (oder Beseitigung) der zyklomatischen Komplexität in einem Softwareprogramm. Jedes Mal, wenn Sie einen if / else-Baum oder eine switch-Anweisung haben, besteht eine hohe Wahrscheinlichkeit, dass ein Besucher sie ersetzen kann, was eine garantierte Ausführung und Überprüfung der Kompilierungszeit bietet. Der Besucher ist eines der mächtigsten Muster, die ich kenne, und wir verwenden es regelmäßig mit großer Wirkung. Es macht das Testen auch zu einem Traum.
Les Hazlewood
@LesHazlewood Ist Visitor dann nicht nur eine Problemumgehung für unzureichende Programmiersprachen? ML-ähnliche Sprachen (Haskell, SML, OCaml usw.) haben algebraische Datentypen ("Union on Steroids") und Pattern Matching ("Steroide einschalten"), die einfacheren Code als Visitor erzeugen, aber vom Compiler vollständig überprüft werden. Im Vergleich zu Besuchern verfügen Sie nicht über viele Methoden, deren Freigabestatus Sie manuell über Objekteigenschaften verwalten müssen. In ML-ähnlichen Sprachen müssen alle Unterscheidungen in Groß- und Kleinschreibung vollständig sein, da sie sonst nicht kompiliert werden können.
Vog
14

Abgesehen von Singleton und Visitor, die bereits von den anderen Antwortenden erwähnt wurden, kenne ich keine "berüchtigten" Designmuster. Meines Erachtens sind die größten Probleme nicht darauf zurückzuführen, dass ein bestimmtes Entwurfsmuster "falsch" ist, sondern dass Entwickler die Muster zu eifrig anwenden.

Fast jeder durchläuft die "Musterfieber" -Phase, wenn er sich mit Mustern vertraut macht. Da man denkt, dass Muster das Beste seit geschnittenem Brot sind, versucht man sie anfangs anzuwenden, wann immer er eine Möglichkeit sieht. Dies führt dazu, dass der Code unter Mustern verborgen bleibt, bei denen die Muster selbst nicht mehr helfen. Sie erschweren lediglich das Verständnis und die langfristige Pflege des Codes.

Schließlich haben die meisten von uns diese Phase hinter sich und lernen, wie man die Muster verwendet, um echte Probleme zu lösen, nicht um ihrer selbst willen. Muster haben ihren Preis, was eine zusätzliche Komplexität bedeutet, und die Anwendung eines bestimmten Musters ist nur dann gerechtfertigt, wenn es sich für die zusätzliche Komplexität auszahlt, indem es dazu beiträgt, einen anderen Teil des Systems zu vereinfachen und so den Code / die Konfiguration insgesamt leichter verständlich und wartbar zu machen. Wenn dies nicht der Fall ist, ist es oft besser, sich von Mustern fernzuhalten und sich an die einfachste Lösung zu halten, die möglicherweise funktionieren könnte.

Péter Török
quelle
Absolut. Muster sind weder gut noch böse, sie werden gut angewendet oder falsch angewendet.
Ich möchte den Menschen lieber die Art und Weise beibringen, wie ich gelernt habe: OO zuerst, Verstehen, wie sich ein Objekt verhält, und dann die Namen der Muster. Es ist zu einfach, in Mustern zu denken, als was getan werden muss. Sie sind ein Kommunikationswerkzeug.
Michael K
Muster sind ein Mittel zur Kommunikation, keine vorgeschriebene Liste. Wenn Sie mit einem Muster beginnen , wenden Sie es möglicherweise falsch an. Wenn Sie finden ein oder verwenden Sie die Hinweise von einem, in Ihrem Design, dann können die Musterkataloge helfen zu verstehen , was Sie sonst noch brauchen.
Rob Crawford
14

Ich gehe hier auf die Probe und schlage vor, die Vererbung übermäßig zu nutzen. Auf jeden Fall am besten in Sprachen wie Java geeignet, die keinen soliden Polymorphismus zur Kompilierungszeit unterstützen. Die Vererbung zur Laufzeit ist ein Tool, keine Art von One-Feature-Fits-All-Wonder.

Andere Leute haben sich bereits ähnlich zu meinem persönlichen Hass auf Singletons geäußert, daher werde ich hier nicht weiter darauf eingehen.

DeadMG
quelle
10

Singleton. Es ist eines der GOF-Muster, die jetzt häufiger als Anti-Muster bezeichnet werden. Einer der Gründe dafür ist, dass Singleton das Testen von Code erschwert.

SiberianGuy
quelle
4
Es gibt zahlreiche grundlegende Mängel in der Singletonmuster, die meisten sind in diesem Artikel von Steve Yegge gut bebildert - Singleton Dumme betrachtet
ocodo
Slomojo: Schöner Artikel. Ich werde es von nun an "simpleton pattern" nennen:-)
Nobody
2
Ja, weil ein Dummkopf ein Muster missbraucht und das Boot völlig verfehlt, worum es bei OO geht (gemessen an allen Manager-Klassen, die er sich ausgedacht hat), ist es natürlich die Schuld des Musters und nicht die Entwickler.
Dunk
Warum verbindet jeder die gemeinsame (und mühsame) Implementierung von Singleton mit dem Muster Singleton? Einer ist fast immer schlecht, der andere nicht.
Quentin-Starin
1
@qes> Singleton wirft wichtige Implementierungsprobleme auf (insbesondere beim Threading). Das ist schon ein schlechter Punkt. Sie werden jedoch auch feststellen, dass Singleton ein Muster dafür ist, wie die Klasse verklagt wird und nicht, wie sie funktioniert. Wie die Klasse verwendet wird, sollte durch den Code unter Verwendung der Klasse behandelt werden, damit Singleton einen Bruch der Trennung von Bedenken darstellt.
Deadalnix
7

Wenn Sie Muster kennen, die häufig missbraucht oder sogar schwierig zu verwenden sind, eignen sie sich auch als Antwort.

Befolgen Sie das MVVM-Muster für WPF zu genau, wie zum Beispiel in dieser Frage angegeben . Einige Leute versuchen, die Richtlinie zu befolgen, dass kein Code zu streng in den Code eingefügt werden sollte und kommen mit allen Arten von exotischen Hacks.

Und natürlich ist MVVM höllisch schwierig und es lohnt sich einfach nicht für kleine kurzfristige Projekte.

Dr. WPF hat in seinem Artikel MV-poo einen ironischen Beitrag dazu verfasst .

Steven Jeuris
quelle
@Akku: Sie sollten natürlich wissen, wie man es benutzt, damit Sie entscheiden können, ob es für Ihr Projekt geeignet ist. Also ja, es ist wichtig für die WPF-Entwicklung und sehr nützlich.
Steven Jeuris
Eines der Probleme ist, dass die Leute das MVVM-Muster falsch verstehen. Es ist nicht "verdammt schwer". Die Leute machen es so, indem sie denken, dass alle anderen Muster wie Command Pattern und Mediator Pattern Teil davon sind. MVVM ist für sich genommen meines Erachtens eines der einfachsten Muster. Ich stimme dir zu, dass es einfach dumm ist, irgendetwas zu befolgen.
BK
5

Einige der Muster im GOF-Buch sind C ++ -spezifisch, da sie in Sprachen mit Reflektion weniger anwendbar sind, z. B. ist das Prototype-Muster in Java weniger wichtig.

Ich betrachte das Interpreter-Muster als 'eng'. Sie müssen ein allgemeines Problem haben, das es wert ist, einen allgemeinen Problemlöser zu entwickeln. Es funktioniert nur für spezielle Probleme, für die Sie eine Sprache erfinden, eine Grammatik definieren und einen Dolmetscher schreiben können. Die Probleminstanzen sollten als Satz in der Grammatik darstellbar sein. Ich glaube, Sie stoßen nicht oft auf solche Situationen.

Karl
quelle
1
Der Großteil von GOF ist nur auf statische OOPs anwendbar. weichen sie ein wenig von solchen sprachen ab und das buch wird nur zu einer unterhaltungs-anekdote.
Javier
5

Die, die ich am häufigsten bereue (wenn auch nicht am heftigsten): Wenn ich nur eine Funktion hätte erstellen sollen, aber eine OOP-Lösung implementiert habe.

C SD
quelle
1
Warum? Warum hast du es bereut? Bitte erweitern Sie Ihre Antwort und fügen Sie Ihre Erfahrungen hinzu.
Walter
In der Tat denke ich, dass eine Klasse mit lokalen Variablen und klaren Methoden VIEL einfacher wiederzuverwenden ist als eine einzelne 200-Zeilen-Funktion, die nur durch Kopieren und Einfügen erneut angewendet werden kann und dann nicht nur an einer Stelle hässlich und unübersichtlich aussieht.
Akku
2
KISS impliziert, dass Sie es zuerst zu einer Funktion machen und dann bei Bedarf zu einer Klasse umgestalten.
Eva
5

Fabrik. Ich habe gesehen, wie Code es implementiert hat, der nur einen Typ erstellt. Das ist völlig nutzloser Code IMO. Es hilft nicht, dass viele der Online-Beispiele vollständig erfunden sind. Pizzafabrik?

Möglicherweise ist die Fabrik aufgrund der Abhängigkeitsinjektion einfacher zu testen. Aber diesen Code hinzuzufügen, wenn Sie ihn nicht benötigen, ist für mich sinnlos, und das Testargument verschwindet, wenn Sie Schein-Frameworks wie JMockit verwenden können. Je einfacher Sie ein Programm erstellen können, desto besser. Fabriken machen nur mit einer größeren Anzahl von Typen wirklich Sinn (mit größer meine ich mindestens mehr als 2).

Michael K
quelle
Ja, Pizza-Fabrik, danke für Head First Design Pattern ~
Niing
2

Singleton

Ich stimme mit den anderen über Singleton überein. Nicht, dass Sie sie niemals verwenden sollten, nur, dass sie auf sehr wenige Fälle beschränkt sein sollten. Sie werden häufig als faule Globals eingesetzt.

Thread-Sicherheit ist ein Problem bei Singletons. Die Ausnahmebehandlung ist eine andere - wenn der Singleton nicht ordnungsgemäß erstellt wird - Sie wissen nicht immer, ob Sie den Fehler sicher abfangen können, insbesondere wenn es sich um eines dieser Objekte handelt, die "vor main" erstellt wurden. Und dann gibt es das Problem der Reinigung danach.

Ich tendiere dazu, lieber einen Singleton zu verwenden und alle anderen "Möchtegern" Singletons "abonnieren" zu lassen. Meine häufigste Singleton-Verwendung ist die Ereignisbehandlung: Sie "senden nur an die Welt", dass ein Ereignis stattgefunden hat, und jeder, der das Ereignis behandelt, tut dies. Auf diese Weise entkoppeln Sie die tatsächlich stattfindenden Ereignisse mit dem, was sie hören. (Protokollierung, Signale usw.)

Besucher

Das Hässliche daran ist, dass sich Entwickler keine aussagekräftigen Namen einfallen lassen und nur Methoden visit () aufrufen, sondern die Erweiterbarkeit in eine Richtung erhöhen und in eine andere Richtung entfernen, dh zusätzliche Funktionen hinzufügen, aber einschränken Die Anzahl der Objekte, die Ihre Besucher über alle Objekttypen wissen müssen, die sie möglicherweise besuchen.

Es ist zwar chaotisch, die Erweiterung in beide Richtungen zuzulassen, dies verwendet jedoch das Besuchermuster nicht vollständig in seiner regulären Form. Die häufigste Anwendung hierfür ist das Drucken von Objekten: Sie haben verschiedene Möglichkeiten zum Drucken von Objekten und verschiedene Objekte, die gedruckt werden müssen. Sie sollten dies in beide Richtungen erweitern können. (Drucken bedeutet, dass Objekte in einen Stream umgewandelt werden: Speichern in einer Datei / Schreiben in eine Konsole / GUI usw.).

(Hinweis: Sie sollten dies nicht mit der Architektur der Dokumentansicht verwechseln, bei der es sich um ein etwas anderes Muster handelt.)

Goldesel
quelle
2
Ihre Lösung verwendet das alte Argument, mit dem Dinge entkoppelt werden. Insbesondere posten Sie ein Ereignis, und ein anderer Mitarbeiter bearbeitet das Ereignis und protokolliert es. Das ist gut so, denn alle sind entkoppelt! FALSCH! Früher habe ich das getan, was für ein königlicher Schmerz es wurde. Mir wurde klar, dass ich, wenn ich möchte, dass etwas protokolliert wird, explizit genau das sagen möchte, genau hier, genau jetzt, im Code zum Zeitpunkt des Auftretens. Lassen Sie kein anderes Objekt herausfinden, was protokolliert werden soll, mit möglichen anderen Ereignissen, die von anderen Handlern ausgelöst werden, wenn es überhaupt protokolliert wird. Es ist nichts anderes als verschlungenes Überdesign.
Dunk
2

Ich denke, das Problem bei einigen der komplexeren Muster ist, dass es so viele Variationen gibt, dass sie viel von ihrem Wert als Kommunikationsgerät verlieren.

Der schlimmste Täter, den ich mir in dieser Kategorie vorstellen kann, ist das MVC-Muster. Selbst wenn wir MVP ignorieren, gibt es so viele Variationen in den Rollen dieser Elemente, dass Sie eine Stunde in jedem neuen Framework verbringen müssen, um herauszufinden, wo die Grenzen liegen.

Uri
quelle
Ich denke auch, dass MVC überall verwendet werden sollte, aber nicht überall auf die gleiche Weise implementiert werden sollte. Und viele Leute verstehen es nicht. Als ich es zum ersten Mal verwenden wollte, erstellte ich drei Klassen mit den Namen Model, View (ein Windows-Formular) und Controller. Es war ein Durcheinander, da Formulare nicht für MVC gemacht wurden.
Akku
1

Es gibt keine schlechten Muster, nur schlechte Menschen.

Ich würde viel lieber leicht lesbaren Code erben, der etwas Klares bewirkt, aber ein wenig ausführlich oder nicht (Queue Evil Villian Music) wiederverwendbar ist (keuch!), Als irgendeinen Mischmasch von InheritAbstractTemplateFaucetSink<Kitchen>.

Wiederverwendbarer Code ist großartig! Möglicherweise schreiben Sie keinen Code, der erneut verwendet wird, oder das erneute Schreiben einer ähnlichen Logik für eine andere Anwendung würde weniger Zeit in Anspruch nehmen als ein verrückter Versuch, den Code einer anderen Anwendung erneut zu verwenden.

Zum weiteren Lesen öffnen Sie einen Teil des C-Codes in den korrekten Implementierungen der Posix-Header oder der Clibs und spielen Sie das Muster aus. Dieser Code wurde von einigen der intelligentesten und engagiertesten Programmierer der Welt geschrieben. Wissen Sie, wie viele abstrakte Fabrikmuster Sie sehen werden? ... KEINER!. Noch bessere Chancen bestehen darin, dass Sie die Logik sehr leicht verstehen und nachvollziehen können, wenn Sie die anderen Teile des Geschehens verstehen.

Mein Punkt ist, dass die meisten "Muster" nicht erstellt wurden, um den Code zu verbessern. Sie wurden erstellt, um Bücher und Modellierungssoftware zu verkaufen. Wenn Sie gut programmieren können, werden Sie wahrscheinlich die meisten davon vermeiden und klaren, prägnanten und clever gestalteten Code schreiben, der Ihr Problem löst. Wenn Sie ein anderes Problem haben, schreiben Sie klaren, präzisen und clever gestalteten Code, um dieses Problem zu lösen. Wenn es Ihr Ziel ist, weniger Code zu schreiben, als ich denke, Sie sind kein Programmierer. Ich liebe es, Code zu schreiben und möchte ihn so oft wie möglich schreiben. Wenn ich etwas neu schreibe, was ich bereits geschrieben habe, mache ich es zehnmal so schnell und werde all die Dinge los, mit denen ich beim ersten Mal nicht zufrieden war.

Damit hinterlasse ich Ihnen das wahrscheinlich beste (relevante) Zitat in der Informatik.

" Es gibt zwei Möglichkeiten, ein Software-Design zu erstellen: Eine Möglichkeit besteht darin, es so einfach zu gestalten, dass es offensichtlich keine Mängel gibt, und die andere darin, es so kompliziert zu gestalten, dass es keine offensichtlichen Mängel gibt. Die erste Methode ist weitaus schwieriger . "

  • Tony Hoare (Erfinder des Quicksort, Vater des modernen Betriebssystemdesigns, Schöpfer der Hoare-Logik und Turing-Preisträger)
nsfyn55
quelle
0

Ich stimme definitiv zu, dass es eine Zeit für die meisten Muster gibt und dass Sie viele Muster missbrauchen können. Ich weiß, dass das Abstract Template-Muster das ist, das ich in der Vergangenheit am häufigsten missbraucht habe. In vollem Umfang wird es als ASP.NET-Webformulare bezeichnet.

Wyatt Barnett
quelle