Kann eine Funktion zu kurz sein?

125

Immer wenn ich die gleiche Logik mehrmals schreibe, schreibe ich sie normalerweise in eine Funktion, sodass es nur eine Stelle in meiner Anwendung gibt, an der ich diese Logik beibehalten muss. Ein Nebeneffekt ist, dass ich manchmal mit ein oder zwei Zeilenfunktionen ende, wie zum Beispiel:

function conditionMet(){
   return x == condition;
}

ODER

function runCallback(callback){
   if($.isFunction(callback))
     callback();
}

Ist das faul oder eine schlechte Übung? Ich frage nur, weil dies zu einer größeren Anzahl von Funktionsaufrufen für sehr kleine Teile der Logik führt.

Mark Brown
quelle
3
Nein, nicht zu kurz. In C # würde ich "Bedingung erfüllt" als eine Eigenschaft tun, die elegant ist und die Verwendung in Betracht ziehen würde Assert.AreEqual<int>(expected, actual, message, arg1, arg2, arg3, ...);. Der zweite ist in Ordnung so wie er ist. Ich würde möglicherweise ein optionales Bool-Flag einfügen, das vorschreibt, ob eine Ausnahme ausgelöst werden soll. falls der callback keine funktion ist.
Job
38
Ja, nur in einem Fall: function myFunction () {}
Spooks
5
def yes(): return 'yes'
Dietbuddha
3
@Spooks - Ich teile hier die Haare auf, aber leere Funktionen sind mindestens für Adapterklassen gültig, z. B. MouseMotionAdapter in download.oracle.com/javase/6/docs/api/java/awt/event/… . Dies ist natürlich nur eine Möglichkeit, um Spracheinschränkungen zu umgehen.
Aleksi Yrttiaho
3
@dietbuddha: Die Anforderungen haben sich gerade geändert - jetzt muss es für eine Demo nächste Woche zwei Sprachen unterstützen. Der Typ, der "def yes ()" schrieb, war sehr froh, bevor er es in "def yes (: (IsFrench ()? 'Oui': 'Yes')" änderte
Andrew Shepherd

Antworten:

167

Hehe, oh Mr. Brown, wenn ich nur alle Entwickler, denen ich begegne, überreden könnte, ihre Funktionen so klein zu halten, glauben Sie mir, die Software-Welt wäre ein besserer Ort!

1) Ihre Codelesbarkeit verzehnfacht sich.

2) So einfach, den Prozess Ihres Codes wegen der Lesbarkeit herauszufinden.

3) TROCKEN - Wiederholen Sie sich nicht - Sie passen sich dem sehr gut an!

4) Testbar. Winzige Funktionen sind millionenfach einfacher zu testen als die 200-Zeilen-Methoden, die wir viel zu oft sehen.

Oh und mach dir keine Sorgen über "Funktionssprung" in Bezug auf die Leistung. "Release" Builds und Compiler-Optimierungen erledigen dies für uns sehr gut, und die Leistung ist zu 99% in anderen Bereichen des Systemdesigns zu finden.

Ist das faul? - Ganz im Gegenteil!

Ist das schlechte Praxis? - Absolut nicht. Besser diese Art der Herstellung als die Teerbälle oder "God Objects", die ach so üblich sind.

Mach weiter so mein Handwerkskollege;)

Martin Blore
quelle
40
Sie beantworten die Frage nicht, sondern predigen nur die Regel, deren extremere Anwendungen hier in Frage gestellt werden.
4
Es kommt nicht sehr oft vor, dass ich die Einschränkung von nur 1 Gegenstimme als frustrierend empfinde. Aber für diese Antwort scheint +1 nicht gerecht zu werden.
Bevan
4
+5 ... oh kann nur +1 geben, na ja! Und zur Unterstützung MeshMan, schlage ich folgendes Buch von Robert C. Martin Sauberem Code . Dieses Buch verändert wirklich die Art und Weise, wie ich jetzt programmiere.
Eric-Karl
10
Sehr sympathische Antwort, aber ich bin mit den meisten davon nicht einverstanden: 1) Extrem kleine Funktionen führen insgesamt zu mehr Code, da für jede Funktion mehr Installationsschritte erforderlich sind. Dies kann die Lesbarkeit beeinträchtigen, insbesondere bei sehr großen Projekten. Auch sprachabhängig. 2) Kommt ganz auf Punkt 1 an und hat daher nichts mit der Frage zu tun. 3) Was? runCallback wiederholt den "Rückruf" viermal und dreimal bezieht sich auf dieselbe Variable, um eine einzelne Funktion auszuführen. 4) Methoden mit mehr als 200 Zeilen sind natürlich nicht testbar, aber von dieser zu einer Zeile ist es ein weiter Weg.
l0b0
10
-1: Das Beängstigendste ist die Anzahl der Stimmen, die auf diese Antwort abgegeben wurden.
Luca
64

