Wenn ich mich mit komplizierten Algorithmen in Sprachen beschäftige, die verschachtelte Funktionen (wie Python und D) unterstützen, schreibe ich oft riesige Funktionen (weil der Algorithmus kompliziert ist), aber mildere dies, indem ich verschachtelte Funktionen verwende, um den komplizierten Code zu strukturieren. Werden riesige Funktionen (über 100 Zeilen) immer noch als böse angesehen, selbst wenn sie intern durch die Verwendung verschachtelter Funktionen gut strukturiert sind?
Bearbeiten: Für diejenigen unter Ihnen, die nicht mit Python oder D vertraut sind, ermöglichen verschachtelte Funktionen in diesen Sprachen auch den Zugriff auf den äußeren Funktionsumfang. In D ermöglicht dieser Zugriff die Mutation von Variablen im äußeren Bereich. In Python ist nur Lesen möglich. In D können Sie den Zugriff auf den äußeren Bereich in einer verschachtelten Funktion explizit deaktivieren, indem Sie diese deklarieren static
.
Antworten:
Denken Sie immer an die Regel, eine Funktion macht eines und macht es gut! Vermeiden Sie in diesem Fall verschachtelte Funktionen.
Es behindert die Lesbarkeit und das Testen.
quelle
Einige haben argumentiert, dass kurze Funktionen fehleranfälliger sein können als lange Funktionen .
Persönlich habe ich festgestellt, dass gut kommentierter direkter Code leichter zu befolgen ist (insbesondere, wenn Sie nicht derjenige waren, der ihn ursprünglich geschrieben hat), als wenn er in mehrere Funktionen unterteilt ist, die an keiner anderen Stelle verwendet werden. Aber es kommt wirklich auf die Situation an.
Ich denke, das Hauptproblem ist, dass Sie, wenn Sie einen Codeblock aufteilen, eine Art von Komplexität gegen eine andere austauschen. Es gibt wahrscheinlich irgendwo in der Mitte einen Sweet Spot.
quelle
Idealerweise sollte die gesamte Funktion ohne Scrollen sichtbar sein. Manchmal ist das nicht möglich. Wenn Sie es jedoch in Teile zerlegen können, wird das Lesen des Codes erheblich erleichtert.
Ich weiß, dass ich mich nur an 7 +/- 2 Dinge von der vorherigen Seite erinnern kann, sobald ich Page Up / Down drücke oder zu einem anderen Abschnitt des Codes gehe. Und leider werden einige dieser Speicherorte beim Lesen des neuen Codes verwendet.
Ich denke immer gerne an mein Kurzzeitgedächtnis wie an die Register eines Computers (CISC, nicht RISC). Wenn Sie die gesamte Funktion auf derselben Seite haben, können Sie in den Cache wechseln, um die erforderlichen Informationen aus einem anderen Programmabschnitt abzurufen. Wenn die gesamte Funktion nicht auf eine Seite passt, entspricht dies dem Übertragen von Speicher nach jedem Vorgang auf die Festplatte.
quelle
Warum verschachtelte Funktionen anstelle normaler externer Funktionen verwenden?
Selbst wenn die externen Funktionen immer nur in Ihrer einzigen, ehemals großen Funktion verwendet werden, ist das Ganze dennoch besser lesbar:
quelle
Ich habe das Buch momentan nicht vor mir (um es zu zitieren), aber laut Code Complete betrug der "Sweetspot" für die Funktionslänge laut seiner Recherche etwa 25-50 Codezeilen.
Es gibt Zeiten, in denen es in Ordnung ist, lange Funktionen zu haben:
Die Zeiten, in denen es nicht in Ordnung ist, lange Funktionen zu haben:
Unter dem Strich sollte die Wartbarkeit eine der höchsten Prioritäten auf Ihrer Liste sein. Wenn ein anderer Entwickler Ihren Code nicht in weniger als 5 Sekunden einsehen kann, um einen Überblick über die Funktionsweise des Codes zu erhalten, bietet Ihr Code nicht genügend "Metadaten", um die Funktionsweise des Codes zu beschreiben. Andere Entwickler sollten in der Lage sein, zu erkennen, was Ihre Klasse tut, indem sie sich den Objektbrowser in der von Ihnen ausgewählten IDE ansehen, anstatt mehr als 100 Codezeilen zu lesen.
Kleinere Funktionen haben folgende Vorteile:
Die Liste geht weiter.....
quelle
Die Antwort ist, es kommt darauf an, aber Sie sollten das wahrscheinlich in eine Klasse verwandeln.
quelle
Ich mag die meisten verschachtelten Funktionen nicht. Lambdas fallen in diese Kategorie, kennzeichnen mich aber normalerweise nur, wenn sie mehr als 30-40 Zeichen haben.
Der Grund dafür ist, dass es sich um eine lokal sehr dichte Funktion mit interner semantischer Rekursion handelt, was bedeutet, dass es für mich schwierig ist, mein Gehirn in den Griff zu bekommen, und dass es einfacher ist, ein paar Dinge in eine Hilfsfunktion zu verschieben, die den Code-Raum nicht überfrachtet .
Ich denke, dass eine Funktion ihre Sache tun sollte. Andere Dinge tun, ist das, was andere Funktionen tun. Wenn Sie also eine 200-Zeilen-Funktion haben, die das Richtige tut und alles fließt, ist das A-OK.
quelle
Ist das akzeptabel? Das ist wirklich eine Frage, die nur Sie beantworten können. Erreicht die Funktion das, was sie benötigt? Ist es wartbar? Ist es für die anderen Mitglieder Ihres Teams "akzeptabel"? Wenn ja, dann ist das wirklich wichtig.
Edit: Ich habe die Sache mit den verschachtelten Funktionen nicht gesehen. Persönlich würde ich sie nicht benutzen. Ich würde stattdessen reguläre Funktionen verwenden.
quelle
Eine lange "Gerade" -Funktion kann eine eindeutige Methode sein, um eine lange Folge von Schritten anzugeben, die immer in einer bestimmten Folge auftreten.
Wie andere erwähnt haben, ist diese Form jedoch anfällig für lokale Komplexitätsabschnitte, in denen der Gesamtfluss weniger offensichtlich ist. Wenn Sie diese lokale Komplexität in eine verschachtelte Funktion einfügen (dh an einer anderen Stelle in der langen Funktion, möglicherweise oben oder unten), kann der Hauptlinienfluss wieder klarer dargestellt werden.
Ein zweiter wichtiger Gesichtspunkt ist die Steuerung des Bereichs von Variablen, die nur in einem lokalen Abschnitt einer langen Funktion verwendet werden sollen. Wachsamkeit ist erforderlich, um zu vermeiden, dass eine Variable, die in einen Codeabschnitt eingefügt wurde, unabsichtlich an einer anderen Stelle referenziert wird (z. B. nach Bearbeitungszyklen), da diese Art von Fehler nicht als Kompilierungs- oder Laufzeitfehler angezeigt wird.
In einigen Sprachen kann dieses Problem leicht abgewendet werden: Ein lokaler Codeabschnitt kann in einen eigenen Block eingeschlossen werden, z. B. mit "{...}", in dem neu eingeführte Variablen nur für diesen Block sichtbar sind. Einige Sprachen wie Python verfügen nicht über diese Funktion. In diesem Fall können lokale Funktionen hilfreich sein, um Bereiche mit kleinerem Gültigkeitsbereich zu erzwingen.
quelle
Nein, mehrseitige Funktionen sind nicht wünschenswert und sollten keine Codeüberprüfung bestehen. Ich habe auch lange Funktionen geschrieben, aber nachdem ich Martin Fowlers Refactoring gelesen hatte , hörte ich auf. Lange Funktionen sind schwer zu schreiben, schwer zu verstehen und schwer zu testen. Ich habe noch nie eine Funktion mit 50 Zeilen gesehen, die nicht einfacher zu verstehen und zu testen wäre, wenn sie in eine Reihe kleinerer Funktionen aufgeteilt wäre. Bei einer mehrseitigen Funktion sollten mit ziemlicher Sicherheit ganze Klassen herausgerechnet werden. Es ist schwer, genauer zu sein. Vielleicht solltest du eine deiner langen Funktionen bei Code Review posten und jemand (vielleicht ich) kann dir zeigen, wie man sie verbessert.
quelle
Wenn ich in Python programmiere, mache ich gerne einen Schritt zurück, nachdem ich eine Funktion geschrieben habe, und frage mich, ob sie dem "Zen of Python" entspricht (geben Sie "import this" in Ihren Python-Interpreter ein):
Schön ist besser als hässlich.
Explizit ist besser als implizit.
Einfach ist besser als komplex.
Komplex ist besser als kompliziert.
Flach ist besser als verschachtelt.
Spärlich ist besser als dicht.
Lesbarkeit zählt.
Sonderfälle sind nicht speziell genug, um die Regeln zu brechen.
Obwohl Zweckmäßigkeit die Reinheit übertrifft.
Fehler sollten niemals unbemerkt passieren.
Sofern nicht ausdrücklich zum Schweigen gebracht.
Lehnen Sie bei Zweideutigkeiten die Versuchung ab, zu raten.
Es sollte einen - und am besten nur einen - offensichtlichen Weg geben, dies zu tun.
Obwohl dieser Weg auf den ersten Blick nicht offensichtlich ist, es sei denn, Sie sind Holländer.
Jetzt ist besser als nie.
Obwohl nie oft besser als richtig istjetzt.
Wenn die Implementierung schwer zu erklären ist, ist es eine schlechte Idee.
Wenn die Implementierung einfach zu erklären ist, ist dies möglicherweise eine gute Idee.
Namespaces sind eine großartige Idee - machen wir mehr davon!
quelle
Legen Sie sie in ein separates Modul.
Angenommen, Ihre Lösung ist nicht aufgeblähter als die Notwendigkeit, dass Sie nicht zu viele Optionen haben. Sie haben die Funktionen bereits in verschiedene Unterfunktionen aufgeteilt, daher lautet die Frage, wo Sie sie platzieren sollten:
Jetzt ist sowohl die zweite als auch die dritte Alternative in gewisser Weise eine Verschachtelung, aber die zweite Alternative scheint für einige Programmierer nicht schlecht zu sein. Wenn Sie die zweite Alternative nicht ausschließen, sehe ich keinen Grund, die dritte auszuschließen.
quelle