Als ich kürzlich in einer großen Firma arbeitete, bemerkte ich, dass die Programmierer dort diesem Codierungsstil folgten:
Angenommen, ich habe eine Funktion, die 12 zurückgibt, wenn der Eingang A ist, 21, wenn der Eingang B ist, und 45, wenn der Eingang C ist.
So kann ich die Funktionssignatur schreiben als:
int foo(String s){
if(s.equals("A")) return 12;
else if(s.equals("B")) return 21;
else if(s.equals("C")) return 45;
else throw new RuntimeException("Invalid input to function foo");
}
Bei der Codeüberprüfung wurde ich jedoch gebeten, die Funktion wie folgt zu ändern:
int foo(String s){
HashMap<String, Integer> map = new HashMap<String, Integer>();
map.put("A", 12);
map.put("B", 21);
map.put("C", 45);
return map.get(s);
}
Ich kann mich nicht davon überzeugen, warum der zweite Code besser ist als der erste. Die Ausführung des zweiten Codes würde definitiv mehr Zeit in Anspruch nehmen.
Der einzige Grund für die Verwendung des zweiten Codes kann sein, dass er eine bessere Lesbarkeit bietet. Wenn die Funktion jedoch mehrmals aufgerufen wird, verlangsamt die zweite Funktion dann nicht die Laufzeit des Dienstprogramms, das sie aufruft?
Was denkst du darüber?
quelle
switch
scheint angemessener zu sein alsif-else
). Aber irgendwann wird es problematisch. Der Hauptvorteil der Verwendung einer Karte besteht darin, dass Sie sie aus einer Datei, einer Tabelle usw. laden können. Wenn Sie die Eingabe in die Karte fest codieren, wird über einen Switch nicht viel Wert angezeigt.Antworten:
Der Punkt ist, die Erstellung der Hashmap außerhalb der Funktion zu verschieben und einmal (oder nur seltener als sonst) auszuführen.
Allerdings konnte Java7 seitdem (endgültige) Zeichenfolgen in Switches haben:
quelle
In Ihrem zweiten Beispiel
Map
sollte das ein privates statisches Mitglied sein, um redundanten Initialisierungsaufwand zu vermeiden.Bei großen Wertemengen ist die Leistung der Karte besser. Mit einer Hashtabelle kann man die Antwort in konstanter Zeit nachschlagen. Das Multiple-If-Konstrukt muss die Eingabe mit jeder der Möglichkeiten vergleichen, bis es die richtige Antwort findet.
Mit anderen Worten ist die Kartensuche O (1), während die
if
s O (n) sind, wobei n die Anzahl möglicher Eingaben ist.Die Kartenerstellung ist O (n), wird jedoch nur einmal durchgeführt, wenn es sich um einen statischen konstanten Zustand handelt. Bei einer häufig durchgeführten Suche übertrifft die Map die
if
Anweisungen auf lange Sicht, was etwas mehr Zeit kostet, wenn das Programm gestartet wird (oder die Klasse je nach Sprache geladen wird).Trotzdem ist die Karte nicht immer das richtige Werkzeug für diesen Job. Es ist schön, wenn es viele Werte gibt oder die Werte über eine Textdatei, Benutzereingabe oder Datenbank konfigurierbar sein müssen (in diesem Fall fungiert die Karte als Cache).
quelle
In der Software gibt es zwei Geschwindigkeiten: die Zeit, die zum Schreiben / Lesen / Debuggen des Codes benötigt wird; und die Zeit, die zum Ausführen des Codes benötigt wird.
Wenn Sie mich (und Ihre Code-Prüfer) davon überzeugen können, dass die Hashmap-Funktion tatsächlich langsamer ist als das if / then / else (nach dem Refactoring, um eine statische Hashmap zu erstellen), UND Sie mich / die Prüfer davon überzeugen können, dass sie genügend Male aufgerufen wird, um eine tatsächliche zu erstellen Unterschied, dann fahren Sie fort und ersetzen Sie die Hashmap durch das if / else.
Andernfalls ist der Hashmap-Code hervorragend lesbar. und (wahrscheinlich) fehlerfrei; Sie können dies schnell feststellen, indem Sie es sich ansehen. Man kann nicht wirklich dasselbe über das Wenn / Sonst sagen, ohne es wirklich zu studieren; Der Unterschied ist noch übertrieben, wenn es Hunderte von Optionen gibt.
quelle
Ich bevorzuge die Antwort im HashMap-Stil.
Dafür gibt es eine Metrik
Es gibt eine Codequalitätsmetrik namens Cyclomatic Complexity . Diese Metrik zählt im Wesentlichen die Anzahl der verschiedenen Pfade durch den Code ( wie die zyklomatische Komplexität berechnet wird ).
Für jeden möglichen Ausführungspfad wird es immer schwieriger, eine Methode zu verstehen UND die Richtigkeit vollständig zu testen.
Es läuft darauf hinaus, dass "Keywords steuern" wie: ifs, elses, whiles usw. boolesche Tests nutzen, die falsch sein können. Die wiederholte Verwendung von "Schlüsselwörtern steuern" erzeugt fragilen Code.
Zusätzliche Vorteile
Der "kartenbasierte Ansatz" ermutigt Entwickler außerdem, sich die Eingabe-Ausgabe-Paare als einen Datensatz vorzustellen, der zur Laufzeit extrahiert, wiederverwendet, bearbeitet, getestet und verifiziert werden kann. Zum Beispiel habe ich unten "foo" umgeschrieben, damit wir nicht dauerhaft in "A-> 12, B-> 21, C-> 45" eingeschlossen sind:
rachet_freak erwähnt diese Art von Refactor in seiner Antwort, er plädiert für Geschwindigkeit und Wiederverwendung, ich plädiere für Laufzeitflexibilität (obwohl die Verwendung einer unveränderlichen Sammlung je nach Situation enorme Vorteile haben kann)
quelle
Daten sind besser als Code. Nicht zuletzt, weil es zu verlockend ist, dem Code noch einen weiteren Zweig hinzuzufügen, ist es jedoch schwierig, einer Zeile eine Zeile hinzuzufügen. Diese Frage ist ein kleines Beispiel dafür. Sie schreiben eine Nachschlagetabelle. Schreiben Sie entweder eine Implementierung mit bedingter Logik und Dokumentation oder schreiben Sie die Tabelle aus und suchen Sie danach.
Eine Datentabelle ist immer eine bessere Darstellung einiger Daten als Code, Modulo-Optimierungsdurchläufe. Wie schwierig es ist, die Tabelle auszudrücken, hängt möglicherweise von der Sprache ab - ich kenne Java nicht, würde aber hoffen, dass es eine Nachschlagetabelle einfacher als das Beispiel im OP implementieren kann.
Dies ist eine Nachschlagetabelle in Python. Wenn dies als einladender Konflikt angesehen wird, beachten Sie bitte, dass die Frage nicht mit Java gekennzeichnet ist, das Refactoring sprachunabhängig ist und dass die meisten Menschen Java nicht kennen.
Die Idee, den Code neu zu strukturieren, um die Laufzeit zu verkürzen, hat sich bewährt, aber ich würde viel lieber einen Compiler verwenden, der das allgemeine Setup hochzieht, als dies selbst zu tun.
quelle