In der objektorientierten Programmierung gibt es natürlich keine genaue Regel für die maximale Länge einer Methode, aber ich fand diese beiden Anführungszeichen immer noch etwas widersprüchlich. Ich würde gerne hören, was Sie denken.
In Clean Code: Ein Handbuch für agiles Software-Handwerk , sagt Robert Martin:
Die erste Regel für Funktionen ist, dass sie klein sein sollten. Die zweite Regel von Funktionen ist, dass sie kleiner sein sollten. Funktionen sollten nicht 100 Zeilen lang sein. Funktionen sollten selten 20 Zeilen lang sein.
und er gibt ein Beispiel aus Java-Code, den er von Kent Beck sieht:
Jede Funktion in seinem Programm war nur zwei, drei oder vier Zeilen lang. Jeder war transparent offensichtlich. Jeder erzählte eine Geschichte. Und jeder führte Sie in einer zwingenden Reihenfolge zum nächsten. So kurz sollten Ihre Funktionen sein!
Das hört sich gut an, aber in Code Complete sagt Steve McConnell etwas ganz anderes:
Die Routine sollte organisch auf 100 bis 200 Zeilen anwachsen können. Nach jahrzehntelangen Beweisen sind Routinen dieser Länge nicht fehleranfälliger als kürzere Routinen.
Und er gibt einen Hinweis auf eine Studie, die besagt, dass die Entwicklung von Routinen mit 65 Zeilen oder mehr billiger ist.
Gibt es also eine funktionale Best Practice für Sie, obwohl es unterschiedliche Meinungen zu diesem Thema gibt?
quelle
switch
Anweisung mit 100case
Bedingungen kann besser verwaltet werden als 10 Ebenen vonif
Anweisungen, die ineinander verschachtelt sind.Antworten:
Funktionen sollten normalerweise kurz sein, zwischen 5 und 15 Zeilen ist meine persönliche "Faustregel" beim Codieren in Java oder C #. Dies ist aus mehreren Gründen eine gute Größe:
Ich halte es jedoch nicht für hilfreich, eine absolute Regel festzulegen, da es immer gültige Ausnahmen / Gründe gibt, von der Regel abzuweichen:
Verwenden Sie also im Grunde den gesunden Menschenverstand , halten Sie sich in den meisten Fällen an kleine Funktionsgrößen, aber seien Sie nicht dogmatisch, wenn Sie einen wirklich guten Grund haben, eine ungewöhnlich große Funktion zu erstellen.
quelle
Obwohl ich mit den Kommentaren anderer übereinstimme, als sie sagten, dass es keine strengen Regeln für die richtige LOC-Nummer gibt, wette ich, wenn wir auf die Projekte zurückblicken, die wir in der Vergangenheit betrachtet haben, und jede Funktion oben identifizieren, sagen wir 150 Codezeilen. Vermutlich stimmen wir überein, dass 9 von 10 dieser Funktionen die SRP (und sehr wahrscheinlich auch die OCP) brechen, zu viele lokale Variablen und zu viel Kontrollfluss aufweisen und im Allgemeinen schwer zu lesen und zu warten sind.
Während LOC kein direkter Indikator für schlechten Code ist, ist es sicherlich ein anständiger indirekter Indikator dafür, dass bestimmte Funktionen besser geschrieben werden könnten.
In meinem Team fiel ich in die Position eines Leaders und aus irgendeinem Grund scheinen mir die Leute zuzuhören. Ich habe mich im Allgemeinen darauf geeinigt, dem Team mitzuteilen, dass, obwohl es kein absolutes Limit gibt, jede Funktion mit mehr als 50 Codezeilen bei der Codeüberprüfung mindestens eine rote Fahne setzen sollte, damit wir sie uns noch einmal ansehen und neu bewerten für Komplexität und SRP / OCP-Verstöße. Nach diesem zweiten Blick lassen wir es vielleicht in Ruhe oder ändern es, aber es bringt die Leute dazu, über diese Dinge nachzudenken.
quelle
Ich bin in ein Projekt eingetreten, das sich nicht um Codierungsrichtlinien gekümmert hat. Wenn ich in den Code schaue, finde ich manchmal Klassen mit mehr als 6000 Codezeilen und weniger als 10 Methoden. Dies ist ein Horrorszenario, wenn Sie Fehler beheben müssen.
Eine allgemeine Regel, wie groß eine Methode maximal sein sollte, ist manchmal nicht so gut. Ich mag die Regel von Robert C. Martin (Onkel Bob): "Methoden sollten klein sein, kleiner als klein". Ich versuche diese Regel die ganze Zeit anzuwenden. Ich versuche, meine Methoden einfach und klein zu halten, indem ich klarstelle, dass meine Methode nur eine Sache und nichts weiter tut.
quelle
Es geht nicht um die Anzahl der Zeilen, es geht um SRP. Nach diesem Prinzip sollte Ihre Methode nur eines tun.
Wenn Ihre Methode dies UND dies UND dieses ODER das macht => dann macht sie wahrscheinlich zu viel. Versuchen Sie, diese Methode zu betrachten und zu analysieren: "Hier erhalte ich diese Daten, sortiere sie und erhalte benötigte Elemente" und "Hier verarbeite ich diese Elemente" und "Hier kombiniere ich sie schließlich, um das Ergebnis zu erhalten". Diese "Blöcke" sollten auf andere Methoden umgestaltet werden.
Wenn Sie einfach SRP folgen, wird der größte Teil Ihrer Methode klein und mit klarer Absicht sein.
Es ist nicht richtig zu sagen "diese Methode ist> 20 Zeilen, so ist es falsch". Es kann ein Hinweis darauf sein, dass mit dieser Methode etwas nicht mehr stimmt.
Möglicherweise haben Sie einen Switch mit 400 Leitungen in einer Methode (kommt häufig in der Telekommunikation vor), und es liegt immer noch in der alleinigen Verantwortung, und es ist vollkommen in Ordnung.
quelle
Es hängt im Ernst davon ab, dass es auf diese Frage keine eindeutige Antwort gibt, da die Sprache, mit der Sie arbeiten, die fünf bis fünfzehnten Zeilen, die in dieser Antwort erwähnt werden, möglicherweise für C # oder Java funktionieren, in anderen Sprachen jedoch nicht Sie viel zu arbeiten. Abhängig von der Domäne, in der Sie arbeiten, werden Sie möglicherweise Codeeinstellungswerte in eine große Datenstruktur schreiben. Sollten Sie bei einigen Datenstrukturen möglicherweise Dutzende von Elementen festlegen müssen, um Funktionen zu trennen, nur weil Ihre Funktion lange ausgeführt wird?
Wie andere angemerkt haben, ist die beste Faustregel, dass eine Funktion eine einzelne logische Entität sein sollte, die eine einzelne Aufgabe behandelt. Wenn Sie versuchen, drakonische Regeln durchzusetzen, die besagen, dass Funktionen nicht länger als n Zeilen sein dürfen, und Sie diesen Wert zu klein machen, wird der Code schwerer lesbar, da Entwickler versuchen, die Regel mit ausgefallenen Tricks zu umgehen. Wenn Sie den Wert zu hoch einstellen, ist dies ebenfalls kein Problem und kann trotz Faulheit zu fehlerhaftem Code führen. Am besten führen Sie einfach Codeüberprüfungen durch, um sicherzustellen, dass die Funktionen eine einzelne Aufgabe bearbeiten, und lassen Sie es dabei.
quelle
Ich denke, ein Problem dabei ist, dass die Länge einer Funktion nichts über ihre Komplexität aussagt. LOC (Lines of Code) sind ein schlechtes Instrument, um etwas zu messen.
Eine Methode sollte nicht übermäßig komplex sein, aber es gibt Szenarien, in denen eine lange Methode einfach verwaltet werden kann. Beachten Sie, dass das folgende Beispiel nicht besagt, dass es nicht in Methoden aufgeteilt werden kann, sondern nur, dass die Methoden die Wartbarkeit nicht ändern.
Ein Handler für eingehende Daten kann beispielsweise eine große switch-Anweisung und dann einen einfachen Code pro Fall haben. Ich habe einen solchen Code - der eingehende Daten von einem Feed verwaltet. 70 (!) Numerisch codierte Handler. Jetzt wird man sagen "benutze Konstanten" - ja, außer dass die API sie nicht bereitstellt und ich hier gerne in der Nähe von "Quelle" bleibe. Methoden? Sicher - leider verarbeiten alle Daten aus denselben zwei riesigen Strukturen. Keine Vorteile bei der Abspaltung, außer vielleicht mehr Methoden (Lesbarkeit). Der Code ist an sich nicht komplex - ein Schalter, abhängig von einem Feld. Dann hat jeder Fall einen Block, der x Datenelemente analysiert und veröffentlicht. Kein Wartungsalptraum. Es gibt eine Wiederholungsbedingung "if", die bestimmt, ob ein Feld Daten enthält (pField = pFields [x], wenn pField-> IsSet () {blabla}) - so ziemlich für jedes Feld.
Ersetzen Sie dies durch eine viel kleinere Routine, die eine verschachtelte Schleife und viele echte Schaltanweisungen enthält, und eine riesige Methode kann einfacher zu warten sein als eine kleinere.
Also, tut mir leid, LOC ist zunächst keine gute Messung. Wenn überhaupt, sollten Komplexität / Entscheidungspunkte verwendet werden.
quelle
Ich werde nur noch ein Zitat einwerfen.
Es ist sehr unwahrscheinlich, dass Funktionen, die auf 100-200 anwachsen, dieser Regel folgen
quelle
Ich bin seit 1970 in diesem verrückten Schläger, auf die eine oder andere Weise.
In der ganzen Zeit habe ich mit zwei Ausnahmen, auf die ich gleich eingehen werde, NIEMALS eine gut gestaltete "Routine" (Methode, Prozedur, Funktion, Subroutine, was auch immer) gesehen, die mehr als eine gedruckte Seite sein MUSS ( etwa 60 Zeilen) lang. Die überwiegende Mehrheit von ihnen war ziemlich kurz, in der Größenordnung von 10-20 Zeilen.
Ich habe jedoch eine Menge "Stream-of-Awareness" -Code gesehen, der von Leuten geschrieben wurde, die anscheinend noch nie von Modularisierung gehört haben.
Die beiden Ausnahmen waren sehr spezielle Fälle. Eines ist eigentlich eine Klasse von Ausnahmefällen, die ich zusammenfasse: große endliche Automaten, die als große hässliche switch-Anweisungen implementiert sind, normalerweise, weil es keinen saubereren Weg gibt, sie zu implementieren. Diese Dinge werden normalerweise in automatisierten Testgeräten angezeigt und analysieren Datenprotokolle des getesteten Geräts.
Das andere war die Photonentorpedoroutine aus dem Spiel Matuszek-Reynolds-McGehearty-Cohen STARTRK, geschrieben in CDC 6600 FORTRAN IV. Es musste die Kommandozeile analysieren, dann den Flug jedes Torpedos mit Störungen simulieren, die Interaktion zwischen dem Torpedo und jeder Art von Dingen überprüfen, die es treffen konnte, und ach übrigens Rekursion simulieren, um 8-Wege-Konnektivität an Ketten von zu tun Novae vom Torpedieren eines Sterns, der neben anderen Sternen lag.
quelle
Wenn ich eine lange Methode finde, könnte ich wetten, dass diese Methode nicht richtig Unit-getestet ist oder die meiste Zeit überhaupt keinen Unit-Test hat. Wenn Sie mit TDD beginnen, werden Sie niemals 100-Zeilen-Methoden mit 25 verschiedenen Verantwortlichkeiten und 5 verschachtelten Schleifen aufbauen. Tests verpflichten Sie, Ihr Chaos ständig zu überarbeiten und Onkel Bobs sauberen Code zu schreiben.
quelle
Es gibt keine absoluten Regeln für die Länge der Methode, aber die folgenden Regeln waren nützlich:
quelle
Meinen die Autoren das Gleiche mit "Funktion" und "Routine"? Wenn ich "function" sage, meine ich normalerweise eine Subroutine / Operation, die einen Wert und "procedure" für eine zurückgibt, die dies nicht tut (und deren Aufruf zu einer einzigen Anweisung wird). Dies ist in SE in der realen Welt keine alltägliche Unterscheidung, aber ich habe sie in Anwendertexten gesehen.
In beiden Fällen gibt es keine richtige Antwort darauf. Ich würde erwarten, dass die Bevorzugung der einen oder der anderen Sprache, des Projekts und der Organisation sehr unterschiedlich ist (wenn es überhaupt eine Präferenz gibt). Genau wie bei allen Code-Konventionen.
Das einzige, was ich hinzufügen möchte, ist, dass die Behauptung "lange Operationen sind nicht fehleranfälliger als kurze Operationen" nicht strikt wahr ist. Zusätzlich zu der Tatsache, dass mehr Code mehr potenziellem Fehlerraum entspricht, ist es offensichtlich, dass das Aufteilen von Code in Segmente Fehler sowohl leichter zu vermeiden als auch leichter zu lokalisieren macht. Andernfalls gäbe es keinen Grund, Code in Teile zu zerlegen, außer bei Wiederholungen. Dies ist jedoch möglicherweise nur dann der Fall, wenn die Segmente so gut dokumentiert sind, dass Sie die Ergebnisse eines Operationsaufrufs ermitteln können, ohne den tatsächlichen Code durchzulesen oder nachzuvollziehen (Design-by-Contract basierend auf Spezifikationen und nicht auf konkreten Abhängigkeiten zwischen Codebereichen).
Wenn Sie möchten, dass längere Vorgänge gut funktionieren, möchten Sie möglicherweise strengere Codekonventionen anwenden, um sie zu unterstützen. Das Verwerfen einer return-Anweisung mitten in einer Operation kann für eine kurze Operation in Ordnung sein, aber bei längeren Operationen kann dies einen großen Codeabschnitt erzeugen, der bedingt ist, aber offensichtlich nicht von einem schnellen Durchlesen abhängig ist (nur für ein Beispiel).
Ich würde also denken, dass der Stil, bei dem es weniger wahrscheinlich ist, dass er mit Fehlern behaftet ist, zu einem großen Teil davon abhängt, welche Konventionen Sie für den Rest Ihres Codes einhalten. :)
quelle
IMHO sollten Sie nicht Bildlaufleiste verwenden müssen, um Ihre Funktion zu lesen. Sobald Sie die Bildlaufleiste bewegen müssen, dauert es einige Zeit, um zu verstehen, wie die Funktion funktioniert.
Dementsprechend hängt es von der üblichen Programmierumgebung Ihrer Teamarbeit ab (Bildschirmauflösung, Editor, Schriftgröße, etc ...). In den 80er Jahren waren es 25 Zeilen und 80 Spalten. Jetzt zeige ich in meinem Editor fast 50 Zeilen an. Die Anzahl der angezeigten Spalten hat sich nicht geändert, seit ich meinen Bildschirm zweigeteilt habe, um jeweils zwei Dateien anzuzeigen.
Kurz gesagt, es hängt vom Setup Ihrer Mitarbeiter ab.
quelle
Ich denke, TomToms Antwort kam meiner Meinung nach sehr nahe.
Ich finde mich immer mehr in zyklomatischer Komplexität als in Linien wieder.
Normalerweise strebe ich nicht mehr als eine Kontrollstruktur pro Methode an, mit Ausnahme der Anzahl der Schleifen, die für die Verarbeitung eines mehrdimensionalen Arrays erforderlich sind.
Manchmal setze ich einzeilige ifs in Switch Cases ein, weil dies aus irgendeinem Grund eher der Fall ist, als dass es hilft, wenn man es aufteilt.
Beachten Sie, dass ich keine Schutzlogik für diese Grenze zähle.
quelle
In OOP sind alle Dinge Objekt und es gibt diese Funktionen:
Wenn Sie diese Regeln einhalten, sind Ihre Methoden normalerweise klein, es gibt jedoch keine Regeln für kleine oder sehr kleine Regeln (z. B. 2-3 Zeilen). Ein Vorteil einer kleinen Methode (kleine Einheit, z. B. Methode oder Funktion) sind:
quelle