Kommentierter kurzer schicker Code vs. unkommentierter längerer einfach zu verstehender Code - was ist zu bevorzugen?

18

Manchmal kann ein Algorithmus auf zwei Arten geschrieben werden:

  • Der kurze, schicke Weg; oder
  • Der längere, leicht verständliche Weg.

Zum Beispiel, hier ist ein längerer, einfacher Weg , um eine Zeichenfolge zu kopieren , sourceum destin C:

*dest = *source;
while (*source != '\0') {
    source++;
    dest++;
    *dest = *source;
} (true);

Und hier ist ein kurzer, ausgefallener Weg.

// Copy string source to dest
while (*dest++ = *source++);

Ich habe immer gehört und gelesen, dass ausgefallener Code vermieden werden sollte, und ich stimme eher zu. Was aber, wenn wir Kommentare berücksichtigen? Angenommen, wir haben wie in den obigen Beispielen einen unkommentierten, längeren und angeblich leichter verständlichen Code und einen gut kommentierten, kurzen, ausgefallenen Code? Wird der unkonventionelle Code weiterhin bevorzugt?

BEARBEITEN: Viele haben Variablennamen kommentiert, deshalb habe ich den Beispielcode geändert, um dies nicht zu einem Faktor zu machen, wenn Sie den anderen vorziehen. Ich habe versucht, die doppelte Zuweisung im ersten Beispiel zu entfernen, aber das hat den Code nur weniger lesbar gemacht.

Vielleicht war dies nicht das beste Beispiel, weil viele den "ausgefallenen" Code lesbarer und verständlicher finden als den längeren Code. Die Idee war, einen längeren Code zu haben, der viel einfacher zu verstehen war als ein sehr kurzer, aber komplizierter Code.

EDIT2: Hier ist ein neues Beispiel, das ich von SO bekommen habe :

Kommentierte Fantasieversion:

//direct formula for xoring all numbers from 1 to N
int Sum = (N & (N % 2 ? 0 : ~0) | ( ((N & 2)>>1) ^ (N & 1) ) );

Nicht kommentierte Langfassung:

int Sum = 0;
for (int i = 1; i < N; ++i)
{
   Sum ^= i; //or Sum = Sum ^ i;
}
gablin
quelle
2
@gablin: "gut" ist ein Wort, aber es ist ein Adjektiv mit einer etwas anderen Bedeutung als "gut" und wird nicht mehr häufig verwendet (zumindest in den USA). Die Adverbform von "gut" ist "gut". wie im "gut kommentierten Code".
John M Gant
@ John: Ah ja, natürlich. Ich habe die Frage entsprechend aktualisiert. Vielen Dank.
Gablin
2
Inwiefern ist der kurze Weg "schick"? Das ist ein Lehrbuch-Teil des C-Codes, den jeder, der behauptet, C zu kennen, problemlos lesen kann. Knappheit bedeutet nicht "Phantasie".
JBRWilkinson
@ JBRWilkinson: Wie ich im modifizierten Teil der Frage sagte, ist dieses Beispiel nicht gut, da die "schicke" Version anscheinend nicht besonders schick ist. Ziel war es, einen kurzen, aber nicht verständlichen Weg mit Kommentar und dann einen längeren, aber viel besser lesbaren Weg ohne Kommentar zu finden.
Gablin
@gablin: Deine Bearbeitung gefährdet die aktuellen Antworten.
Maniero

Antworten:

28

Im Allgemeinen würde ich es vorziehen, den ausgefallenen Code in eine eigene Methode zu extrahieren.

Anstatt den ausgefallenen Code zu kommentieren, sollte sein Methodenname alles sein, was er braucht, um die Dinge klar zu machen.

char *copy_string(char *s, const char *t) {    
    while (*s++ = *t++); 
    return s;
}
Mongus Pong
quelle
3
Großartiger Punkt. Das Ausklammern von in sich geschlossenem Code ist weitaus besser als das Ausklammern von Kommentaren. Der Compiler weiß, wie er bei Bedarf eingebunden wird.
dbkk
Ah ja, das ist eine großartige Möglichkeit, den Kommentar überflüssig zu machen. Aber würden Sie trotzdem immer den ausgefallenen Code dem längeren Code vorziehen?
Gablin
Im Allgemeinen ja. Ich bin der Meinung, dass kurze, gut benannte Methoden das Lesen und Verwalten von Code erleichtern. Komplexität, die in ihre eigenen Methoden einbezogen wird, macht die Wiederverwendung zugänglicher und offensichtlicher. Es gibt immer Ausnahmen, letztendlich kommt es immer auf den Code an.
Mongus Pong
Sicherlich sollte Ihre Funktion "strcpy" heißen?
JBRWilkinson
Dieser Code enthält einen Fehler. Was wird zurückgegeben? Was sollte zurückgegeben werden? Machen Sie es einfach eine leere Methode und damit fertig sein;)
Christian Mann
10