Ich würde sagen, dass eine überarbeitete Methode zu kurz ist, wenn entweder:

  • Es dupliziert eine primitive Operation nur, um sie zu einer Methode zu machen:

Ex:

boolean isNotValue() {
   return !isValue();
}

oder...

  • Der Code wird nur einmal verwendet und seine Absicht ist auf einen Blick leicht zu verstehen.

Ex:

void showDialog() {
    Dialog singleUseDialog = new ModalDialog();
    configureDialog(singleUseDialog);
    singleUseDialog.show();
}

void configureDialog(Dialog singleUseDialog) {
    singleUseDialog.setDimensions(400, 300);
}

Dies könnte ein gültiges Muster sein, aber in diesem Beispiel würde ich nur die configureDialog () -Methode einbinden, es sei denn, ich beabsichtige, sie zu überschreiben oder diesen Code an einer anderen Stelle wiederzuverwenden.

RMorrisey
quelle
7
Das Trennen einer einzeiligen Methode im zweiten Fall kann vorteilhaft sein, um die Abstraktionsebene der aufrufenden Methoden konsistent zu halten. Das angegebene Beispiel befindet sich auf dem Zaun, wenn diese Überlegung verwendet wird: Ist die genaue Pixelbreite und -höhe zu detailliert, um einen Dialog anzuzeigen?
Aleksi Yrttiaho
2
Die Methode "isNotValue ()" ist falsch benannt und sollte überarbeitet werden, um die eigentliche Domänenfrage zu benennen.
4
@ Aleksi: Ich stimme nicht zu; Die Details sind in diesem Beispiel bereits in der Methode showDialog () verborgen. Es ist nicht nötig, es doppelt zu überarbeiten. Das Beispiel soll einen isolierten Anwendungsfall zeigen. Wenn in verschiedenen Fällen ein Muster mit unterschiedlichen Dialogkonfigurationen benötigt wird, ist es sinnvoll, zurückzugehen und eine Umgestaltung durchzuführen, sobald das Muster erstellt ist.
RMorrisey
1
@Thorbjorn: Ich könnte einen Fall dafür sehen, wenn Sie eine Geschäftsdomänenfrage beantworten, deren Logik möglicherweise nicht offensichtlich ist. Ich weise nur darauf hin, dass es Fälle gibt, in denen es übertrieben ist.
RMorrisey
3
Vielleicht ist dies eine Fehlauswahl, aber ich würde argumentieren, dass in Ihren Beispielen das Problem nicht darin besteht, dass die Funktion zu kurz ist, sondern dass sie keinen beschreibenden Wert hinzufügen.
Keppla
59

Kann eine Funktion zu kurz sein? Im Allgemeinen nicht.

In der Tat der einzige Weg, um sicherzustellen, dass:

  1. Sie haben alle Klassen in Ihrem Entwurf gefunden
  2. Ihre Funktionen machen nur eine Sache.

Ist, um Ihre Funktionen so klein wie möglich zu halten. Oder mit anderen Worten, extrahieren Sie Funktionen aus Ihren Funktionen, bis Sie nicht mehr extrahieren können. Ich nenne das "Extrakt bis zum Umfallen".

Um dies zu erklären: Eine Funktion ist ein Bereich mit Funktionsblöcken, die über Variablen kommunizieren. Eine Klasse ist auch ein Bereich mit Funktionsblöcken, die über Variablen kommunizieren. So kann eine lange Funktion immer durch eine oder mehrere Klassen mit kleiner Methode ersetzt werden.

