Ist Lesbarkeit ein triftiger Grund, const nicht in (Referenz-) Parametern zu verwenden?

24

Beim Schreiben einiger Funktionen habe ich in Parametern wie diesen ein const-Schlüsselwort gefunden:

void MyClass::myFunction(const MyObject& obj,const string& s1,const string& s2,const string& s3){
}

verursacht in IDE oder vim häufig das Teilen einer Zeile in zwei Zeilen. Daher möchte ich alle const-Schlüsselwörter in den Parametern entfernen:

void MyClass::myFunction(MyObject& obj,string& s1,string& s2,string& s3){
} 

ist das ein triftiger grund, const nicht zu verwenden? Ist es wartbar, die Parameterobjekte manuell unverändert zu lassen?

ggrr
quelle
110
"Hey, ich möchte mein Programm funktional ändern", um es lesbarer zu machen, ist ein schlechter Grund.
Pieter B
37
Das Programm wird ohnehin nicht mehr lesbar - Sobald Sie sehen, dass etwas übergeben wird const, haben Sie einen starken Hinweis darauf, dass Sie sich nicht darum kümmern müssen, wie es in der Funktion geändert werden könnte.
Tofro
43
Eine bessere Möglichkeit, die Lesbarkeit zu verbessern, besteht darin , die Anzahl der Argumente zu verringern .
5gon12eder
15
'const' verbessert wohl die Lesbarkeit. Diese Aussage macht deutlich, dass sich obj nicht ändern darf!
Charles
14
Zur besseren Lesbarkeit sollte nach jedem Komma ein Leerzeichen eingefügt werden.
Sam Hocevar

Antworten:

182

Die Lesbarkeit ist ein wichtiger Grund, um die Verwendung von Leerzeichen zu erlernen:

void MyClass::myFunction(
        const MyObject& obj,
        const string& s1,
        const string& s2,
        const string& s3
) {
    return;
}

Dort werden die Parameter nicht mit dem Funktionsumfang verwechselt. Wenn Sie sie in einer anderen Zeile suchen, müssen Sie sie nicht neu positionieren, wenn Sie den Namen myFunctionin einen aussagekräftigeren Namen ändern . Die Position der Parameter nicht zu ändern, wenn sie nicht geändert wurden, ist etwas, das Benutzer von Versionsverwaltungs-Diff-Tools zu schätzen wissen.

constbedeutet etwas. Wirf es nicht raus, nur weil dir der Raum und die Ideen ausgehen. Lesbarkeit ist das A und O, aber Dinge in ihrem Namen zu brechen, gibt einfach auf.

kandierte_orange
quelle
6
"Sie müssen sie nicht neu positionieren, wenn Sie den Namen von myFunction ändern" - obwohl es in diesem Fall so aussieht, als ob sie ungefähr an der Öffnung ausgerichtet sind (, und wenn dies der Fall ist, müssen Sie sie möglicherweise neu positionieren sie, wenn sich die Länge des Klasse + Funktionsnamens um mehr als ungefähr 4 Zeichen ändert. Wenn Sie dies nicht tun müssen, fügen Sie eine feste Anzahl von Einrückungsstufen hinzu, nicht eine Zahl, die von der Länge des Funktionsnamens abhängt. Ich würde 1 Stufe empfehlen, diese Antwort verwendet 6, aber jede feste Zahl erreicht das angegebene Ziel :-)
Steve Jessop
6
@CandiedOrange Ich bin überrascht, dass Sie in dieser Antwort nicht "Form 6" verwendet haben ... es ist eindeutig weniger hässlich!
Svidgen
6
Bilden Sie 6 für den Gewinn. Ein Tabulator für eine Einrückungsebene. Einfach und effektiv. Problem gelöst :)
Leichtigkeit Rennen mit Monica
2
Ok ok Form 6 ist es. Dies ist die Variante, die JeffGrigg auf c2 erwähnt hat.
candied_orange
4
@ random832 Ich denke, wir sind jetzt fest im Gebiet des Fahrradschuppens. Hier ist die richtige Lösung: Durchsuchen Sie Ihre Codebasis nach Beispielen, konsultieren Sie Ihren Shop-Styleguide, fragen Sie die Entwickler in Ihrem Shop, und verwenden Sie diese Option, wenn sich daraus keine verbindliche Antwort ergibt. Lösen Sie Streitigkeiten, die mit einem Viertel in beide Richtungen verlaufen könnten. Sobald das Quartal gesprochen hat, sei konsequent!
candied_orange
52

