Gibt es objektive, unterstützbare Argumente für das Software-Engineering für oder gegen das Ändern der Werte von By-Value-Parametern im Hauptteil einer Funktion?
Ein wiederkehrender Spucke (meistens mit viel Spaß) in meinem Team ist, ob die vom Wert übergebenen Parameter geändert werden sollen oder nicht. Einige Mitglieder des Teams sind fest davon überzeugt, dass niemals Parameter zugewiesen werden sollten, damit der ursprünglich an die Funktion übergebene Wert immer abgefragt werden kann. Ich bin anderer Meinung und bin der Meinung, dass Parameter nichts anderes als lokale Variablen sind, die durch die Syntax des Aufrufs der Methode initialisiert werden. Wenn der ursprüngliche Wert eines By-Value-Parameters wichtig ist, kann eine lokale Variable deklariert werden, um diesen Wert explizit zu speichern. Ich bin nicht zuversichtlich, dass einer von uns seine Position sehr gut unterstützt.
Ist dies ein nicht lösbarer religiöser Konflikt oder gibt es gute, objektive Gründe für das Software-Engineering in beide Richtungen?
Hinweis: Die Grundsatzfrage bleibt unabhängig von den Implementierungsdetails der jeweiligen Sprache. In JavaScript beispielsweise, wo die Argumentliste immer dynamisch ist, können Parameter als syntaktischer Zucker für die Initialisierung lokaler Variablen aus dem arguments
Objekt betrachtet werden. Trotzdem könnte man von Parametern deklarierte Bezeichner als "speziell" behandeln, da sie immer noch die Weitergabe von Informationen vom Anrufer an den Angerufenen erfassen.
quelle
Antworten:
Ich nehme eine dritte Position ein: Parameter sind wie lokale Variablen: Beide sollten standardmäßig als unveränderlich behandelt werden. Variablen werden also einmal zugewiesen und dann nur gelesen, nicht geändert. Bei Schleifen ist
for each (x in ...)
die Variable im Kontext jeder Iteration unveränderlich. Die Gründe dafür sind:Angesichts einer Methode mit einer Reihe von Variablen, die zugewiesen werden und sich dann nicht ändern, kann ich mich auf das Lesen des Codes konzentrieren, anstatt zu versuchen, den aktuellen Wert jeder dieser Variablen zu speichern.
Angesichts der gleichen Methode, diesmal mit weniger Variablen, die sich jedoch ständig ändern, muss ich mich jetzt an den aktuellen Status dieser Variablen erinnern und daran arbeiten, was der Code tut.
Nach meiner Erfahrung ist Ersteres für mein armes Gehirn weitaus einfacher. Andere, klügere Leute als ich haben dieses Problem vielleicht nicht, aber es hilft mir.
Was den anderen Punkt betrifft:
gegen
Erfundene Beispiele, aber meiner Meinung nach ist es aufgrund der Variablennamen viel klarer, was im zweiten Beispiel vor sich geht: Sie vermitteln dem Leser weit mehr Informationen als diese Masse
r
im ersten Beispiel.quelle
for
Schleifen mit unveränderlichen Variablen auszuführen . Das Einkapseln der Variablen in die Funktion reicht Ihnen nicht aus? Wenn Sie Probleme haben, Ihren Variablen in einer bloßen Funktion zu folgen, sind Ihre Funktionen möglicherweise zu lang.for (const auto thing : things)
ist eine for-Schleife, und die eingeführte Variable ist (lokal) unveränderlich.for i, thing in enumerate(things):
mutiert auch keine EinheimischenDas ist eine Sache, die ich an (gut geschriebenem) C ++ wirklich mag: Sie können sehen, was Sie erwartet.
const string& x1
ist eine konstante Referenz,string x2
ist eine Kopie undconst string x3
ist eine konstante Kopie. Ich weiß, was in der Funktion passieren wird.x2
wird geändert, denn wenn es nicht wäre, gäbe es keinen Grund, es nicht konstant zu machen.Wenn Sie also eine Sprache haben, die dies zulässt , erklären Sie, was Sie mit den Parametern tun möchten. Das sollte die beste Wahl für alle Beteiligten sein.
Wenn Ihre Sprache dies nicht zulässt, gibt es leider keine Silberkugel-Lösung. Beides ist möglich. Die einzige Richtlinie ist das Prinzip der geringsten Überraschung. Nehmen Sie einen Ansatz und gehen Sie damit durch Ihre gesamte Codebasis, mischen Sie ihn nicht.
quelle
int f(const T x)
und sie unterscheidenint f(T x)
sich nur im Funktionskörper.const int x
nur um x klar zu machen, wird im Inneren nicht geändert? Sieht für mich nach einem sehr seltsamen Stil aus.const
aus der Parameterliste entfernen, wenn er dies behindert. Ich denke also nicht, dass dies die Frage beantwortet.Ja, es ist ein "religiöser Konflikt", außer dass Gott keine Programme liest (soweit ich weiß), also wird er zu einem Lesbarkeitskonflikt herabgestuft, der eine Frage des persönlichen Urteils wird. Und ich habe es auf jeden Fall getan und gesehen, in beide Richtungen. Beispielsweise,
Nur wegen des Argumentnamens t0 würde ich mich hier wahrscheinlich dafür entscheiden, seinen Wert nicht zu ändern. Nehmen wir stattdessen an, wir haben diesen Argumentnamen lediglich in tNow oder so ähnlich geändert . Dann hatte ich höchstwahrscheinlich eine lokale Kopie vergessen und einfach tNow + = dt; für diese letzte Aussage.
Angenommen, ich wusste, dass der Client, für den das Programm geschrieben wurde, einige neue Programmierer mit sehr wenig Erfahrung einstellen wird, die diesen Code lesen und daran arbeiten würden. Dann würde ich mir wahrscheinlich Sorgen machen, sie mit Pass-by-Value versus -reference zu verwechseln, während ihre Gedanken zu 100% damit beschäftigt sind, die gesamte Geschäftslogik zu verdauen. In einem solchen Fall würde ich immer eine lokale Kopie eines Arguments deklarieren, das geändert wird, unabhängig davon, ob es für mich mehr oder weniger lesbar ist oder nicht.
Antworten auf diese Art von Stilfragen tauchen mit Erfahrung auf und haben selten eine kanonische religiöse Antwort. Jeder, der glaubt, es gäbe nur eine Antwort (und dass er es weiß :), braucht wahrscheinlich mehr Erfahrung.
quelle