Eine Funktion, die groß genug ist, um eine andere Funktion daraus zu extrahieren, ist per Definition mehr als eine Sache . Also , wenn Sie können eine Funktion von einem anderen extrahieren, Sie sollten diese Funktion extrahieren.

Einige Leute befürchten, dass dies zu einer Verbreitung von Funktionen führen wird. Sie haben recht Es wird. Das ist eigentlich eine gute Sache. Es ist gut, weil Funktionen Namen haben. Wenn Sie bei der Auswahl guter Namen vorsichtig sind, fungieren diese Funktionen als Wegweiser, die andere Personen durch Ihren Code leiten. In der Tat sind gut benannte Funktionen in gut benannten Klassen in gut benannten Namespaces eine der besten Möglichkeiten, um sicherzustellen, dass Ihre Leser NICHT verloren gehen.

Darüber gibt es in Episode III von Clean Code auf cleancoders.com noch viel mehr

Onkel Bob.
quelle
5
Onkel Bob! Schön, Sie hier an Bord zu sehen. Wie erwartet, fantastischer Rat. Ich habe den Begriff "Extrahieren bis zum Umfallen" noch nie gehört und werde diesen Begriff mit Sicherheit ab Montag im Büro verwenden;).
Martin Blore
1
Wären Sie bereit, auf Ihren ersten Punkt einzugehen? Das mit gutem Beispiel zu erklären wäre großartig.
Daniel Kaplan
53

Wow, die meisten dieser Antworten sind überhaupt nicht hilfreich.

Es sollte keine Funktion geschrieben werden, deren Identität ihre Definition ist . Das heißt, wenn der Funktionsname einfach der in Englisch geschriebene Codeblock der Funktion ist, dann schreibe ihn nicht als Funktion.

Betrachten Sie Ihre Funktion conditionMetund diese andere Funktion addOne(verzeihen Sie mir mein rostiges JavaScript):

function conditionMet() { return x == condition; }

function addOne(x) { return x + 1; }

conditionMetist eine richtige konzeptionelle Definition; addOneist eine Tautologie . conditionMetist gut, weil Sie nicht wissen, was conditionMetbedeutet, addOnewenn Sie nur "Bedingung erfüllt" sagen, aber Sie können sehen, warum es albern ist, wenn Sie es auf Englisch vorlesen:

"For the condition to be met is for x to equal condition" <-- explanatory! meaningful! useful!

"To add one to x is to take x and add one." <-- wtf!

Schreiben Sie aus Liebe zu allem, was noch heilig sein könnte, bitte keine tautologischen Funktionen!

( Schreiben Sie aus dem gleichen Grund keine Kommentare für jede Codezeile !)

Rei Miyasaka
quelle
Einige der komplexeren Sprachkonstrukte sind möglicherweise unbekannt oder schwer zu lesen, was dies zu einem nützlichen Trick macht.
3
Einverstanden, was genau in eine Funktion umgewandelt werden soll, hängt weitgehend von der Sprache ab, in der sie geschrieben wird. Eine Funktion wie addOne ist hilfreich, wenn Sie in einer Sprache wie VHDL arbeiten, in der Sie die Bedeutung des Hinzufügens einer Funktion zu einer definieren Binär- oder Zahlentheorieebene. Ich würde gerne denken, dass keine Sprache draußen so kryptisch ist, dass es selbst für geübte Programmierer schwer zu lesen ist (vielleicht brainf # ck), aber wenn das der Fall ist, würde die gleiche Idee gelten, da die Funktion tatsächlich eine Übersetzung aus dem Englischen ist zu dieser Sprache - so ist der Name nicht mit der Definition identisch.
Rei Miyasaka
1
Ich spreche über die Identitätsfunktion von Dingen aus der Haskell-Standardbibliothek - ich glaube nicht, dass man "tautologischer" sein kann als das :)
hugomg
1
@missingno Bah, das ist Betrug: D
Rei Miyasaka
5
Wenn Sie die Funktionen nach ihrem Zweck anstatt nach ihrem Inhalt benennen, werden sie sofort nicht mehr albern. So könnten deine Beispiele zB sein function nametoolong() { return name.size > 15; }oder function successorIndex(x) { return x + 1; } so ist das Problem mit deinen Funktionen eigentlich nur, dass sie schlecht heißen.
Hans-Peter Störr
14

