it-swarm-eu.dev

Was ist als gute maximale Länge einer Funktion erwiesen?

Beeinflusst die Funktionslänge die Produktivität eines Programmierers? Wenn ja, wie viele Zeilen können maximal verwendet werden, um Produktivitätsverluste zu vermeiden?

Da dies ein Thema mit hoher Meinung ist, stützen Sie die Behauptung bitte mit einigen Daten.

47
Gaurav

Seit ich 1970 mit diesem verrückten Schläger angefangen habe, habe ich genau ein Modul gesehen, das wirklich benötigt mehr als eine gedruckte Seite (ungefähr 60 Zeilen) ist. Ich habe viele Module gesehen, die länger waren.

Im Übrigen habe ich Module geschrieben, die länger waren, aber normalerweise waren es große Finite-State-Maschinen, die als große switch-Anweisungen geschrieben wurden.

Ein Teil des Problems scheint zu sein, dass Programmierer heutzutage nicht lernen, Dinge zu modularisieren.

Codierungsstandards, die die Verschwendung von vertikalem Raum maximieren, scheinen ebenfalls Teil des Problems zu sein. (Ich habe noch Um einen Software-Manager zu treffen, der Gerald Weinberg 's " Psychologie der Computerprogrammierung " gelesen hat. Weinberg weist darauf hin, dass mehrere Studien gezeigt haben, dass das Verständnis des Programmierers im Wesentlichen auf das beschränkt ist, was der Programmierer zu einem bestimmten Zeitpunkt sehen kann. Wenn der Programmierer scrollen oder eine Seite umblättern muss, sinkt sein Verständnis erheblich: Er muss sich erinnern und abstrakt sein.)

Ich bin weiterhin davon überzeugt, dass viele der gut dokumentierten Produktivitätssteigerungen von Programmierern von HER auf das FORTH "Block" -System für Quellcode zurückzuführen sind: Module waren hart- begrenzt auf ein absolutes Maximum von 16 Zeilen mit 64 Zeichen. Sie könnten unendlich viel faktorisieren, aber Sie könnten unter keinen Umständen schreiben eine 17-zeilige Routine.

47
John R. Strohm

Was ist wirklich die richtige Größe?

Hängt von der Sprache ab, die Sie verwenden, aber im Allgemeinen (und für meinen persönlichen Geschmack):

  • Idealerweise weniger als 25 Zeilen.
  • Akzeptabel , weniger als 35 Zeilen.

Wenn es mehr ist, muss ich später darauf zurückkommen und es überarbeiten.

Aber realistisch , jede Größe, die es sein muss, wenn Sie etwas liefern müssen und dass es im Moment sinnvoller ist, sie so auszuspucken, macht Manchmal ist es für jemanden sogar noch einfacher, dies vor dem Versand zu überprüfen. (aber später noch darauf zurückkommen).

(Kürzlich hat mein Team ein Programm auf unserer Codebasis ausgeführt: Wir haben eine Klasse mit 197 Methoden und eine andere mit nur 3 Methoden gefunden, aber eine davon bestand aus 600 Zeilen. Süßes Spiel: Was ist das schlimmste der 2 Übel?)


Nun zu einer Zen-Antwort ... Im Allgemeinen wird es als eine gute Praxis (TM) angesehen, einen oder zwei große Männer zu zitieren.

Alles sollte so einfach wie möglich gemacht werden, aber nicht einfacher. - A. Einstein

Perfektion wird schließlich nicht erreicht, wenn nichts mehr hinzuzufügen ist, sondern wenn nichts mehr wegzunehmen ist. - A. de Saint Exupéry


Nachtrag zu Kommentarstilen

Als Ergänzung dazu sollten Ihre Funktionen klare Namen haben, die ihre Absicht erklären. In Bezug auf Kommentare kommentiere ich normalerweise nicht innerhalb einer Funktion:

  • Kommentare sagen "warum?" ,
  • Code sagt "wie?" .

Ein Kommentarblock am Anfang jeder Funktion (der einer Erklärung bedarf) reicht aus. Wenn Ihre Funktion klein ist und die Funktionsnamen explizit genug sind, sollten Sie nur sagen müssen, was Sie erreichen möchten und warum. Ich verwende Inline-Kommentare nur für Felder in einigen Sprachen oder bei Blockstarts für Funktionen, die gegen diese 25-35-Zeilenregeln verstoßen, wenn die Absicht unklar ist. Ich verwende einen Blockkommentar im Code, wenn eine Ausnahmesituation auftritt (ein Catch-Block, in dem Sie nichts tun müssen oder wollen, sollte beispielsweise einen Kommentar enthalten, der angibt, warum).

Für weitere Informationen lesen Sie bitte meine Antwort on Stil und Empfehlungen des Kommentarcodes

31
haylem

Meiner Meinung nach sollte jede Funktion so klein wie möglich sein. Jede Funktion sollte nur eines tun und es gut machen. Das beantwortet die Frage nach der maximalen Länge nicht wirklich, aber es sind eher meine Gefühle bezüglich der Länge von Funktionen.

Um die Worte von Onkel Bob zu verwenden, "Extrahieren, bis Sie einfach nicht mehr extrahieren können. Extrahieren, bis Sie fallen."

12
Jason

Was sollte die maximale Höhe eines Gebäudes sein? Hängt davon ab, wo sich der Build befindet oder wie hoch er sein soll.
Möglicherweise erhalten Sie unterschiedliche Antworten von unterschiedlichen Personen, die aus unterschiedlichen Städten stammen.
Einige Skriptfunktionen und Kernel-Interrupt-Handler sind sehr lang.

10
Huang F. Lei

Eine Methode, die für mich funktioniert, ist: Kann ich einen Teil einer längeren Funktion einen sinnvollen Namen geben lassen? Ich denke, die Länge einer Methode ist nicht so wichtig wie eine gute Benennung. Die Methode sollte das tun, was der Name sagt, nicht mehr und nicht weniger. Und Sie sollten in der Lage sein, einen guten Namen zu geben. Wenn Sie Ihre Methode nicht gut benennen können, ist der Code wahrscheinlich nicht gut zusammengesetzt.

10
Mnementh

Solange es sein muss, um das zu tun, was es tun muss, aber nicht mehr.

10
Paul Nathan

Ich denke, es gibt einen Kompromiss. Wenn Sie viele kurze Methoden haben, ist es oft schwieriger, sie zu debuggen als eine lange Methode. Wenn Sie 20 oder 30 Mal im Editor herumspringen müssen, um einen Methodenaufruf zu verfolgen, ist es schwierig, alles im Kopf zu behalten. Wenn es eine gut geschriebene klare Methode gibt, selbst wenn es sich um 100 Zeilen handelt, ist es oft einfacher, im Kopf zu bleiben.

Die eigentliche Frage ist, warum Elemente auf unterschiedliche Weise verwendet werden sollten, und die Antwort wie oben angegeben lautet Code-Wiederverwendung. Wenn Sie den Code nicht wiederverwenden (oder nicht wissen), kann es sinnvoll sein, ihn in einer riesigen, leicht zu befolgenden Methode zu belassen und dann, wenn Sie ihn wiederverwenden müssen, die Teile aufzuteilen, die erneut verwendet werden müssen Verwendung in kleinere Methoden.

In Wirklichkeit besteht ein Teil eines guten Methodendesigns darin, funktional zusammenhängende Methoden zu entwickeln (im Wesentlichen tun sie eine Sache). Die Länge der Methoden spielt keine Rolle. Wenn eine Funktion eine genau definierte Sache macht und 1.000 Zeilen umfasst, ist dies eine gute Methode. Wenn eine Funktion 3 oder 4 Dinge tut und nur 15 Zeilen umfasst, ist dies eine schlechte Methode ...

6
Cervo

Von Zyklomatische Komplexität (Wikipedia):

Die zyklomatische Komplexität eines Abschnitts des Quellcodes ist die Anzahl der linear unabhängigen Pfade durch den Quellcode.

  • Ich empfehle, dass Sie diese Zahl in einer einzigen Methode unter 10 halten. Wenn es 10 wird, ist es Zeit, neu zu faktorisieren.

  • Es gibt Tools, die Ihren Code auswerten und Ihnen eine zyklomatische Komplexitätszahl geben können.

  • Sie sollten sich bemühen, diese Tools in Ihre Build-Pipeline zu integrieren.

  • Verfolgen Sie eine Methodengröße nicht buchstäblich, sondern versuchen Sie, ihre Komplexität und Verantwortlichkeiten zu untersuchen. Wenn es mehr als eine Verantwortung hat, ist es wahrscheinlich eine gute Idee, neu zu faktorisieren. Wenn die zyklomatische Komplexität zunimmt, ist es wahrscheinlich an der Zeit, sie neu zu faktorisieren.

  • Ich bin mir ziemlich sicher, dass es andere Tools gibt, die Ihnen ähnliches Feedback geben, aber ich hatte noch keine Gelegenheit, dies zu untersuchen.

5
CodeART

Für mich ist eine Funktion beliebig lang. Die meiste Zeit, in der ich es aufteile, werde ich Code wiederverwenden.

Grundsätzlich werde ich mich an das Prinzip "hohe Kohäsion, niedrige Kopplung" halten und es gibt keine Einschränkung der Länge.

5
Ross

Die Frage sollte sein, wie viele Dinge eine Funktion tun soll. Und normalerweise ist es selten, dass Sie 100 Zeilen benötigen, um "eine" Sache zu tun. Dies hängt wiederum von der Ebene ab, von der aus Sie den Code betrachten: Ist das Hashing eines Passworts eine Sache? Oder ist Hashing und Speichern des Passworts eine Sache?

Ich würde sagen, beginnen Sie mit dem Speichern des Passworts als eine Funktion. Wenn Sie das Gefühl haben, dass Hashing anders ist und Sie den Code umgestalten. Ich bin keineswegs ein erfahrener Programmierer, aber meiner Meinung nach beginnt die ganze Idee von Funktionen klein: Je atomarer Ihre Funktionen sind, desto höher ist die Wahrscheinlichkeit einer Wiederverwendung von Code, und Sie müssen niemals dieselbe Änderung an mehr als einer Stelle vornehmen , usw.

Ich habe gesehen SQL gespeicherte Prozeduren , die über 1000 Zeilen laufen. Ist die Anzahl der Zeilen gespeicherter Prozeduren auch kleiner als 50? Ich weiß es nicht, aber es macht das Lesen des Codes zur Hölle. Sie müssen nicht nur weiter nach oben und unten scrollen, sondern auch einigen Codezeilen einen Namen wie "Dies führt zu Validierung1", "Diese Aktualisierungen in der Datenbank" usw. geben - eine Arbeit, die der Programmierer hätte erledigen müssen.

5
Narayana

Ich finde es einfacher, den Überblick zu behalten, was ich tue, wenn ich die gesamte Funktion auf einmal sehen kann. So schreibe ich lieber Funktionen:

  1. Kurz genug, um mit einer angemessenen Schrift auf meinen Monitor zu passen.
  2. Wenn es länger als Nr. 1 sein muss, kurz genug, um auf einem Blatt Papier in einer angemessenen Schriftart zu drucken.
  3. Wenn es länger als # 2 sein muss, kurz genug, um 2-fach auf ein Stück Papier zu drucken.

Ich schreibe selten längere Funktionen. Die meisten davon sind riesige C/C++ - Switch-Anweisungen.

5
Bob Murphy

Kurz genug, um richtig optimiert zu werden

Die Methoden sollten so kurz sein, dass sie genau eines bewirken. Der Grund dafür ist einfach: So kann Ihr Code richtig optimiert werden.

In einer JIT-Sprache wie Java oder C #) ist es wichtig, dass Ihre Methoden einfach sind, damit der JIT-Compiler schnell Code erzeugen kann. Längere, kompliziertere Methoden erfordern natürlich mehr JIT-Zeit. Außerdem bieten JIT-Compiler nur eine Handvoll Optimierungen, und nur die einfachsten Methoden profitieren davon. Diese Tatsache wurde sogar in Bill Wagners Effective C # erwähnt.

In einer untergeordneten Sprache wie C oder C++ ist es auch wichtig, kurze Methoden (etwa ein Dutzend Zeilen) zu haben, da Sie auf diese Weise die Notwendigkeit minimieren, lokale Variablen in RAM anstatt) zu speichern Beachten Sie jedoch, dass in diesem nicht verwalteten Fall die relativen Kosten für jeden Funktionsaufruf ziemlich hoch sein können.

