Was ist eine gute Codepraxis, wenn eine Funktion / Methode für kleine sich wiederholende Codesegmente erstellt werden soll?


12

Oft habe ich mich beim Schreiben größerer Programme gefragt, nach wie vielen Kopieren und Einfügen es sinnvoll ist, den Code in eine Funktion oder Methode einzufügen, und was ist eine gute Faustregel? Ich habe eine Faustregel mit vier oder mehr Zeilen verwendet und tauche mehr als zweimal auf. Dann erstelle ich eine einfache Funktion / Methode, die diesen Code enthält. Können Sie sich eine bessere Vorgehensweise vorstellen oder Hinweise geben? Dies ist eher eine allgemeine Entwurfsmusterfrage als eine sprachspezifische Frage.

Antworten:


29

Ich benutze Funktionen teilweise, um den Code zu dokumentieren. Das Aufrufen einer Funktion mit einem aussagekräftigen Namen erleichtert das Verständnis des Codes. In einigen Fällen ist sogar eine Funktion mit einer einzelnen Zeile sinnvoll.

In "Clean Code" gibt Robert C. Martin beispielsweise das folgende Beispiel an: Welches würden Sie lieber sehen? Dies:

// Check to see if the employee is eligible for full benefits
if ((employee.flags & HOURLY_FLAG) &&
    (employee.age > 65))

Oder dieses?

if (employee.isEligibleForFullBenefits())

Ich stimme ihm nicht immer zu, aber in diesem Fall. Code sollte nicht nur lesbar sein, wenn Sie ihn schreiben und jedes Detail kennen, sondern auch um 21.00 Uhr, wenn Sie Fehler im Code eines anderen Benutzers beheben müssen. Es ist nicht empfehlenswert, lange zu warten und zu versuchen, alle Doppelnegative herauszufinden. Wenn Sie einfach einen Namen darauf setzen können (nicht nur Bedingungen, sondern jeden Code, den Sie schreiben), wird es viel einfacher.

Ich habe es nie bereut, etwas in eine Funktion eingefügt zu haben, und wenn Sie sich Sorgen um die Leistung machen, sollten Sie sich zuerst profilieren.


2
Wenn Sie diese einfache Vorgehensweise befolgen, können Sie den Anwendungscode möglicherweise auf einer relativ hohen Ebene schreiben. Die kleinen Funktionen werden in kleinen Klassen zusammengefasst und bald wandeln Sie funktionale Spezifikationen fast wörtlich in Code um.
Kevin Cline

11
Ich habe dieses Beispiel geliebt. Plötzlich brauchst du diesen Kommentar nicht mehr. Dies ist eine Faustregel : Wenn Ihr Kommentar in einen Variablen- oder Funktionsnamen konvertiert werden kann, tun Sie es!
Karoly Horvath

Ich stimme hier mit omrib überein, es geht oft darum, den Code zu bereinigen - was ihn besser lesbar macht als jede andere Faustregel. Wenn ich etwas wiederverwende, extrahiere ich es in eine Methode. Meine IDE und Tools helfen dabei jedoch häufig, sodass dies einfach und schnell möglich ist.
Travis

+1 Diese Art von Code könnte sogar noch schneller sein, zumindest wenn er JIT-geprüft werden muss - Sie zahlen nur für das, was Sie verwenden.
Job

1
auch bekannt als Intention Revealing Names .
rwong

13

Es gibt ein weit verbreitetes Missverständnis, dass Funktionsaufrufe nur erfolgen sollten, um sich wiederholende Codesegmente zu vermeiden. Meine Faustregel lautet, dass jede logische Arbeitseinheit zu einer Funktion gemacht werden sollte, auch wenn sie nur an einem einzigen Ort verwendet wird. Dies führt normalerweise zu einer besseren Lesbarkeit und ermöglicht es Ihnen, selbstdokumentierenden Code zu schreiben, bei dem Funktionsnamen Kommentare ersetzen und Sie keine zusätzlichen Kommentare schreiben müssen, die erklären, was Sie tun.


1
Sehen Sie, wie lange Programmierer brauchen, um keinen Kommentar zu schreiben?
Alger

1
@Alger wie sie sollten
MatrixFrog

6

Wenn es an mehr als einem Ort verwendet wird, und

  • es wird sich wahrscheinlich ändern, oder
  • Es ist schwierig, es richtig zu machen

dann mache es zu einer Funktion oder Methode. Nach meiner Erfahrung werden lange Teile von wiederholtem Code natürlich in eine dieser Kategorien fallen (normalerweise die erste, aber dann überlappen sich die Kategorien stark;). Natürlich ist alles, was sich in der Schnittstelle befinden muss, auch eine eigenständige Funktion / Methode.


3
Die Frage ist: Warum würden Sie keine Funktion für einen häufig wiederholten Teil des Codes schreiben, selbst wenn es nicht schwierig wäre, die richtige zu finden oder sich wahrscheinlich zu ändern? (Meine Faustregel: Wenn eine Funktion wiederholt und länger aufgerufen wird, machen Sie sie zu einer Funktion)
Winston Ewert

Ich würde noch weiter gehen. Als Programmierer müssen Sie alle Arten von Wiederholungen beseitigen . Ob in der Datenbank (normalisieren), einige manuelle Tests (ersetzen durch Komponententests) oder Bereitstellung (automatisieren).
Karoly Horvath