Ich bin alles für die längere Version. Das Problem mit der Kurzversion des Codes, abgesehen davon, dass es für einige Programmierer schwieriger ist, sie zu lesen, ist, dass es die meiste Zeit schwieriger ist, Fehler zu erkennen, wenn man sie nur ansieht.

Ich habe ein echtes Beispiel. In unserem Produkt hatten wir den folgenden Codeausschnitt:

if (++someCounter < MAX_VALUE) {
    // Do something that has to be done only MAX_VALUE times
}

Dieser Code sieht auf den ersten Blick völlig in Ordnung aus, aber nach einer langen Zeit läuft dieser Zähler über und bricht den Zustand (im realen Szenario haben wir das Produktionssystem unseres Kunden mit einem OOM zerstört). Dieser Code ist etwas weniger "raffiniert", aber es ist klar, dass er das tut, was er tun soll:

if (someCounter < MAX_VALUE) {
    ++someCounter;
    // Do whatever it is we came here for
}

Und Sie können sagen, dass der Entwickler, der diesen Code geschrieben hat, einfach nicht gut genug war (was nicht wahr ist, er war ein ziemlich kluger Kerl), aber ich denke, wenn Ihre Codierungstechnik erfordert, dass Sie überdurchschnittlich gut darin sind, GOTT zu programmieren Um Ihren Code richtig zu machen, machen Sie etwas falsch. Ihr Code sollte für Sie so narrensicher wie möglich sein und für alle, die diesen Code nach Ihnen pflegen müssen (die möglicherweise nicht so schlau sind wie Sie).

Also - ich bin alles für Einfachheit und Klarheit.