Und selbst in einer dynamischen Sprache wie Ruby oder Python) hilft es auch bei Compiler-Optimierungen, kurze Methoden zu haben. In einer dynamischen Sprache ist es umso schwieriger, je dynamischer eine Funktion ist Zum Beispiel wird eine lange Methode, die ein X benötigt und ein Int, Float oder String zurückgeben kann, wahrscheinlich viel langsamer ausgeführt als drei separate Methoden, die jeweils nur einen einzigen Typ zurückgeben. Dies liegt daran, wenn der Compiler genau weiß, welcher Typ Wenn die Funktion zurückgegeben wird, kann auch die Site für Funktionsaufrufe optimiert werden. (z. B. keine Überprüfung auf Typkonvertierungen.)

4
Chris Smith

Normalerweise versuche ich, meine Methoden/Funktionen so zu halten, wie sie auf den Bildschirm eines 1680x1050-Monitors passen. Wenn es nicht passt, verwenden Sie Hilfsmethoden/-funktionen, um die Aufgabe zu parzellieren.

Es verbessert die Lesbarkeit auf Bildschirm und Papier.

4
Jason

Ich beschränke nichts auf eine harte Linie, da einige Funktionen Algorithmen implementieren, die von Natur aus komplex sind, und jeder Versuch, sie kürzer zu machen, die Interaktionen zwischen den neuen, kürzeren Funktionen so kompliziert machen würde, dass das Nettoergebnis keine Verringerung der Einfachheit bedeuten würde. Ich glaube auch nicht, dass die Idee, dass eine Funktion nur "eine Sache" tun sollte, ein guter Leitfaden ist, da "eine Sache" auf einer hohen Abstraktionsebene "viele Dinge" auf einer niedrigeren Ebene sein kann.

