it-swarm.com.de

Sollte ich Funktionen, die nur in einer anderen Funktion verwendet werden, innerhalb dieser Funktion platzieren?

Insbesondere schreibe ich in JavaScript.

Angenommen, meine Hauptfunktion ist Funktion A. Wenn Funktion A Funktion B mehrmals aufruft, Funktion B jedoch nirgendwo anders verwendet wird, sollte ich dann einfach Funktion B in Funktion A einfügen?

Ist das eine gute Praxis? Oder sollte ich Funktion B trotzdem in den gleichen Bereich wie Funktion A stellen?

34
Gary

Ich bin generell für verschachtelte Funktionen, insbesondere in JavaScript.

  • In JavaScript können Sie die Sichtbarkeit einer Funktion nur einschränken, indem Sie sie in eine andere Funktion verschachteln.
  • Die Hilfsfunktion ist ein privates Implementierungsdetail. Wenn Sie den gleichen Umfang festlegen, bedeutet dies, dass die privaten Funktionen einer Klasse öffentlich gemacht werden.
  • Wenn sich herausstellt, dass es allgemeiner ist, können Sie es leicht entfernen, da Sie sicher sein können, dass der Helfer derzeit nur von dieser einen Funktion verwendet wird. Mit anderen Worten, es macht Ihren Code zusammenhängender.
  • Sie können häufig Parameter entfernen, wodurch die Funktionssignatur und -implementierung weniger ausführlich sind. Dies ist nicht dasselbe wie Variablen global zu machen. Es ist eher so, als würde man ein Klassenmitglied in einer privaten Methode verwenden.
  • Sie können den Hilfsfunktionen bessere und einfachere Namen geben, ohne sich um Konflikte sorgen zu müssen.
  • Die Hilfsfunktion ist leichter zu finden. Ja, es gibt Tools, die Ihnen helfen können. Es ist immer noch einfacher, die Augen ein wenig über den Bildschirm zu bewegen.
  • Code bildet natürlich eine Art Abstraktionsbaum: einige allgemeine Funktionen an der Wurzel, die sich in mehrere Implementierungsdetails verzweigen. Wenn Sie einen Editor mit Funktion zum Falten/Reduzieren von Funktionen verwenden, wird durch Verschachteln eine Hierarchie eng verwandter Funktionen auf derselben Abstraktionsebene erstellt. Das macht es sehr einfach, den Code auf der gewünschten Ebene zu studieren und die Details zu verbergen.

Ich denke, viel Widerstand kommt von der Tatsache, dass die meisten Programmierer entweder in einer C/C++/Java-Tradition aufgewachsen sind oder von jemand anderem unterrichtet wurden, der es war. Verschachtelte Funktionen sehen nicht natürlich aus, da wir ihnen beim Programmieren nicht viel ausgesetzt waren. Das heißt nicht, dass sie nicht nützlich sind.

34
Karl Bielefeldt

Sie sollten es aus mehreren Gründen global anwenden.

  • Durch das Verschachteln einer Hilfsfunktion in den Anrufer wird die Länge des Anrufers erhöht. Die Funktionslänge ist fast immer ein negativer Indikator. kurze Funktionen sind leichter zu verstehen, zu merken, zu debuggen und zu warten.

  • Wenn die Hilfsfunktion einen sinnvollen Namen hat, reicht es aus, diesen Namen zu lesen, ohne die Definition in der Nähe sehen zu müssen. Wenn Sie do die Hilfsdefinition sehen müssen, um die Aufruferfunktion zu verstehen, dann tut dieser Aufrufer zu viel oder arbeitet gleichzeitig an zu vielen Abstraktionsebenen.

  • Wenn der Helfer global verfügbar ist, können andere Funktionen ihn aufrufen, wenn er sich als allgemein nützlich herausstellt. Wenn der Helfer nicht verfügbar ist, sind Sie versucht, ihn auszuschneiden und einzufügen oder ihn zu vergessen und schlecht neu zu implementieren oder eine andere Funktion länger als nötig zu machen.

  • Das Verschachteln der Hilfsfunktion erhöht die Versuchung, Variablen aus dem Bereich des Aufrufers ohne Deklaration zu verwenden, so dass unklar wird, welche Ein- und Ausgänge der Helfer sind. Wenn eine Funktion nicht klar angibt, mit welchen Daten sie arbeitet und welche Auswirkungen sie hat, ist dies normalerweise ein Zeichen für unklare Verantwortlichkeiten. Wenn Sie den Helferarsch als eigenständige Funktion deklarieren, müssen Sie genau wissen, was er tatsächlich tut.

Bearbeiten

Das stellte sich als kontroversere Frage heraus, als ich dachte. Zu klären:

In JavaScript erfüllen große Funktionen zum Überspannen von Dateien häufig die Rolle von Klassen, da die Sprache keinen anderen Mechanismus zur Einschränkung des Gültigkeitsbereichs bietet. Sicherlich sollten Hilfsfunktionen innen solche Quasi-Klassen sein, nicht außerhalb von ihnen.

Und der Punkt über die einfachere Wiederverwendung setzt voraus, dass Sie bereit sind, eine Unterroutine tut, wenn sie häufiger verwendet wird, vollständig zu verschieben und an einer geeigneten Stelle zu platzieren, z. eine String-Dienstprogrammbibliothek oder in Ihre globale Konfigurationsregistrierung. Wenn Sie Ihren Code nicht so bestellen möchten, können Sie das Unterprogramm genauso gut verschachteln, wie Sie es mit einem normalen Methodenobjekt in einer "blockigeren" Sprache tun würden.

14
Kilian Foth

Ich werde einen dritten Weg vorschlagen, um beide Funktionen innerhalb eines Abschlusses zu platzieren. Es würde so aussehen:

var functionA = (function(){
    function functionB() {
        // do stuff...
    }

    function functionA() {
        // do stuff...
        functionB();
        // do stuff...
    }

    return functionA;
})();

Wir erstellen den Abschluss, indem wir die Deklaration beider Funktionen in ein IIFE einschließen. Der Rückgabewert des IIFE ist die öffentliche Funktion, die in einer Variablen des Namens für die Funktion gespeichert ist. Die öffentliche Funktion kann genauso aufgerufen werden, als ob sie als globale Funktion deklariert worden wäre, dh functionA(). Beachten Sie, dass der Rückgabewert die Funktion ist, kein Aufruf der Funktion, also keine Parens am Ende.

Wenn Sie die beiden Funktionen so zusammenfassen, ist functionB jetzt vollständig privat und kann nicht außerhalb des Abschlusses aufgerufen werden, sondern ist nur für functionA sichtbar. Der globale Namespace ist nicht überladen, und überladen nicht die Definition von functionA.

8
cbojar

Durch Definieren von Funktion B innerhalb von Funktion A erhält Funktion B Zugriff auf die internen Variablen von A.

Eine in einer Funktion A definierte Funktion B vermittelt also den Eindruck (oder zumindest die Möglichkeit), dass B die lokalen Variablen von A verwendet oder ändert. Beim Definieren von B außerhalb von A wird deutlich, dass B dies nicht tut.

Aus Gründen der Klarheit des Codes würde ich B innerhalb von A nur definieren, wenn B auf lokale Variablen von A zugreifen muss. Wenn B einen klaren Zweck hat, der von A unabhängig ist, würde ich ihn definitiv außerhalb von A definieren.

0
Florian F