Edit: Oh, und zu Kommentaren - das macht nichts. Viele Leute werden sowieso keine Kommentare lesen ( http://www.javaspecialists.co.za/archive/Issue039.html ) und diejenigen, die Ihren Code ohne Kommentare nicht verstehen, werden es mit ihnen nicht gut genug verstehen, so dass sie kann es pflegen. Das Ziel ist es, den Leuten zu zeigen , dass bestimmter Code "korrekt" ist. Kommentare können dabei nicht helfen.

Hila
quelle
1
"zermalmt Produktionssystem unseres Kunden" - das ist ziemlich schlimm: -S
"Das Problem mit der Kurzversion des Codes, abgesehen davon, dass es für einige Programmierer schwieriger ist, ihn zu lesen" - jeder Code kann "für einige Programmierer" schwer zu lesen sein. Sie müssen nur dumm genug Programmierer finden. Den Code nicht auf den kleinsten Nenner bringen.
quant_dev
@quant_dev: Umgekehrt: "Das Debuggen ist doppelt so schwierig wie das Schreiben des Codes. Wenn Sie den Code also so geschickt wie möglich schreiben, sind Sie per Definition nicht schlau genug, um ihn zu debuggen." - Brian W. Kernighan
Michael Borgwardt
@MichaelBorgwardt Ich würde Kernighans Spruch nicht blind auf jede mögliche Situation anwenden. Das OPs-Beispiel ist eine Funktion, die "so geschickt wie möglich" (oder in der Nähe davon) geschrieben wurde, und dennoch sollte es ziemlich einfach zu debuggen sein, wenn ein Debugging erforderlich ist. Auf der anderen Seite können komplizierte Bit-Twiddling-Oneliners sehr clever sein, werden aber mit Sicherheit noch schwieriger zu debuggen sein. (Auch: Kernighan geht davon aus, dass Codierungsfähigkeiten = Debugging-Fähigkeiten sind.
Dies
6

Ich würde generell die längere Version vorziehen. Zwei Hauptgründe fallen mir ein:

  • Es ist wahrscheinlich, dass mehr Leute es mit weniger Aufwand verstehen (vorausgesetzt, es ist kein solches "Standard" -Beispiel wie diese String-Kopie).
  • Es ist möglich, einzelne Anweisungen mit Haltepunkten zu versehen und mit einem Debugger durchzugehen.

Um das Beste aus beiden Welten zu erreichen, wickeln Sie den Code in eine Funktion ein, deren Name den Kommentar für Sie übernimmt:

void copy_string(char *s, char *t)
{
    *s = *t;
    while (*t != '\0') {
        t++;
        s++;
        *s = *t;
    }
}

Der einzige Grund, dies nicht zu tun, wäre, wenn die Leistung ein Problem wäre und die Profilerstellung tatsächlich einen signifikanten Funktionsaufwand aufwies.

Paul Stephenson
quelle
1
Ist das nicht was Inline ist?
Antsan
In der Tat, obwohl Inlining mit seinen eigenen Problemen einhergeht, wie zum Beispiel den Funktionskörper in Header-Dateien verfügbar zu machen. Sind moderne Compiler, die Inline-Inhalte für Sie erstellen, nicht automatisch sinnvoll?
Paul Stephenson
4

Was immer am klarsten ist. Oft handelt es sich um ein kompaktes, leicht verständliches Codefragment, das keinen Kommentar erfordert ... wie Ihr zweites Beispiel.

Im Allgemeinen sind kürzere Code-Schnipsel leichter zu verstehen, da der Leser immer weniger im Kopf behalten kann. Offensichtlich gibt es eine Grenze, wenn der Code übermäßig verschleiert wird, und ich meine nicht, dass der die Klarheit verbessernde weiße Raum beschnitten werden sollte.

In Kommentaren sollte niemals etwas angegeben werden, das aus dem Code hervorgeht, sodass der Leser das Gleiche nur zweimal liest. Für mich bedarf der erste Ausschnitt der Klärung. Warum hat der Entwickler keine do...whileSchleife verwendet, um das Duplikat der *s = *t;Zuweisung zu entfernen ? Ich muss mehr Code analysieren, um zu erkennen, dass es sich um eine String-Kopie handelt. Ein Kommentar zu diesem längeren Code wäre hilfreicher als zu dem kürzeren Code.

Der Kommentar zum zweiten Snippet ist fast überflüssig, da die while-Schleife praktisch idiomatisch ist, aber er sagt, was der Code auf einer höheren Ebene tut als der Code selbst, was ihn zu einem nützlichen Kommentar macht.

CB Bailey
quelle
Der Entwickler (ich) hat nicht do ... whileeinfach verwendet, weil ich nicht daran gedacht habe, als ich die Frage schrieb. Vielen Dank für den Hinweis. ^^ Das zweite Snippet mag dir klar sein, aber es ist bestimmt nichts für mich.
Gablin
4

Das Problem ist, dass es keine klare Definition gibt, short fancy codeda dies sehr stark vom Level des Programmierers abhängt. Während manche Menschen kein Problem damit haben, einen while(*s++ = *t++);Ausdruck zu verstehen , werden es andere tun.

Persönlich finde ich das while(*s++ = *t++);perfekt lesbare und das längere schwieriger zu lesen. Andere könnten jedoch nicht zustimmen.

Unabhängig davon ist es nur eine Frage des gesunden Menschenverstands. Lesbarkeit sollte definitiv Priorität haben, aber es gibt einen Punkt, an dem längerer Code weniger lesbar wird, wenn er länger wird. Ausführlichkeit verringert häufig die Lesbarkeit nach meinen Erfahrungen.

Wolph
quelle
Es macht mich traurig, dass ein Thema vieler dieser Antworten lautet: "Entwickler erkennen möglicherweise nicht die Standardmethode zum Schreiben von strcpy () in C"
AShelly,
Es sollte nicht - es bedeutet nicht, dass es keine guten Programmierer mehr gibt, sondern vielmehr, dass a) wir C nicht mehr viel beibringen und b) dass die Stärke von C auch seine Schwäche ist - in dem Moment, in dem sich diese Schleife befindet Verständlich für jemanden, der in C geübt hat, ist es auch ziemlich geheimnisvoll und in einer Welt, die sich bemüht, sicheren Code zu schreiben, der ziemlich beängstigend ist für das, was man in C
Murph
Wir stehen also vor einer weiteren Herausforderung für unsere täglichen Aufgaben. Wir müssen das allgemeine Sprachverständnis unserer direkten Kollegen erraten, damit unsere Codeüberprüfungen konstruktiv bleiben. Nicht in Schlachten zu geraten, ist der "richtige", klarere Ausdruck von Absicht.
Frogstarr78
2

Ich muss den meisten anderen Antworten hier nicht zustimmen - ich denke (zumindest in diesem Fall), dass der kürzere Code besser ist. Entgegen Ihrer Behauptung ist der längere Code zumindest für einen Leser nicht "einfacher". Wenn überhaupt, haben Sie anscheinend keine Lust mehr, den Code zu verlängern, obwohl dies das Verständnis des Codes erschwert und / oder die Sicherheit gibt, dass er korrekt funktioniert.

Insbesondere wenn die Zuweisung des ersten Bytes der Zeichenfolge außerhalb der Schleife von der Zuweisung für die anderen Bytes getrennt ist, muss beim Lesen viel sorgfältiger vorgegangen werden, um sicherzustellen, dass alle Bytes korrekt kopiert werden. Die grundlegende Abfolge der Aktionen in der kürzeren Version ist viel einfacher zu überprüfen. Das einzige wirkliche Problem liegt in der Formatierung. Wenn Sie einen absichtlich leeren Schleifenkörper haben, sollten Sie dies klarstellen:

while (*dest++ = *source++)
    ;

oder auch:

while (*dest++ = *source++)
    ; /* no body */

Einige Leute bevorzugen stattdessen die Verwendung von Zahnspangen:

while (*dest++ = *source++)
    {}

Unabhängig von der genauen Formatierung, die Sie bevorzugen, wurden genügend Fehler mit folgenden Dingen gemacht:

if (x>y);
     x = z;

... dass es wichtig ist, sicherzustellen, dass 1) offensichtlich ist, was tatsächlich von einer Flusssteuerung gesteuert wird, und 2) dass der Code in dem Wissen geschrieben wurde , was von ihm gesteuert wird, damit jemand, der ihn liest, keine Zeit damit verschwendet, es zu versuchen um herauszufinden, ob sie gerade einen Fehler gefunden haben.

Jerry Sarg
quelle
Ja, im Nachhinein ist die "schicke" Version wahrscheinlich besser lesbar als die längere Version. Wenn ich mir ein besseres Beispiel vorstellen könnte, würde ich es tun, aber ich kann es im Moment nicht. Aber ich habe mir nicht die Mühe gemacht, es länger zu machen - so würde ich zumindest anfangs eine String-Kopie schreiben. Es ist vielleicht nicht der beste Ansatz, aber er wurde absichtlich nicht länger als nötig gemacht.
Gablin
2
Keep it simple, stupid!

Stellen Sie sicher, dass jeder andere Programmierer verstehen kann, was Ihr Code tut - und noch besser, wenn Sie einen Blick darauf werfen (hier kommen gute Namen und Kommentare zum Tragen).

Fantasievolles Kung-Fu-Drehen und Inline-Assemblieren sind im Namen der (möglicherweise unnötigen und verfrühten) Optimierung großartig, aber selbst wenn Sie den Code, den Sie geschrieben haben, nicht verstehen , als Sie zwei Monate später auf einen Fehler stoßen. Was war der Punkt? Sie werden sich Zeit und Mühe kosten.

In diesen Situationen beziehe ich mich oft auf das Zen von Python . Bestimmtes:

Explicit is better than implicit.
Simple is better than complex.
Humphrey Bogart
quelle
1

Schreiben Sie keinen ausgefallenen Code in Produktionssoftware. Ich weiß, es fühlt sich gut an, das tatsächlich schreiben zu können, und es ist kürzer. Durch das Schreiben von Fancy Code wird der Wert für "WTF / Minute" erheblich erhöht, dh die Qualität verringert.

Alt-Text

Tamás Szelei
quelle
1

Das hängt natürlich ganz von den Umständen ab. Aber im Allgemeinen halte ich dies für eine gute Faustregel:

Das Debuggen ist doppelt so schwierig wie das Schreiben des Codes. Wenn Sie den Code so geschickt wie möglich schreiben, sind Sie per Definition nicht schlau genug, um ihn zu debuggen.

~ Brian Kernighan

violet313
quelle
länger, aber aussagekräftiger, eleganter als das kompaktere KISS - Akronym
ich
0

Meiner Erfahrung nach besteht der größte Gewinn in Bezug auf Short-Fancy-Code eher in der Rekursion als in der Iteration. Es ist auch eines der schwierigsten Dinge, Code auf einen Blick zu verstehen, es sei denn, Sie arbeiten in einer Sprache, in der sowieso alles rekursiv ist. Ich würde es immer noch für die Eleganz und Geschwindigkeit der Entwicklung bevorzugen, aber ich versuche sicherzustellen, dass es detaillierte Kommentare enthält, wenn es für zukünftige Betreuer oder mein zukünftiges Ich undurchsichtig erscheint.

Glenatron
quelle
0

Ich fange an, Kommentaren niemals zu vertrauen. Nur allzu oft werden Kommentare nicht aktualisiert, wenn der Code aktualisiert wird, und sind weitestgehend veraltet oder stellen Regeln von Kunden / Management dar, die nicht mehr relevant sind.

In einigen Fällen stimmen die Kommentare nicht mehr mit dem Code überein, den sie beschreiben.

Wenn ich zwischen kurz / ausgefallen und länger / leichter zu verstehen wählen muss, dann entscheide ich mich immer für Letzteres, es sei denn, es gibt einen wirklich guten Grund.

Steven Evers
quelle
0

Lesbarkeit und Wartbarkeit sind der Schlüssel, und Ihr zweites Beispiel (dh das längere) ist viel mehr von beidem. Aber warum beschränken Sie sich auf zwei Möglichkeiten? Auch der längere Code ist zu komplex (IMHO), um nicht weiter notiert zu werden. Ich würde es in eine eigene Methode mit geeignetem Javadoc (oder was auch immer) und einem geeigneten Methodennamen einfügen.

Chris Knight
quelle