Für mich ist eine Funktion definitiv zu lang, wenn ihre Länge subtile Verstöße gegen DRY im Moment) verursacht und das Extrahieren eines Teils der Funktion in eine neue Funktion oder Klasse dies lösen könnte. Eine Funktion kann es auch sein lange, wenn dies nicht der Fall ist, aber eine Funktion oder Klasse leicht extrahiert werden könnte, die den Code auf eine Weise modularer macht, die angesichts vorhersehbarer Änderungen in der Zukunft wahrscheinlich nützlich ist.

4
dsimcha

Es hängt sehr davon ab, was im Code enthalten ist.

Ich habe eine Routine mit tausend Zeilen gesehen, mit der ich kein Problem hatte. Es war eine riesige switch-Anweisung, keine Option überschritt ein Dutzend Zeilen und die einzige Kontrollstruktur in einer Option war eine einzelne Schleife. Heutzutage wäre es mit Objekten geschrieben worden, aber das war damals keine Option.

Ich betrachte auch 120 Zeilen in einem Schalter vor mir. Kein Fall überschreitet 3 Zeilen - eine Wache, eine Aufgabe und die Pause. Es analysiert eine Textdatei, Objekte sind keine Möglichkeit. Jede Alternative wäre schwerer zu lesen.

3
Loren Pechtel

