Ich habe heute eine Codeüberprüfung von einem leitenden Entwickler erhalten, in der gefragt wurde: "Was halten Sie übrigens davon, Funktionen über eine switch-Anweisung zu verteilen?" Ich habe an vielen Stellen gelesen, wie schlecht es ist, ein Argument durch die Methode zum Umschalten auf einen Aufruf zu pumpen. OOP, nicht so erweiterbar usw. Eine endgültige Antwort kann ich ihm jedoch nicht geben. Ich würde das gerne ein für alle Mal für mich selbst regeln.
Hier sind unsere konkurrierenden Codevorschläge (PHP wird als Beispiel verwendet, kann aber universeller angewendet werden):
class Switch {
public function go($arg) {
switch ($arg) {
case "one":
echo "one\n";
break;
case "two":
echo "two\n";
break;
case "three":
echo "three\n";
break;
default:
throw new Exception("Unknown call: $arg");
break;
}
}
}
class Oop {
public function go_one() {
echo "one\n";
}
public function go_two() {
echo "two\n";
}
public function go_three() {
echo "three\n";
}
public function __call($_, $__) {
throw new Exception("Unknown call $_ with arguments: " . print_r($__, true));
}
}
Ein Teil seines Arguments lautete: "Es (Switch-Methode) behandelt Standardfälle viel sauberer als die generische Methode __call () magic."
Ich bin nicht einverstanden mit der Sauberkeit und bevorzuge in der Tat einen Anruf, aber ich würde gerne hören, was andere zu sagen haben.
Argumente, die ich zur Unterstützung des Oop
Schemas vorbringen kann:
- Etwas sauberer in Bezug auf den Code, den Sie schreiben müssen (weniger, leichter zu lesen, weniger zu berücksichtigende Schlüsselwörter)
- Nicht alle Aktionen wurden an eine einzelne Methode delegiert. Hier gibt es keinen großen Unterschied in der Ausführung, aber zumindest ist der Text mehr unterteilt.
- Auf die gleiche Weise kann an einer beliebigen Stelle in der Klasse eine andere Methode anstelle einer bestimmten Stelle hinzugefügt werden.
- Methoden haben einen Namensraum, was sehr gut ist.
- Gilt hier nicht, aber es wird ein Fall betrachtet, in dem
Switch::go()
ein Element und kein Parameter bearbeitet wird. Sie müssten zuerst das Mitglied ändern und dann die Methode aufrufen. DennOop
Sie können die Methoden jederzeit eigenständig aufrufen.
Argumente, die ich zur Unterstützung des Switch
Schemas vorbringen kann:
- Der Einfachheit halber eine sauberere Methode für die Behandlung einer (unbekannten) Standardanforderung
- Scheint weniger magisch, was dazu führen könnte, dass sich unbekannte Entwickler wohler fühlen
Hat jemand für beide Seiten etwas hinzuzufügen? Ich hätte gerne eine gute Antwort für ihn.
quelle
Oop
erlaubt phpdoc zur Beschreibung jeder Methode, die von einigen IDEs (zB NetBeans) analysiert werden kann.Antworten:
Ein Schalter wird nicht als OOP betrachtet, da häufig Polymorphismus den Trick bewirken kann.
In Ihrem Fall könnte eine OOP-Implementierung folgendermaßen aussehen:
quelle
für dieses Beispiel:
OK, hier nur teilweise ein Scherz. Das Argument für / gegen die Verwendung einer switch-Anweisung kann mit einem solchen trivialen Beispiel nicht eindeutig formuliert werden , da die OOP-Seite von der Semantik abhängt, nicht nur vom Versandmechanismus .
Switch-Anweisungen sind oft ein Hinweis auf fehlende Klassen oder Klassifizierungen, aber nicht unbedingt. Manchmal ist eine switch-Anweisung nur eine switch-Anweisung .
quelle
Vielleicht keine Antwort, aber im Falle des Nicht-Switch-Codes scheint dies eine bessere Übereinstimmung zu sein:
Ein großer Teil des zu bewertenden Puzzles ist, was passiert, wenn Sie
NewSwitch
oder erstellen müssenNewOop
. Müssen Ihre Programmierer nach der einen oder anderen Methode durch die Rahmen springen? Was passiert, wenn sich Ihre Regeln usw. ändern?quelle
is_callable
, aber call_user_func verlassen, da (nicht Teil dieser Frage) möglicherweise andere Argumente weitergegeben werden müssen. Aber jetzt, da dies auf Programmierer übergegangen ist, stimme ich definitiv zu, dass die Antwort von @ Andrea viel besser ist :)Anstatt nur den ausgeführten Code in Funktionen zu integrieren, implementieren Sie ein vollständiges Befehlsmuster und ordnen Sie sie jeweils einer eigenen Klasse zu, die eine gemeinsame Schnittstelle implementiert. Mit dieser Methode können Sie mithilfe von IOC / DI die verschiedenen "Fälle" Ihrer Klasse verkabeln und im Laufe der Zeit problemlos Fälle zu Ihrem Code hinzufügen und daraus entfernen. Es gibt Ihnen auch ein gutes Stück Code, das nicht gegen SOLID-Programmierprinzipien verstößt.
quelle
Ich finde das Beispiel schlecht. Wenn es eine go () - Funktion gibt, die das Argument $ where akzeptiert, ist es vollkommen gültig, switch in der Funktion zu verwenden. Die Funktion single go () erleichtert das Ändern des Verhaltens aller Szenarien in go_where (). Darüber hinaus wird die Klassenschnittstelle beibehalten. Wenn Sie verschiedene Methoden verwenden, ändern Sie die Schnittstelle der Klasse mit jedem neuen Ziel.
Eigentlich sollte switch nicht durch eine Reihe von Methoden ersetzt werden, sondern durch eine Reihe von Klassen - das ist Polymorphismus. Dann wird das Ziel von jeder Unterklasse behandelt, und es gibt für alle eine einzelne go () -Methode. Bedingt durch Polymorphismus zu ersetzen , ist eine der grundlegenden Umgestaltungen, die von Martin Fowler beschrieben wurden. Aber Sie brauchen möglicherweise keinen Polymorphismus, und der Wechsel ist der richtige Weg.
quelle
go()
, kann dies leicht gegen das Liskov-Substitutionsprinzip verstoßen. Wenn Sie mehr Funktionalität hinzugefügtgo()
, Sie tun mögen die Schnittstelle so weit ändern , wie ich bin concerend.