@ Winston: Das hängt von der verwendeten Sprache ab. Nicht jedes Konstrukt kann auf natürliche Weise als Funktion erfasst werden. Die Funktion benötigt möglicherweise mehr Platz als der ursprüngliche Code (denken Sie an C und geben Sie per Zeiger zurück). Funktionsaufrufe verursachen möglicherweise Overhead.
Fred Foo

@ Larsman, ich bin gespannt, worauf Sie sich beziehen, indem Sie "(denken Sie an C und kehren Sie mit dem Zeiger zurück)". Aber Sie sagen, was ich mit meiner Faustregel erreichen wollte. Das Aufrufen der Funktion muss einfacher sein (dh natürlich erfassen und weniger Platz beanspruchen) als das Implementieren des Funktionsinhalts.
Winston Ewert

Wenn ein Stück Code mehrere Werte berechnet, sagen wir float x, int yund double densitydann können diese Berechnungen als C - Funktion der Einrichtung sein heikler als nur den Code zu wiederholen, da Sie einen Weg finden , haben alle drei Werte raus. Wenn die wiederholten Berechnungen selbst trivial sind, ist es manchmal besser, sie einfach inline zu lassen.
Fred Foo

4

Fast immer, besonders wenn jedes Duplikat konzeptionell den gleichen Vorgang darstellt. Führen Sie eine generische Implementierung durch, wenn dies auf die gleiche Weise, jedoch auf unterschiedlichen Typen durchgeführt wird.

Der einzige Grund, warum ich mir das nicht vorstellen kann, ist die Wartung: Manchmal ist es vielleicht bequemer, eine Abhängigkeit zwischen einzelnen Dingen zu vermeiden, selbst wenn einige Duplikate erforderlich sind.


Hüten Sie sich vor Ente eingeben, wenn jetzt die Umsetzung ist ähnlich, aber die Funktionalität ist effektiv anders, dann die Zusammenlegung der beiden macht es ärgerlich wie die Hölle auf Split zurück. Vor allem in Sprachen mit schlechter IDE-Unterstützung (hey, ich arbeite in C ++ ...)
Matthieu M.

Auf der anderen Seite haben Sie zwei Funktionen, die das Gleiche tun, um zu testen, die Hälfte der Wahrscheinlichkeit, dass Ihr Code ausgeführt wird, zwei Stellen, an denen derselbe Fehler auftreten kann, und Sie müssen sich daran erinnern, den Fehler zu beheben, bei dem Der Fehler wurde noch nicht erkannt. Ich würde gerne noch in C ++ arbeiten, ungeachtet der schlechten IDE-Unterstützung ;-)
Nicola Musatti

1

Eine Suche nach " Refactoring " führt Sie zu vielen Ressourcen für "Best Practices" der Branche für diesen sehr häufigen Prozess. Der etwas berühmte Artikel " Once and Only Once" ist eine großartige historische Referenz, die erklärt, was einige als "Best Practices" für die von Ihrer Frage aufgeworfenen Bedenken ansehen. Das noch allgemeinere Konzept wird auch als Don't Repeat Yourself (DRY) bezeichnet . Lesen Sie Martin Fowlers großen Klassiker " Refactoring: Verbessern des Designs von vorhandenem Code" , der einige der bekanntesten Ratschläge für das Refactoring enthält , die Sie intuitiv ausführen möchten !


0

Wenn der Code mehrmals genau wiederholt wird und sich der wiederholte Abschnitt in naher Zukunft nicht ändern wird, breche ich ihn in eine Funktion auf.


1
wenn es sich ändern wird, noch mehr Grund, es umzugestalten. Dann müssen Sie es nur einmal ändern
SHug

0

Das hängt von der Art des Zusammenhalts des wiederholten Codes ab. Wenn der wiederholte Codeabschnitt eine bestimmte Funktion ausführt, ist er ein ausgezeichneter Kandidat für die Umwandlung in eine Methode, zum Teil aufgrund des DRY-Prinzips , zum Teil, weil nur ein Abschnitt vorhanden ist, wenn die Funktion optimiert oder korrigiert werden muss Code zu behandeln.

Wenn die Zuordnung zufällig ist, ist es besser, den Code zu wiederholen, als ihn in eine Methode umzuwandeln. Wenn Sie etwas in die Mitte einer der Codesequenzen einfügen müssen, um eine der Verwendungen dieses Snippets zu erfüllen, kann sich die Änderung, die Sie vornehmen, auf andere Verwendungen dieser Methode auswirken.

Siehe den Wikipedia-Artikel zum Konzept der Codekohäsion .


Wenn die Assoziation zufällig aussieht, ist es wahrscheinlich, dass die beiden Prozesse eine gemeinsame Idee haben, und Sie sollten wahrscheinlich untersuchen, ob die beiden Prozesse tatsächlich zwei Facetten derselben Sache sind. Meistens schon.
Lie Ryan

0

Man muss zwischen Funktionen im Sinne einer strukturierten Programmierung und Methoden einer Klasse unterscheiden.

In Ihrem Beispiel haben Sie eine Methode gezeigt, die als solche nicht inline codiert werden sollte.

Möglicherweise müssen Sie eine Zeichenfolge validieren, um festzustellen, ob es sich um eine Zahl handelt. In diesem Fall verwenden Sie eine Funktion, und die meisten der vorstehenden Antworten gelten.

Diese Unterscheidung ist besonders bei großen Projekten wichtig.

Versuchen Sie, so gut Sie können, Geschäftsregeln (das sind Methoden) von Rechenalgorithmen (das sind reine Programmierfunktionen) zu trennen.

Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.