Die meisten Compiler haben nichts gegen die Länge einer Funktion. Eine Funktion sollte funktional sein, aber sowohl leicht zu verstehen als auch zu ändern und für den Menschen wiederzuverwenden sein. Wählen Sie eine Länge, die am besten zu Ihnen passt.

2

Vielleicht ist die Funktionslänge keine so gute Metrik. Wir versuchen, zyklomatische Komplexität auch für Methoden und eine der zukünftigen Regeln für das Einchecken der Quellcodeverwaltung zu verwenden, wonach die zyklomatische Komplexität für Klassen und Methoden niedriger als X sein muss.

Für Methoden ist X auf 30 gesetzt, und das ist ziemlich eng.

1
Antonio Bakula

Meine allgemeine Regel ist, dass eine Funktion auf den Bildschirm passen sollte. Ich habe nur drei Fälle gefunden, die dazu neigen, dies zu verletzen:

1) Versandfunktionen. Früher waren diese üblich, aber die meisten von ihnen werden heutzutage durch Objektvererbung ersetzt. Objekte funktionieren jedoch nur in Ihrem Programm, und daher werden beim Versand von Daten, die von einem anderen Ort eingehen, immer noch gelegentliche Versandfunktionen angezeigt.

2) Funktionen, die eine ganze Reihe von Schritten ausführen, um ein Ziel zu erreichen, und bei denen den Schritten eine gute Unterteilung fehlt. Am Ende erhalten Sie eine Funktion, die einfach eine lange Liste anderer Funktionen der Reihe nach aufruft.

3) Wie # 2, aber wenn die einzelnen Schritte so klein sind, dass sie einfach inline sind und nicht separat aufgerufen werden.

1
Loren Pechtel