Tatsächlich geht das Problem der Lesbarkeit definitiv in die andere Richtung. Erstens können Sie Ihre Run-On-Linie mithilfe von Leerzeichen trivial lösen . Durch das Entfernen constwird die Zeile jedoch nicht nur kürzer, sondern die Bedeutung des Programms wird vollständig geändert.

Herb Sutter bezeichnet den constin Bezug auf constals den wichtigsten,const weil ein Verweis constauf eine vorübergehende binden und seine Lebensdauer verlängern kann. Für einen Wertverweis auf non- constcannot benötigen Sie eine separate Variable.

void foo_const(std::string const& );
void foo_nc(std::string& );

std::string some_getter();

foo_const(some_getter());      // OK
foo_const("Hello there"); // OK

foo_nc(some_getter()); // error
foo_nc("Nope");   // error

std::string x = some_getter(); // have to do this
foo_nc(x);                     // ok
std::string msg = "Really??";  // and this
foo_nc(msg);                   // ok

Für die Benutzerfreundlichkeit bedeutet dies, dass Sie alle diese temporären Variablen einführen müssen, um Ihre Funktion aufrufen zu können. Das ist für die Lesbarkeit nicht besonders gut, da diese Variablen bedeutungslos sind und nur existieren, weil Ihre Signatur falsch ist.

Barry
quelle
6
Ihr zweiter Absatz gibt mir Kopfschmerzen beim Versuch herauszufinden, ob constes sich um consteinen anderen handelt constund was constin der Tat der wichtigste istconst
Mindwin
3
@ Mindwin Ich denke, die Ironie ist, dass mein zweiter Absatz klar und eindeutig ist, und ich habe keine Ahnung, wovon du sprichst.
Barry
2
@Barry Es ist sicherlich eindeutig, aber ich habe diesen Absatz ein paar Mal gelesen, um herauszufinden, was es bedeutete. Ich denke, ein Problem ist, dass es analysiert werden kann: "Herb Sutter bezeichnet die Konstante (in Bezug auf Konstante) als die wichtigste Konstante ..." oder "Herb Sutter bezeichnet die Konstante in (in Bezug auf Konstante) als die am häufigsten verwendete Konstante." important const ... "Ich glaube, letzteres ist die einzig gültige Gruppierung der Wörter, aber es braucht ein bisschen, um sie zu verarbeiten. Vielleicht gibt es eine Möglichkeit, Anführungszeichen zu verwenden, um die Mehrdeutigkeit zu beseitigen?
Cort Ammon - Reinstate Monica
1
Ich denke, einige mit Bindestrich versehene Verbindungen würden das klären.
Shawnt00
2
oder speziell verwenden, const&anstatt dort als constNomen (-phrase) zu
verweisen
21

Einfache Antwort ist "nein".

Die lange Antwort lautet, dass das constSchlüsselwort Teil des Vertrags ist, den die Funktion anbietet. es sagt Ihnen, dass das Argument nicht geändert wird. In dem Moment, in dem Sie die constGarantie entfernen , erlischt das Fenster. Denken Sie daran , dass Sie die Konstantheit vernünftigerweise nicht halten können (oder jede andere Eigenschaft) von etwas mit Dokumentation, Konventionen oder Richtlinien - wenn die Konstantheit nicht durch den Compiler erzwungen wird, jemand wird denken , dass sie ihre Arbeit erleichtern können , wenn sie Geige mit der Parameter "nur ein bisschen". Erwägen:

// parameter "foo" is not modified
void fna(Foo& foo);

void fnb(const Foo& foo);

Abgesehen von der Tatsache, dass die letztere Version prägnanter ist, bietet sie auch einen stärkeren Vertrag und lässt den Compiler Ihnen helfen, Ihre Absichten aufrechtzuerhalten. Ersteres hindert die fna(Foo&)Funktion nicht daran, den übergebenen Parameter zu ändern.

Wie in @CandiedOrange answer können Sie den Code mit Leerzeichen auslegen und die Lesbarkeit verbessern.

Mael
quelle
14

