Programmierung ohne if-Anweisungen?
Ich erinnere mich an einige Zeit (Jahre, wahrscheinlich) Wochen Las ich auf Stackoverflow über die Reize der Programmierung mit möglichst wenigen, wenn tests wie möglich. Diese Frage ist etwas relevant, aber ich denke der stress war auf durch viele kleine Funktionen, die zurückgegebenen Werte durch tests bestimmt, in Abhängigkeit der parameter, die Sie erhalten. Ein sehr einfaches Beispiel wäre mit dieser:
int i = 5;
bool iIsSmall = isSmall(i);
mit isSmall()
so Aussehen:
private bool isSmall(int number)
{
return (i < 10);
}
statt nur das zu tun diese:
int i = 5;
bool isSmall;
if (i < 10) {
isSmall = true;
} else {
isSmall = false;
}
(Logisch dieser code ist nur Beispiel-code. Es ist nicht Teil von einem Programm, das ich mache.)
Der Grund dafür, glaube ich, war, weil es sieht schöner aus und macht ein Programmierer weniger anfällig für logische Fehler. Wenn diese Codierung Konvention ist, richtig angewendet, würden Sie sehen, praktisch keine if-tests, die überall, außer bei Funktionen, deren einziger Zweck es ist, das zu tun, test.
Nun, meine Frage ist: gibt es eine Dokumentation zu dieser Tagung? Gibt es überall, wo Sie sehen wilde Auseinandersetzungen zwischen Anhänger und Gegner von diesem Stil? Ich habe versucht, die Suche für die Stackoverflow-post, die von mir eingeführt, an diese, aber ich kann Sie nicht mehr finden.
Schließlich, ich hoffe, diese Frage nicht abgeschossen, weil ich mich nicht Fragen, für eine Lösung zu einem problem. Ich bin einfach der Hoffnung zu hören, mehr über diese Codierung Stil und vielleicht erhöhen Sie die Qualität der Codierung werde ich in der Zukunft tun.
- Dieser könnte ein guter Ort, um zu starten. Ich habe das von diese Frage.
- Siehe can-you-write-any-algorithm-without-an-if-statement
- Programmierung ohne if-Anweisungen? Sicher ist: while(Bedingung){/*stuff*/break;}
Du musst angemeldet sein, um einen Kommentar abzugeben.
Diese ganzen "wenn" vs "Nein, wenn" Sache, die macht mich denken, die Ausdruck Problem1. Im Grunde, es ist eine Beobachtung, dass die Programmierung mit if-Anweisungen oder ohne if-Anweisungen ist eine Frage der Kapselung und Erweiterbarkeit, und dass manchmal es besser, verwenden Sie if-Anweisungen2 und manchmal ist es besser, verwenden Sie die dynamische Disposition mit Methoden - /Funktions-Zeiger.
Wenn wir wollen, zu Modell etwas, es gibt zwei Achsen zu kümmern:
Einer Weise zu implementieren, die diese Art der Sache ist mit if-Anweisungen /pattern-matching /das Besucher-Muster:
Die andere Möglichkeit ist die Verwendung von Objekt-Orientierung:
Seine nicht schwer zu sehen, dass die erste version mit if-Anweisungen erleichtert das hinzufügen neuer Operationen auf den Daten-Typ: erstellen Sie einfach eine neue Funktion und eine Fall-Analyse drin. Auf der anderen Seite, das macht es schwierig, fügen Sie neue Fälle auf unsere Daten geben denn das würde bedeuten, die wieder durch das Programm und ändern Sie alle programmzweige.
Die zweite version ist irgendwie das Gegenteil. Es ist sehr einfach zu fügen Sie neue Fälle, die für den Datentyp: erstellen Sie einfach eine neue "Klasse" und sagen, was zu tun für jede der Methoden, die wir implementieren müssen. Allerdings ist das jetzt schwer zu hinzufügen neuer Operationen der Schnittstelle, da dies bedeutet das hinzufügen einer neuen Methode für alle alten Klassen, die implementiert das interface.
Gibt es viele verschiedene Ansätze, die Sprachen benutzen, um zu versuchen zu lösen die Expression Problem und es einfach zu machen, sowohl neue Fälle und neue Vorgänge zu einem Modell. Es gibt jedoch vor-und Nachteile dieser Lösungen3 also im Allgemeinen denke ich, es ist eine gute Faustregel, um zu wählen zwischen OO und wenn Aussagen, je nachdem, welche Achse Sie wollen, um es einfacher zu erweitern Zeug.
Sowieso, gehen zurück zu Ihrer Frage gibt es paar o Dinge möchte ich hinweisen:
Die erste ist, dass ich denke, dass die OO "mantra" loszuwerden alle if-Anweisungen und ersetzen Sie Sie mit Methode Versand hat mehr damit zu tun, wie die meisten OO-Sprachen nicht typesafe Algebraische Datentypen, es hat zu tun mit "wenn statemsnts" schlecht für die Kapselung. Da der einzige Weg, um Typ-sicher ist, verwenden Sie Methode Aufrufe, die Sie ermutigt zu konvertieren Programme mit if-Anweisungen in Programmen mit der Besucher-Muster4 oder noch schlimmer: konvertieren Programme, die sollten mit den visitor-pattern in Programme mit einfachen Methode dispatch, wodurch die Erweiterbarkeit einfach in die falsche Richtung.
Die zweite Sache ist, dass ich nicht bin ein großer fan von Bremsen, die Dinge in die Funktionen, einfach, weil Sie können. Insbesondere finde ich, dass der Stil, wo alle Funktionen haben nur 5 Linien, und rufen Sie Tonnen von anderen Funktionen, ist ziemlich schwer zu Lesen.
Endlich, ich finde dein Beispiel nicht wirklich loswerden von if-Anweisungen. Im wesentlichen, was Sie tun, ist eine Funktion von Ganzzahlen, um einen neuen Datentyp (mit zwei Fällen, eine für Große und eine für Kleine) und Sie dann noch brauchen, um zu verwenden, wenn Aussagen, die bei der Arbeit mit dem Datentyp:
Gehen wir zurück zu dem Ausdruck problem Sicht, den Vorteil zu definieren, unsere toSize /isSmall Funktion ist, dass wir die Logik der Auswahl, was Fall unsere Nummer passt in einer einzigen Ort, und dass unsere Funktionen können nur auf den Fall, dass nach. Jedoch, dies bedeutet nicht, dass wir entfernt haben, wenn die Aussagen unseres code! Wenn wir die toSize wird eine factory-Funktion, und wir haben Große und Kleine werden Klassen teilen eine Schnittstelle, dann ja, wir werden entfernt haben, wenn die Aussagen von unserem code. Jedoch, wenn aus isSmall gerade gibt einen booleschen Wert zurück oder enum-dann gibt es nur so viele if-Anweisungen, als es vorher waren. (und Sie sollten entscheiden, welche Implementierung zu verwenden, je nachdem, ob Sie möchten, um es einfacher, um neue Methoden oder neue Fälle - sagen wir Mittel - in die Zukunft)
1 - Der name des Problems kommt aus dem problem, wo Sie haben eine "expression" Datentyp (zahlen, Variablen, addition/Multiplikation der Teilausdrücke, etc) und implementieren wollen, die Dinge wie die Bewertung von Funktionen und anderen Dingen.
2 - Oder pattern-matching über Algebraische Datentypen, wenn Sie mehr sein wollen geben sicher...
3 - Sie könnten Zum Beispiel festlegen, müssen alle multimethods auf der "obersten Ebene", wo der "dispatcher" sehen kann. Dies ist eine Einschränkung gegenüber dem Allgemeinen Fall, da die Sie verwenden können, wenn Aussagen (und lambdas) tief verschachtelt innerhalb anderer code.
4 - im Wesentlichen ein "Kirche-Codierung" von einem algebraischen Datentyp
Ist es wirklich eine convention? Sollte man tötet nur minimal, wenn-Konstrukte, nur weil es sein könnte frustration über es?
Ok, wenn Aussagen neigen dazu, zu wachsen außer Kontrolle, vor allem, wenn viele Spezial-Fälle wurden im Laufe der Zeit Hinzugefügt. Zweig nach Zweig Hinzugefügt wird und am Ende niemand in der Lage ist, zu begreifen, was alles funktioniert, ohne stundenlang Zeit und einige Tassen Kaffee in dieser grwon Instanz von spaghetti-code.
Aber ist es wirklich eine gute Idee, um alles in seperate Funktionen? Code sollte wiederverwendbar sein. code sollte lesbar sein. Aber eine Funktion aufrufen, nur schafft die Notwendigkeit, schauen Sie weiter oben in der source-Datei. Wenn alle ifs sind weggeräumt, auf diese Weise, Sie einfach zu überspringen um in der Quell-Datei die ganze Zeit. Sieht diese Unterstützung der Lesbarkeit?
Oder betrachten wir eine if-Anweisung, die nicht wiederverwendet werden, überall. Sollte es wirklich gehen, in eine separate Funktion, nur für die Zwecke der Konvention? es ist etwas Aufwand, auch hier. Performance-Probleme können in diesem Zusammenhang relevant sein, auch.
Was ich bin versucht zu sagen: nach coding-Konventionen ist gut. Stil ist wichtig. Aber es gibt Ausnahmen. Versuchen Sie einfach, guten code zu schreiben, der passt in Ihr Projekt und behalten Sie die Zukunft im Blick. Am Ende, coding conventions sind nur Richtlinien, die versuchen, uns zu helfen, produziert guten code ohne die Durchsetzung nichts bei uns.
Ich habe noch nie gehört, so ein Konvektion. Ich weiß nicht, wie es funktioniert, sowieso. Sicherlich der einzige Punkt, der mit einem
iIsSmall
ist, um später die Filiale auf der es (eventuell in Kombination mit anderen Werten)?Was ich haben gehört, ist ein argument, um zu vermeiden, dass Variablen wie
iIsSmall
an alle.iIsSmall
nur speichern das Ergebnis eines Tests, die Sie gemacht, so dass Sie später verwenden die Ergebnisse, um einige Entscheidung. Also warum nicht einfach testen, den Wert voni
an dem Punkt, wo Sie brauchen, um die Entscheidung zu treffen? also, statt:nur schreiben:
Diese Weise können Sie sagen, an der Verzweigung, was Sie tatsächlich Verzweigung auf, weil es genau dort. Das ist nicht schwer, in diesem Beispiel sowieso, aber wenn der test war kompliziert, du bist wahrscheinlich nicht in der Lage sein zu codieren, das ganze in die variable name.
Es ist auch sicherer. Es besteht keine Gefahr, dass der name
iIsSmall
ist irreführend, weil Sie verändert den code, so dass es wurde getestet, etwas anderes, oder weili
wurde tatsächlich verändert, nachdem Sie genanntisSmall
so, dass es nicht unbedingt kleine nicht mehr, oder weil jemand nahm nur eine dumme variable name, etc, etc.Offensichtlich funktioniert das nicht immer. Wenn die
isSmall
test ist teuer, und Sie müssen auf den Zweig, auf dessen Ergebnis viele Male, die Sie nicht ausführen möchten, Sie viele Male. Sie auch nicht wollen könnte, um den code duplizieren, dass viele Male rufen, es sei denn, es ist trivial. Oder möchten Sie vielleicht, um die Rückkehr der Flagge verwendet werden, die von einem Anrufer, der nicht weiß, überi
(obwohl dann könnten Sie einfach zurückisSmall(i)
, anstatt in einer Variablen gespeichert und dann wieder die variable).Btw, die separate Funktion speichert nichts in deinem Beispiel. Sie können
(i < 10)
in Zuordnung zu einembool
variable genauso einfach wie in einer return-Anweisung in einerbool
Funktion. d.h. Sie könnten genauso gut schreibenbool isSmall = i < 10;
- es ist diese, die verhindert, dass der if-Anweisung, nicht die separate Funktion. Code der formif (test) { x = true; } else { x = false; }
oderif (test) { return true; } else { return false; }
ist immer dumm, benutzen Sie einfachx = test
oderreturn test
.