Ich würde sagen, wenn Sie der Meinung sind, dass die Absicht eines Codes durch Hinzufügen eines Kommentars verbessert werden kann, extrahieren Sie den Code in eine eigene Methode, anstatt diesen Kommentar hinzuzufügen. Egal wie klein der Code war.

Wenn Ihr Code zum Beispiel so aussehen würde:

if x == 1 { ... } // is pixel on?

Lass es stattdessen so aussehen:

if pixelOn() { ... }

mit

function pixelOn() { return x == 1; }

Mit anderen Worten, es geht nicht um die Methodenlänge, sondern um selbstdokumentierenden Code.

Julio
quelle
5
Mein geschätzter Kollege weist darauf hin, dass Sie auch schreiben könnten if x == PIXEL_ON. Die Verwendung einer Konstante kann genauso aussagekräftig sein wie die Verwendung einer Methode und ist etwas kürzer.
Tom Anderson
7

Ich denke, genau das möchten Sie tun. Im Moment besteht diese Funktion vielleicht nur aus einer oder zwei Zeilen, aber im Laufe der Zeit könnte sie wachsen. Wenn Sie außerdem mehr Funktionsaufrufe haben, können Sie die Funktionsaufrufe lesen und nachvollziehen, was dort vor sich geht. Dies macht Ihren Code sehr trocken (Don't Repeat Yourself), was viel besser zu pflegen ist.

mpenrow
quelle
4
Was ist also falsch daran, es später auszublenden, wenn Sie beweisen können, dass Sie es brauchen, anstatt jetzt, wenn es nur totes Gewicht ist?
Dsimcha
Funktionen wachsen nicht von alleine. IMHO sind die Beispiele mies. conditionMetist ein zu generischer Name und nimmt kein Argument an, also testet er irgendeinen Zustand? (x == xCondition) ist in den meisten Sprachen und Situationen so aussagekräftig wie 'xConditition'.
Benutzer unbekannt
Ja, und aus diesem Grund möchten Sie einen Overhead von über 75% in Ihrem Code haben? Single-Liner als 3 Zeilen geschrieben ist eigentlich 300%.
Coder
5

Ich stimme allen anderen Posts zu, die ich gesehen habe. Das ist guter Stil.

Der Overhead einer so kleinen Methode kann null sein, da der Optimierer den Abruf optimieren und den Code einbinden kann. Ein einfacher Code wie dieser ermöglicht es dem Optimierer, seine beste Arbeit zu leisten.

Code sollte aus Gründen der Klarheit und Einfachheit geschrieben werden. Ich versuche, eine Methode auf eine von zwei Rollen zu beschränken: Entscheidungen treffen; oder Arbeit verrichten. Dies kann einzeilige Methoden erzeugen. Je besser ich das kann, desto besser finde ich meinen Code.

Code wie dieser weist tendenziell eine hohe Kohäsion und eine niedrige Kopplung auf, was eine gute Kodierungspraxis ist.

EDIT: Ein Hinweis zu Methodennamen. Verwenden Sie einen Methodennamen, der angibt, was die Methode nicht tut, wie sie es tut. Ich finde verb_noun (_modifier) ​​ist ein gutes Namensschema. Dies gibt Namen wie Find_Customer_ByName und nicht Select_Customer_Using_NameIdx. Der zweite Fall neigt dazu, falsch zu werden, wenn die Methode geändert wird. Im ersten Fall können Sie die gesamte Implementierung der Kundendatenbank austauschen.

BillThor
quelle
+1 für die Erwähnung von Inlining, imo das Hauptaugenmerk auf Leistung und Kurzfunktionen.
Garet Claborn
4

Das Umgestalten einer Codezeile in eine Funktion scheint übertrieben. Es kann Ausnahmefälle geben, wie z. B. sehr viele Zeilen oder Erweiterungen, aber ich würde dies nicht tun, es sei denn, ich weiß, dass die Funktion in Zukunft erweitert wird.

und Ihr erstes Beispiel weist auf die Verwendung von Globals hin (die möglicherweise von anderen Problemen im Code sprechen). Ich würde es weiter überarbeiten und diese beiden Variablen als Parameter definieren:

function conditionMet(x, condition){
   return x == condition;
}
....
conditionMet(1,(3-2));
conditionMet("abc","abc");

Das conditionMetBeispiel könnte nützlich sein , wenn die Bedingung war lange und sich wiederholende wie zum Beispiel:

function conditionMet(x, someObject){
   return x == ((someObject.valA + someObject.valB - 15.4) / /*...whole bunch of other stuff...*/);
}
FrustratedWithFormsDesigner
quelle
1
Sein erstes Beispiel weist nicht auf Globales hin. Wenn überhaupt, handelt es sich um eine zusammenhängende Methode in einer sehr zusammenhängenden Klasse, in der sich die meisten Variablen auf dem Objekt befinden.
Martin Blore
7
Diese conditionMetFunktion ist nur ein ausführlicher ==Operator. Das ist wahrscheinlich nicht nützlich.
1
Ich benutze definitiv keine Globals. @MeshMan, genau dort, wo das Beispiel herkommt ... eine Methode für eine Klasse.
Mark Brown
1
@ Mark Brown: @ MeshMan: Ok, ich denke, das Codebeispiel war zu vage, um es sicher zu wissen ...
FrustratedWithFormsDesigner
Ich rieche ein conditionMet (x, relation condition) {hier, wo Sie x, '==' und Beziehung übergeben. Dann brauchen Sie den Code für '<', '>', '<=', '! =' Und so weiter nicht zu wiederholen. Auf der anderen Seite - die meisten Sprachen haben diese Konstrukte eingebaut, da Operatoren (x == Bedingung) genau das tun. Funktionen für atomare Anweisungen sind einen Schritt zu weit entfernt.
Benutzer unbekannt
3

Bedenken Sie:

Eine einfache Kollisionserkennungsfunktion:

bool collide(OBJ a, OBJ b)
{
    return(pow(a.x - b.x, 2) + pow(a.y - b.y, 2) <= pow(a.radius + b.radius, 2));
}

Wenn Sie diese "einfache" Zeile die ganze Zeit in Ihren Code geschrieben haben, könnten Sie irgendwann einen Fehler machen. Außerdem wäre es wirklich mühsam, das immer und immer wieder zu schreiben.

muntoo
quelle
Wenn wir es hier mit C zu tun haben, könnten wir es einfach missbrauchen #define;)
Cole Johnson
Vielleicht möchten Sie dies sogar gegen die langsamere, aber überlaufsichere Hypot austauschen, wenn Ihre Größen oder Abstände sehr groß werden. Das ist natürlich viel einfacher, wenn man es einmal macht.
Matt Krause
2

Nein, und das ist selten ein Problem. Wenn jemand der Meinung ist, dass keine Funktion länger als eine Codezeile sein sollte (wenn es nur so einfach sein könnte), wäre dies ein Problem und in gewisser Weise faul, weil er nicht darüber nachdenkt, was angemessen ist.

JeffO
quelle
Ich würde es nicht in Codezeilen zählen, sondern in Ausdrücken. "(x == condition)" ist atomar, daher würde ich es nur dann in eine Methode / Funktion einfügen, wenn es mehrfach verwendet wird UND möglicherweise geändert wird, wie function isAdult () = { age >= 18; }aber sicherlich nicht isAtLeast18.
Benutzer unbekannt
2

Ich würde sagen, sie sind zu kurz, aber das ist meine subjektive Meinung.

Weil:

  • Es gibt keinen Grund, eine Funktion zu erstellen, wenn sie nur ein- oder zweimal verwendet wird. Springen auf Defs saugen. Besonders mit erstaunlich schnellem VS- und C ++ - Code.
  • Klassenübersicht. Wenn Sie Tausende kleiner Funktionen haben, macht es mich wütend. Ich genieße es, wenn ich Klassendefinitionen anzeigen und schnell sehen kann, was es tut, nicht wie es SetXToOne, SetYToVector3, MultiplyNumbers, + 100 Setter / Getter.
  • In den meisten Projekten werden diese Helfer nach einer oder zwei Umgestaltungsphasen unfähig, und dann "alle durchsuchen" -> "löschen", um veralteten Code zu entfernen, in der Regel ~ 25% +.

Funktionen, die lang sind, sind schlecht, aber Funktionen, die kürzer als 3 Zeilen sind und nur 1 Ding ausführen, sind IMHO gleich schlecht.

Also würde ich sagen, schreibe nur kleine Funktionen, wenn es:

  • 3+ Codezeilen
  • Gibt es Dinge, die Junior-Entwickler vermissen könnten (nicht wissen)
  • Führt eine zusätzliche Validierung durch
  • Wird verwendet oder wird mindestens 3x verwendet
  • Vereinfacht häufig verwendete Benutzeroberfläche
  • Wird beim nächsten Refactoring nicht zum Eigengewicht
  • Hat eine spezielle Bedeutung, zum Beispiel Template-Spezialisierung oder so
  • Erledigt einige Isolationsaufgaben - const-Referenzen, beeinflusst veränderbare Parameter, ruft private Mitglieder ab

Ich wette, der nächste Entwickler (Senior) wird bessere Dinge zu tun haben, als sich an alle Ihre SetXToOne-Funktionen zu erinnern. So werden sie ziemlich bald in totes Gewicht verwandeln.

Coder
quelle
1

Das Beispiel Nr. Gefällt mir nicht. 1, weil es ein Gattungsname ist.

conditionMetscheint nicht generisch zu sein, steht es also für eine bestimmte Bedingung? Mögen

isAdult () = { 
  age >= 18 
}

Das wäre in Ordnung. Es ist ein semantischer Unterschied, während

isAtLeast18 () { age >= 18; } 

wäre nicht gut für mich.

Vielleicht wird es oft verwendet und kann später geändert werden:

getPreferredIcecream () { return List ("banana", "choclate", "vanilla", "walnut") }

ist auch in Ordnung. Wenn Sie es mehrmals verwenden, müssen Sie nur einen Ort wechseln, wenn Sie müssen - vielleicht wird Schlagsahne morgen möglich.

isXYZ (Foo foo) { foo.x > 15 && foo.y < foo.x * 2 }

ist nicht atomar, und sollte Ihnen eine schöne Testmöglichkeit geben.

Wenn Sie eine Funktion übergeben müssen, übergeben Sie natürlich alles, was Sie möchten, und schreiben Sie ansonsten albern aussehende Funktionen.

Aber im Allgemeinen sehe ich viel mehr Funktionen, die zu lang sind, als Funktionen, die zu kurz sind.

Ein letztes Wort: Einige Funktionen sehen nur deshalb passend aus, weil sie zu ausführlich geschrieben sind:

function lessThan (a, b) {
  if (a < b) return true else return false; 
}

Wenn Sie sehen, dass es das gleiche ist wie

return (a < b); 

Sie werden kein Problem mit haben

localLessThan = (a < b); 

Anstatt von

localLessThan = lessThan (a, b); 
Benutzer unbekannt
quelle
0

Es gibt keinen Code wie keinen Code!

Halten Sie es einfach und nicht zu kompliziert.

Es ist nicht faul, es macht deinen Job!

RDL
quelle
0

Ja, es ist in Ordnung, eine Funktionscode-Funktion zu haben. Bei Methoden wie "Getter", "Setter" und "Accesors" ist dies, wie bereits erwähnt, weit verbreitet.

Manchmal sind diese kurzen "accesors" -Funktionen virtuell, da die Funktionen beim Überschreiben in Unterklassen mehr Code enthalten.

Wenn Sie möchten, dass Sie nicht so kurz funktionieren, ob global oder methodisch, verwende ich normalerweise eine "Ergebnis" -Variable (Pascal-Stil) anstelle einer direkten Rückgabe. Dies ist sehr hilfreich, wenn Sie einen Debugger verwenden.

function int CalculateSomething() {
  int Result = -1;

   // more code, maybe, maybe not

  return Result;
}
umlcat
quelle
0

Zu kurz ist nie ein Problem. Einige Gründe für kurze Funktionen sind:

Wiederverwendbarkeit

Wenn Sie z. B. eine Funktion haben, wie z. B. eine Set-Methode, können Sie diese festlegen, um sicherzustellen, dass die Parameter gültig sind. Diese Überprüfung muss überall dort erfolgen, wo die Variable gesetzt ist.

Wartbarkeit

Möglicherweise verwenden Sie eine Aussage, von der Sie glauben, dass sie sich in Zukunft ändern könnte. Sie zeigen jetzt beispielsweise ein Symbol in einer Spalte an, das sich später jedoch möglicherweise zu etwas anderem (oder sogar zu einem Piepton) ändert.

Gleichmäßigkeit

Sie verwenden z. B. das Fassadenmuster und eine Funktion gibt die Funktion nur exakt an eine andere weiter, ohne die Argumente zu ändern.

Michel Keijzers
quelle
0

Wenn Sie einem Codeabschnitt einen Namen geben, dient dies im Wesentlichen dazu, ihm einen Namen zu geben . Dies kann verschiedene Gründe haben, aber der entscheidende Punkt ist, ob Sie ihm einen aussagekräftigen Namen geben können, der Ihr Programm erweitert. Namen wie "addOneToCounter" würden nichts hinzufügen, conditionMet()würden aber .

Wenn Sie eine Regel benötigen, um herauszufinden, ob das Snippet zu kurz oder zu lang ist, überlegen Sie, wie lange Sie brauchen, um einen aussagekräftigen Namen für das Snippet zu finden. Wenn Sie dies nicht innerhalb einer angemessenen Zeitspanne tun können, ist das Snippet nicht in der richtigen Größe.

user1249
quelle
0

Nein, aber es kann zu knapp sein.

Denken Sie daran: Code wird einmal geschrieben, aber mehrmals gelesen.

Schreiben Sie keinen Code für den Compiler. Schreiben Sie es für zukünftige Entwickler, die Ihren Code warten müssen.

Jim G.
quelle
-1

Ja, meine Liebe, die Funktion könnte immer kleiner werden und ob sie gut oder schlecht ist, hängt von der Sprache / dem Framework ab, das Sie verwenden.

Meiner Meinung nach beschäftige ich mich hauptsächlich mit Front-End-Technologien. Kleine Funktionen werden meistens als Hilfsfunktionen verwendet, die Sie bei der Arbeit mit kleinen Filtern und der Verwendung der gleichen Logik in Ihrer gesamten Anwendung häufig verwenden müssen. Wenn Ihre Anwendung zu viel gemeinsame Logik hat, wird es eine Menge kleiner Funktionen geben.

In einer Anwendung, in der Sie keine gemeinsame Logik haben, müssen Sie keine kleinen Funktionen ausführen, sondern können Ihren Code in Segmente aufteilen, die für Sie einfacher zu verwalten und zu verstehen sind.

Im Allgemeinen ist die Aufteilung Ihres großen Codes in kleine Funktionen ein sehr guter Ansatz. In modernen Frameworks und Sprachen sind Sie dazu verpflichtet, z

data => initScroll(data)

ist eine anonyme Funktion in ES 2017 JavaScript und Typescript

getMarketSegments() {
 this.marketService.getAllSegments(this.project.id)
  .subscribe(data => this.segments = data, error => console.log(error.toString()));
}

Im obigen Code sehen Sie 3 Funktionsdeklarationen und 2 Funktionsaufrufe. Dies ist ein einfacher Service-Aufruf in Angular 4 mit Typescript. Sie können sich das als Ihre Anforderungen vorstellen

([] 0)
([x] 1)
([x y] 2)

Die oben genannten sind 3 anonyme Funktionen in Clojure Language

(def hello (fn [] "Hello world"))

Das obige ist eine Funktionserklärung in Clojure

Also ja FUNKTIONEN können so kleiner sein aber ob es gut oder schlecht ist wenn du Funktionen hast wie:

incrementNumber(numb) { return ++numb; }

Das ist keine gute Vorgehensweise, aber wenn Sie diese Funktion in einem HTML-Tag verwenden, wie wir es in Angular Framework tun, wenn Increment oder Decrement in Angular HTML-Vorlagen nicht unterstützt werden, wäre dies die Lösung für mich.

Nehmen wir ein anderes Beispiel

insertInArray(array, newKey) {
 if (!array.includes(newKey)) {
   array.push(newKey);
 }
}

Das obige Beispiel ist ein Muss, wenn Arrays in Angular HTML-Vorlagen abgespielt werden. Manchmal müssen Sie also kleine Funktionen erstellen

Anwaar Ulhaq
quelle
-2

Ich bin damit nicht einverstanden, dass zu diesem Zeitpunkt fast eine Antwort gegeben wird.

Kürzlich habe ich einen Kollegen gefunden, der alle Klassenmitglieder wie folgt schreibt:

 void setProperty(int value){ mValue=value; }
 int getProperty() const { return (mValue); }

Dies könnte in sporadischen Fällen ein guter Code sein, aber sicherlich nicht, wenn Sie viele Klassen mit vielen und vielen Eigenschaften definieren. Ich möchte damit nicht sagen, dass Methoden wie die oben genannten nicht geschrieben werden sollen. Wenn Sie jedoch den größten Teil des Codes als "Wrapper" der realen Logik schreiben, stimmt etwas nicht.

Wahrscheinlich vermisst der Programmierer die Gesamtlogik, hat Angst vor zukünftigen Änderungen und vor der Überarbeitung des Codes.

Die Definition der Schnittstelle beruht auf einem tatsächlichen Bedarf. in der Tat, wenn Sie eine einfache Eigenschaft setzen und erhalten müssen (ohne viel Logik, die das Mitglied kürzer macht), ist es möglich. Aber wenn der tatsächliche Bedarf auf andere Weise analysiert werden könnte, warum nicht eine intuitivere Benutzeroberfläche definieren?

Um die Frage wirklich zu beantworten, ist es natürlich nein, und der Grund liegt auf der Hand: Die Methode / Eigenschaft / Whatelse muss für das definiert werden, was sie benötigt. Auch eine leere virtuelle Funktion hat einen Grund zu existieren.

Luca
quelle
6
Es gibt einen guten Grund, Accessor / Mutator-Methoden hinzuzufügen, auf die Sie unter "Angst vor der Zukunft ... Refactoring" hinweisen. Aber Sie haben auch Recht, dass es dem Code keinen Mehrwert verleiht. Weder durch Verkleinern (lokal oder global) noch durch Erhöhen der Lesbarkeit. In meinen Augen spricht dies für ein schlechtes Sprachdesign sowohl in Java als auch in der JavaBeans-Konvention. Dies ist ein (von vielen) Bereichen, in denen C # die Sprache erfolgreich verbessert hat, um beide Probleme mit der automatischen Eigenschaftensyntax zu lösen . Als Java - Programmierer, ich stimme mit rohem Stil für die grundlegende Struktur-ähnliche Klassen.
Anm
1
Getter / Setter-Funktionen sind gut, auch wenn sie im Moment nur eine Variable lesen oder schreiben. In der Praxis können Sie sich ein Szenario vorstellen, in dem Sie später entscheiden, bei jeder Änderung des Felds einen Wert auf den Bildschirm zu drucken oder zu überprüfen, ob dieser Wert gültig ist oder nicht. (Vielleicht ist es ein Nenner für einen Bruchteil, und Sie möchten überprüfen, ob es nicht Null ist.)
Rei Miyasaka
2
Getter und Setter sind schrecklich, ungeachtet ihrer gültigen Verwendung. Wenn es notwendig ist, sie zu benutzen, halte ich es für einen Sprachfehler.
Carson Myers
@Rei: Warum muss eine externe Klasse den Wert der Nenner überprüfen? Dies sollte durch die Funktion divide () der Klasse Fraction erfolgen, oder die Klasse Fraction sollte ein isDivisible () bereitstellen, um auf NULL-Nenner zu prüfen. Benötigte Getter / Setter sind normalerweise ein Code-Geruch, der eine hohe Kopplung und / oder eine geringe Kohäsion (dh eine schlechte) Ihrer Klasse aufweist.
Lie Ryan
@Lie Was? Ich habe nie gesagt, dass eine externe Klasse verwendet werden sollte, um Nenner zu überprüfen. Ich sage, dass eine externe Klasse aus Versehen einen Nenner auf 0 setzen könnte. Der Zweck der Gültigkeitsprüfung bei den Setzern besteht darin, zu ermutigen, Fehler im Verbrauchercode früher zu finden. Das Bereitstellen einer isDivisible () - Funktion, die möglicherweise aufgerufen wird oder auch nicht, funktioniert zu diesem Zweck ebenfalls nicht. Und wie genau deutet der Bedarf an Gettern / Setzern auf eine hohe Kopplung hin?
Rei Miyasaka