Durch das Entfernen des constSchlüsselworts wird die Lesbarkeit beeinträchtigt, da constInformationen an den Reader und den Compiler übermittelt werden.
Die horizontale Länge des Codes zu reduzieren ist gut (niemand mag es, seitwärts zu scrollen), aber es gibt mehr constals nur Text. Sie könnten es umschreiben:

typedef string str;
typedef MyObject MObj;
void MyClass::myFunction(const MObj& o,const str& s1,const str& s2,const str& s3)

Das ändert den Vertrag nicht, erfüllt aber die Notwendigkeit, die Leitungslänge zu reduzieren. Wahrlich, ich würde das obige Snippet als weniger lesbar betrachten und mich dafür entscheiden, mehr Leerzeichen zu verwenden, wie bereits in CandiedOranges Antwort erwähnt.

constist eine Funktionalität des Codes selbst. Sie würden die Funktion nicht als Nichtmitglied festlegen, um den MyClass::Abschnitt der Deklaration zu entfernen. Entfernen Sie also nicht dieconst

Erdrik Ironrose
quelle
4
Ich stimme zu, dass das von Ihnen bereitgestellte Snippet weniger lesbar ist. Es zwingt den Leser herauszufinden, was MObjund was stres ist, und zieht mit Sicherheit die Augenbrauen hoch. Es ist besonders seltsam für Arten , deren Namen Sie bereits Kontrolle über: ZB Warum haben Sie nicht nur Namen MyObjectwie MObjzu beginnen?
Jason C
3

Ist Lesbarkeit ein triftiger Grund, const nicht in Parametern zu verwenden?

Nein. Das Weglassen constkann die Funktionalität ändern, den Schutz verlieren constund möglicherweise weniger effizienten Code erstellen.

Ist es wartbar, die Parameterobjekte manuell unverändert zu lassen?

Anstatt Zeit damit zu verbringen, Code manuell zu formatieren

void MyClass::myFunction(const MyObject& obj,const string& s1,const string& s2,const string& s3){
  //
}

Verwenden Sie automatische Formatierungswerkzeuge . Schreiben Sie die Funktion gemäß den funktionalen Anforderungen und lassen Sie die Präsentation automatisch formatieren. Das manuelle Anpassen der Formatierung ist nicht so effizient wie das Verwenden der automatischen Formatierung und das Verwenden der gespeicherten Zeit, um andere Aspekte des Codes zu verbessern.

void MyClass::myFunction(const MyObject& obj, const string& s1, const string& s2, 
    const string& s3) {
  // 
}
chux - Setzen Sie Monica wieder ein
quelle
-1

So lange wie möglich ist es besser, const sichtbar zu halten. Es verbessert die Codewartung erheblich (es ist kein Rätselraten, ob diese Methode meine Argumente ändert).

Wenn eine Methode viele Argumente enthält, muss ich über die Erstellung eines projektbasierten Jarons (Matrix, Employee, Rectangle, Account) nachdenken, der viel kürzer und verständlicher ist (wodurch eine lange Liste von Argumenten für Methoden entfällt).

Schwarzer Stift
quelle
Einverstanden. Ich habe gezögert, darauf hinzuweisen. Also "Extremfall".
Blackpen
@cmaster Das heißt, manchmal in bestimmten Kontexten, mit bestimmten Programmierern, könnte es lesbar bleiben. Zum Beispiel, in dem sehr speziellen Fall eines Programms hüfthoch in Windows - API - Aufrufen, mit einem Leser, der zu dieser Umgebung verwendet wird, Sachen wie zB typedef Point * LPPOINTund typedef const Point * LPCPOINT, während Super widerwärtig, trägt immer noch eine implizite Bedeutung, weil es mit sofortigen Erwartungen konsistent ist im Zusammenhang. Aber niemals im allgemeinen Fall; Es ist nur eine seltsame Ausnahme, die ich mir vorstellen kann.
Jason C
1
Ja, als ich die Frage sah, kam mir "const unsigned long long int" in den Sinn, aber es ist kein guter Kandidat, Nutzen daraus zu ziehen, entweder "const" oder "reference" zu sein. Das typedef löst das allgemeine Problem der Abkürzung von Namen. aber es fühlt sich nicht nach gutem Design an, den eigentlichen Zweck von Sprachkonstrukten (wie "const") dahinter zu verbergen.
Blackpen