Switch-Anweisungen sind schlecht?
Habe ich vor kurzem erfahren, dass switch-Anweisungen sind schlecht in OOP, perticularly von "Clean Code"(p37-39) von Robert Martin.
Aber betrachten Sie dieser Szene: ich Schreibe eine Spiel-server, das empfangen von Nachrichten von clients, die enthalten eine ganze Zahl, die angibt, Spieler die Aktion wie bewegen, angreifen, Holen Einzelteil... etc, es werden mehr als 30 verschiedene Handlungen. Wenn ich code schreiben, der Umgang mit diesen Nachrichten, keine metter, was für Lösungen ich überlege, es zu benutzen, Schalter irgendwo. Was Muster sollte ich verwenden, wenn keine switch-Anweisung?
Siehe [Große Switch-Anweisungen: Bad OOP? ](stackoverflow.com/questions/505454/...)
'"Considered Harmful" Considered Harmful'.
oft hinzufügen einer Klasse minimiert die Menge der vorhandenen code zu ändern. Wenn Sie code haben, hängt von den spezifischen Klassen, die bereits vorhanden sind, werden diese wohl switch-Anweisungen (oder Zweigstellen der wenn/dann/sonst), und jeder von diesen wird geändert
beim hinzufügen eines
sicher, wenn die app ist klein, oder es ist wahrscheinlich nicht viel ändern dann wird ein Schalter kann klarer sein. Manchmal "springen"s sind auch OK. Ich wurde nur darauf hin, es gibt gute Gründe, warum Leute sagen, eine Klasse hinzufügen, qualitativ unterschiedliche, vom hinzufügen einen Schalter
'"Considered Harmful" Considered Harmful'.
oft hinzufügen einer Klasse minimiert die Menge der vorhandenen code zu ändern. Wenn Sie code haben, hängt von den spezifischen Klassen, die bereits vorhanden sind, werden diese wohl switch-Anweisungen (oder Zweigstellen der wenn/dann/sonst), und jeder von diesen wird geändert
beim hinzufügen eines
case
zu Ihr zu wechseln, Sie tun müssen, regression tests und entwickeln von Testfällen für diese Klasse. In der Erwägung, dass das hinzufügen einer weiteren Klasse nicht benötigen, dass viele tests entwickelt werden, da es eine "neue Funktionen" und Sie sind sich nicht berühren vorhandenen Quelle, je nachdem, wie Sie laden die neuen Klassen (aka Reflexion), ansonsten regression tests müssen getan werden, auch für die instanziieren codesicher, wenn die app ist klein, oder es ist wahrscheinlich nicht viel ändern dann wird ein Schalter kann klarer sein. Manchmal "springen"s sind auch OK. Ich wurde nur darauf hin, es gibt gute Gründe, warum Leute sagen, eine Klasse hinzufügen, qualitativ unterschiedliche, vom hinzufügen einen Schalter
InformationsquelleAutor Hongbo | 2010-12-11
Du musst angemeldet sein, um einen Kommentar abzugeben.
Ein-Schalter ist wie jedes andere Steuerelement-Struktur. Es gibt Orte, wo es die beste/sauberste Lösung, und vielen weiteren Orten, wo es völlig unangebracht. Es ist nur missbraucht, weit mehr als andere Kontroll-Strukturen.
In OO-design, ist es im Allgemeinen vorzuziehen, als in einer situation, wie Ihnen der Einsatz von verschiedenen message-Typen/Klassen Erben von einer gemeinsamen Klasse Nachricht, dann verwenden Sie überladene Methoden, um "automatisch" die Unterscheidung zwischen den verschiedenen Arten.
In einem Fall wie dem Ihren, man könnte eine Aufzählung, die Karten zu Ihrem action-codes, fügen Sie dann ein Attribut zu jedem nummerierten Wert, das Sie verwenden, Generika oder Typ-Gebäude zu bauen, die verschiedenen sub-class-Objekte, so dass die überlastung Methode funktioniert.
Aber das ist eine echte Schmerzen.
Bewerten, ob es eine design-option, wie die Aufzählung, die möglich ist und Ihre Lösung. Wenn nicht, verwenden Sie einfach den Schalter.
Können Sie bitte erläutern Sie diese Aussage mit einem Beispiel :"bringen Sie dann ein Attribut zu jedem nummerierten Wert, das Sie verwenden, Generika oder Typ-Gebäude zu bauen, die verschiedenen sub-class-Objekte, so dass die überlastung Methode funktioniert."?
Ja, ich hatte wohl nur eine
PlayerAction
enum mit einempublic static PlayerAction forActionId(int actionId)
- und enum-würde eine öffentlichedoAction
Typ Methode. Keine Notwendigkeit für einen Schalter, nurPlayerAction.forActionId(number).doAction(args);
. Alles was Sie jetzt zu tun haben, einen weiteren hinzufügen Aktion fügen Sie einen enum-Wert und Umsetzung derdoAction
- Methode auf. HINWEIS: ich weiß nicht, wie mit der "Ordnungszahl" entweder, da es einfach zu re-bestellen Sie Ihre enum-Werte alphabetisch sortiert und alles zerstören, was mit den alten zahlen.InformationsquelleAutor Toby
'Schlecht' switch-Anweisungen sind oft diejenigen Umschaltung auf den Objekttyp (oder etwas, das könnte ein Objekttyp in einem anderen design). In anderen Worten hardcoding etwas, das besser sein könnte, behandelt durch Polymorphismus. Andere Arten von switch-Anweisungen könnte gut sein, OK
Benötigen Sie eine switch-Anweisung, aber nur einen. Wenn Sie die Meldung erhalten, rufen Sie ein Factory-Objekt, um ein Objekt zurückgeben, das die entsprechende Message-Unterklasse (Bewegen, Angreifen etc), rufen Sie dann eine Nachricht,->doit () - Methode auf, um die Arbeit zu tun.
Das heißt, wenn Sie mehr hinzufügen, message-Typen, nur das factory-Objekt zu ändern.
Map<Class<?>, Thing>
dies ist sehr ähnlich zu "tun ein Schalter auf "Klassen", diese jedoch genommen, als ein okay der Praxis?InformationsquelleAutor The Archetypal Paul
Den
Strategie
Muster in den Sinn kommt.In diesem Fall die "Familie von algorithmen" sind Ihre verschiedenen Aktionen.
Als für switch-Anweisungen - in "Clean Code" von Robert Martin sagt, dass er versucht, beschränken sich eine switch-Anweisung pro Typ. Nicht beseitigen insgesamt.
Der Grund ist, dass switch-Anweisungen nicht einhalten OCP.
InformationsquelleAutor Oded
Vom design patterns Perspektive kann man mit dem Befehl Muster für das angegebene Szenario. (Siehe http://en.wikipedia.org/wiki/Command_pattern).
Wenn Sie finden, sich selbst immer wieder mit switch-Anweisungen in das OOP-Paradigma ist dies ein Hinweis darauf, dass Ihre Klassen vielleicht nicht gut design. Angenommen, Sie haben ein richtiges design von super-und Subklassen und einen fairen Betrag von Polymorphismus. Die Logik hinter switch-Anweisungen behandelt werden sollten, die von den sub-Klassen.
Weitere Informationen darüber, wie Sie entfernt werden, diese switch-Anweisungen und führen in die richtige sub-Klassen, empfehle ich Ihnen die Lektüre der ersten Kapitel des Refactoring von Martin Fowler. Oder finden Sie ähnliche Folien hier http://www1.informatik.uni-wuerzburg.de/database/courses/pi2_ss03_dir/RefactoringExampleSlides.pdf. (Folie 44)
InformationsquelleAutor TechTravelThink
IMO
switch
Aussagen sind nicht bad, sollte aber vermieden werden, wenn möglich. Eine Lösung wäre die Verwendung einerMap
wo die Tasten sind die Befehle, und die WerteCommand
Objekte mit einemexecute()
Methode. Oder einList
wenn Ihre Befehle sind numerisch und haben keine Lücken.Jedoch in der Regel, verwenden Sie
switch
Aussagen, wenn design-Pattern implementiert; ein Beispiel wäre die Verwendung einer Kette der Verantwortung - Muster zu handhaben, die Befehle jeder Befehl "id" oder "Wert". (Die Strategie Muster war auch aufgeführte.) Aber in deinem Fall hast du vielleicht auch einen Blick in die Befehl Muster.Grundsätzlich in OOP, werden Sie versuchen, andere Lösungen, als sich auf
switch
Blöcke, die mit einem prozeduralen Programmierparadigma. Jedoch, Wann und wie zu verwenden, entweder etwas ist Ihre Entscheidung. Ich persönlich benutze oftswitch
Blöcke bei Verwendung der Fabrik Muster etc.Definition von code-organisation :
Collection
- API in vielen frameworks)Math
Klasse...add
Methode wird verlassen sich auf andere Methoden zu tun, der sich nicht erfüllen wird, die operation selbst, weil es nicht, es ist Vertrag.)Deshalb, wenn Sie Ihre
switch
- Anweisung ausführen unterschiedlicher Arten von Operationen, Sie sind "gegen" , definition; in der Erwägung, dass die Verwendung eines design-Muster nicht wie jede operation definiert ist, in seiner eigenen Klasse (eigene Funktionen).InformationsquelleAutor Yanick Rochon
Ich würde mal sagen, die Nachrichten in ein array und dann entsprechen die Artikel zu der Lösung der Schlüssel, um die Nachricht anzuzeigen.
InformationsquelleAutor Michael Swierzbinski II
Befehle verwenden. Wickeln Sie die Aktion in ein Objekt und lassen Polymorphismus tun, der Schalter für Sie. In C++ (
shared_ptr
ist einfach ein Zeiger oder eine Referenz in Java-Bezug. Es ermöglicht eine dynamic dispatch):Kunden wählen eine Aktion aus, und sobald Sie tun, Sie senden, dass die Aktion selbst auf den server, damit der server muss nicht jedem Parsen:
InformationsquelleAutor wilhelmtell
Kaufe ich nicht. Diese OOP-Berserker zu haben scheinen Maschinen, die haben unendlich viel RAM und eine beeindruckende Leistung. Offensichtlich mit inifinite RAM brauchen Sie sich keine Gedanken über RAM-Fragmentierung und die Auswirkungen auf die Leistung, wenn Sie ständig auf der erstellen und zu zerstören kleine Helfer-Klassen. In Anlehnung an ein Zitat für die "Schönen Code" Buch - "Jedes problem in der informatik gelöst werden kann mit einer anderen Ebene der Abstraktion"
Einen switch verwenden, wenn Sie es brauchen. Compiler sind ziemlich gut bei der Generierung von code für Sie.
InformationsquelleAutor James