Warum wird es als schlechte Praxis angesehen, geschweifte Klammern wegzulassen? [geschlossen]


177

Warum sagt mir jeder, dass das Schreiben von Code wie diesem eine schlechte Praxis ist?

if (foo)
    Bar();

//or

for(int i = 0 i < count; i++)
    Bar(i);

Mein größtes Argument für das Weglassen der geschweiften Klammern ist, dass es manchmal doppelt so viele Zeilen mit ihnen geben kann. Hier ist beispielsweise ein Code zum Zeichnen eines Glow-Effekts für ein Etikett in C #.

using (Brush br = new SolidBrush(Color.FromArgb(15, GlowColor)))
{
    for (int x = 0; x <= GlowAmount; x++)
    {
        for (int y = 0; y <= GlowAmount; y++)
        {
            g.DrawString(Text, this.Font, br, new Point(IconOffset + x, y));
        }
     }
 }
 //versus
using (Brush br = new SolidBrush(Color.FromArgb(15, GlowColor)))
    for (int x = 0; x <= GlowAmount; x++)
        for (int y = 0; y <= GlowAmount; y++)
            g.DrawString(Text, this.Font, br, new Point(IconOffset + x, y));

Sie können auch den zusätzlichen Vorteil einer Verkettung nutzen, usingsohne millionenfach einrücken zu müssen.

using (Graphics g = Graphics.FromImage(bmp))
{
    using (Brush brush = new SolidBrush(backgroundColor))
    {
        using (Pen pen = new Pen(Color.FromArgb(penColor)))
        {
            //do lots of work
        }
    }
 }
//versus
using (Graphics g = Graphics.FromImage(bmp))
using (Brush brush = new SolidBrush(backgroundColor))
using (Pen pen = new Pen(Color.FromArgb(penColor)))
{
    //do lots of work
}

Das häufigste Argument für geschweifte Klammern dreht sich um die Wartungsprogrammierung und die Probleme, die durch das Einfügen von Code zwischen der ursprünglichen if-Anweisung und dem beabsichtigten Ergebnis entstehen würden:

if (foo)
    Bar();
    Biz();

Fragen:

  1. Ist es falsch, die kompaktere Syntax verwenden zu wollen, die die Sprache bietet? Die Leute, die diese Sprachen entwerfen, sind schlau. Ich kann mir nicht vorstellen, dass sie eine Funktion einsetzen würden, deren Verwendung immer schlecht ist.
  2. Sollten wir oder sollten wir nicht Code schreiben, damit der kleinste gemeinsame Nenner ihn verstehen kann und keine Probleme damit hat?
  3. Gibt es ein anderes Argument, das mir fehlt?

6
Ich stimme mit Ihnen ein. Lass sie weg. Zeitraum.
Andrei Rînea

67
WER SORGT FÜR WIE VIELE LINIEN ETWAS IST, IST ES 2010. Monitore sind breit und billig und hochauflösend! Mein Monitor ist 2048 x 1152 und ich habe ZWEI davon! Die Lesbarkeit ist viel wichtiger als das Speichern von 2 vertikalen Linien, wenn Sie leicht subtile Fehler einführen können, die schwer zu finden sind.

51
Monitore sind breit und billig, aber nicht groß und billig. Der vertikale Raum ist knapper als der horizontale Raum.
Adam sagt - Setzen Sie Monica

32
@ AdamRuth Drehen Sie sie zur Seite :)
Zachary Yates

16
Sie vermasseln also nicht wie Apple den SSL-Fehler, der im Februar 2014 gefunden wurde, LOL.
Learnvst

Antworten:


183

Eigentlich war das einzige Mal, dass mich jemals wirklich gebissen hat, als ich debuggte und bar () auskommentierte:

if(foo)
  // bar();
doSomethingElse();

Davon abgesehen neige ich dazu:

if(foo) bar();

Welches kümmert sich um den oben genannten Fall.

BEARBEITEN Vielen Dank für die Klärung der Frage, ich stimme zu, wir sollten keinen Code auf den kleinsten gemeinsamen Nenner schreiben.


31
Das ist natürlich rau, aber ich denke, das größte Problem für Betreuer ist, dass sie eine zweite Zeile hinzufügen und nicht erkennen, dass dies nicht Teil der bedingten Anweisung ist, obwohl es WIRKLICH so aussieht, wie es sein sollte.
danieltalsky

23
Ich mag den Einzeiler-Stil nicht, weil ich immer nach dem Schlaufenkörper unten suche.
Nosredna

18
Ich finde den Einzeiler-Stil eher irritierend als hilfreich, da (insbesondere bei tiefen Verschachtelungen - ugh) die Aussage leicht überlesen werden kann und Verwirrung entstehen kann. Ich verwende solche ifs mit nur einer Anweisung fast ausschließlich für die Eingabevalidierung (dh frühe Rückgabe) oder die Schleifensteuerung (z. B. das Ignorieren irrelevanter Dateinamen in Dateisystemspaziergängen), wobei Leerzeilen helfen, sie vom Hauptcode abzuheben.
Alan Plum

1
Einzeiliger Stil verbirgt auch die Leiste () vor der Testabdeckung. Es wird verdeckt aussehen, auch wenn foo immer falsch ist.
Bohumil Janda

1
Dies ist eine andere Art zu sagen: "Hätte die Quelle die geschweiften Klammern enthalten, hätte ich beim Debuggen keine Zeit verschwendet." - Das Hinzufügen der Zahnspangen ist trivial einfach und vermeidet es, Fallstricke für die nächste Person zu hinterlassen. Das einzige Argument dagegen ist "Lesbarkeit", was ziemlich schwierig ist, da dies ein Fall ist, in dem implizit etwas passiert, wenn Sie es weglassen.
Andrew Theken

156

Lesegeschwindigkeit ...

Abgesehen von dem, was bereits erwähnt wurde. Zu diesem Zeitpunkt war ich bereits darauf konditioniert, if-Anweisungen mit geschweiften Klammern und Leerzeichen zu analysieren. Also las ich:

if (condition)
{
    DoSomething();
}

DoSomethingElse();

Etwas schneller als ich gelesen habe:

if (condition) DoSomething();

DoSomethingElse();

Ich lese es etwas langsamer, wenn es so aussieht:

if (condition) DoSomething();
DoSomethingElse();

Ich habe das deutlich langsamer gelesen als vorher:

if (condition) 
    DoSomething();
DoSomethingElse();

Weil ich nicht anders kann, als es für alle Fälle noch einmal zu lesen und mich zu fragen, ob der Autor es beabsichtigt hat:

if (condition)
{
    DoSomething();
    DoSomethingElse();
}

Im Allgemeinen bereits behandelt, aber wenn es darum geht, das Folgende zu lesen , werde ich mich eine ganze Weile damit befassen, um sicherzustellen, was der Autor beabsichtigt hat. Ich kann sogar den ursprünglichen Autor suchen, um dies zu bestätigen.

if (condition) 
    DoSomething();
    DoSomethingElse();

29
Das Problem ist gelöst, wenn Sie in Ihrem vierten Beispiel einfach eine leere Zeile nach der if-Anweisung einfügen, um sie von DoSomethingElse () zu trennen. Das ist, was ich tue, und die Lesbarkeit ist praktisch dieselbe wie beim ersten Beispiel (wenn nicht besser ;-P). Eine andere Sache ist, dass das Einfügen von Zeilen in Gruppen von 2 oder 3 die Lesbarkeit erheblich verbessert. Sie scannen den Code einfach viel schneller.
Piotr Owsiak

6
Vielleicht liegt es daran, dass ich an Python gewöhnt bin, aber wenn ich die erste geschweifte Klammer in dieselbe Zeile wie die if-Anweisung setze, kann ich sie noch schneller lesen und verstehen.
Ponkadoodle

16
Das Problem mit dem spannungslosen Stil lässt Sie Ihre kostbare Konzentration verschwenden, wenn Sie darüber nachdenken, ob der Block eher Zahnspangen als wichtigere Dinge hat oder nicht. Dies allein ist ein guter Grund, die einfachste Konvention zu verwenden, bei der es sich immer um geschweifte Klammern handelt.
Nate CK

2
Zahnspangen sind von Natur aus explizit. Ich bleibe dabei, danke.
TheOptimusPrimus

2
Im letzten Fall jagen Sie den ursprünglichen Autor und verprügeln ihn ...;)
Per Lundberg

55

Wenn es etwas Kleines ist, schreibe es so:

if(foo()) bar();

Wenn es lang genug ist, um in zwei Zeilen zu brechen, verwenden Sie geschweifte Klammern.


Ja, das mache ich auch. Es zwingt Sie, geschweifte Klammern hinzuzufügen, wenn Sie eine weitere Zeile hinzufügen, und es ist ziemlich klar, dass bar () tatsächlich Teil des if ist, so dass schlimme Dinge passieren, wenn Sie es nur auskommentieren.
Jalf

10
Nicht sehr debuggerfreundlich. Wie richten Sie einen Haltepunkt für den Teil "Leiste" ein?
Nemanja Trifunovic

9
@Nemanja: Setzen Sie einfach Ihren Cursor auf bar (); und drücke F9. Sowohl VS2005 als auch VS2008 verarbeiten zeileninterne Haltepunkte, wenn es sich um separate "Anweisungen" handelt.
GalacticCowboy

4
GalanticCowboy: Es gibt mehr Umgebungen als die, die Sie kennen. :-)

20
Sicher, aber da der Kontext C # ist, sollte dies eine signifikante Mehrheit der Benutzer abdecken ...
GalacticCowboy

47

Früher dachte ich auch, es sei besser, Zahnspangen nur dann zu verwenden, wenn sie wirklich gebraucht werden. Aber nicht mehr, der Hauptgrund, wenn Sie viel Code haben, macht es ihn lesbarer und Sie können den Code schneller analysieren, wenn Sie einen konsistenten Klammerstil haben.

Ein weiterer guter Grund für die Verwendung von geschweiften Klammern neben der Hinzufügung einer zweiten Anweisung zum if ist, dass so etwas passieren könnte:

if(a)
   if(b)
     c();
else
   d();

Haben Sie bemerkt, dass die else-Klausel tatsächlich die des "if (b)" ist? Sie haben es wahrscheinlich getan, aber würden Sie darauf vertrauen, dass jemand mit dieser Gotcha vertraut ist?

Wenn also nur aus Gründen der Konsistenz und weil Sie nie wissen, welche unerwarteten Dinge passieren können, wenn jemand anderes (es sind immer die anderen, die dumm sind) den Code ändert, setze ich immer geschweifte Klammern, weil dadurch der Quellcode lesbarer und schneller zu analysieren ist dein Gehirn. Nur für die einfachsten if-Anweisungen, z. B. wenn eine Delegierung vorgenommen wird oder switch-artig ist und Sie wissen, dass die Klausel niemals erweitert wird, würde ich die geschweiften Klammern weglassen.


12
Dies ist einer der beiden Fälle, in denen ich Zahnspangen verwende. Sonst nicht.
Andrei Rînea

3
Dies sollte eher so geschrieben werden, als ob (a && b) ... in erster Linie überlegt.
alexander.biskop

8
@ alexander.biskop: Sicher nicht, da dies dem else-Block eine andere Bedeutung gibt ( !a || !b) als entweder mit ( !a) oder ohne ( a && !b) hinzugefügte Klammern.
Ben Voigt

1
@ Ben Voigt: Stimmt! Fiel darauf herein ;-) Ein halbes Jahr und zwei positive Stimmen später merkt jemand, dass die Aussage, die ich gemacht habe, falsch ist ... Ich schätze, ich habe nicht genug auf Details geachtet, hauptsächlich, weil die Absicht hinter meinem Kommentar eine andere war als darauf hinzuweisen eine technisch korrekte Umwandlung dieser if-Klausel. Was ich damit meinte war, dass verschachtelte Inline-if-Anweisungen im Allgemeinen die Lesbarkeit (und insbesondere die Rückverfolgbarkeit des Kontrollflusses) imho erheblich verringern und daher eher zu einer Anweisung zusammengefasst (oder insgesamt umgangen) werden sollten. Cheers
alexander.biskop

3
@ alexander.biskop: Gleichzeitig ist das Debuggen mit verschachtelten ifs mit jeweils einfacheren Bedingungen einfacher, da Sie jeweils einen Schritt ausführen können.
Ben Voigt

35

Dies wird nicht immer als schlechte Praxis angesehen. Die Mono Project Coding Guidelines empfehlen, keine geschweiften Klammern zu verwenden, wenn dies nicht erforderlich ist. Gleiches gilt für die GNU Coding Standards . Ich denke, es ist eine Frage des persönlichen Geschmacks, wie immer bei Codierungsstandards.


2
Das Betrachten des Mono-Codes erscheint mir nach dem Lesen der gesamten Richtlinie ziemlich fremd .
Dance2die

35

Linien sind billig. Prozessorleistung ist billig. Entwicklerzeit ist sehr teuer.

In der Regel würde ich mich immer auf die Seite des Schreibens von Code irren, es sei denn, ich entwickle eine absolut ressourcen- / geschwindigkeitskritische Anwendung

(a) Für jeden anderen Entwickler ist es einfach zu verfolgen, was ich tue

(b) Kommentieren Sie bestimmte Teile des Codes, die ihn möglicherweise benötigen

(c) Einfach zu debuggen, wenn etwas schief geht

(d) Einfach zu ändern, wenn es in Zukunft sein muss (dh Hinzufügen / Entfernen von Code)

Die Geschwindigkeit oder akademische Eleganz des Codes ist aus geschäftlicher Sicht diesen Faktoren untergeordnet. Das soll nicht heißen, dass ich klobigen oder hässlichen Code schreiben wollte, aber dies ist MEINE Prioritätsreihenfolge.

Durch das Weglassen von geschweiften Klammern in den meisten Fällen wird es für mich (b), (c) und (d) schwieriger (Anmerkung jedoch nicht unmöglich). Ich würde sagen, dass die Verwendung von geschweiften Klammern oder nicht keine Auswirkung auf (a) hat.


9
Ihre letzte Aussage zu (a) ist eine Meinung, die eine große Anzahl von Entwicklern, einschließlich anderer Poster hier, argumentieren würde.
Kelly S. French

34

Ich bevorzuge die Klarheit, die die geschweifte Klammer bietet. Sie wissen genau, was gemeint ist und müssen nicht raten, ob jemand sie nur vermasselt und weggelassen hat (und einen Fehler eingeführt hat). Das einzige Mal, wenn ich sie weglasse, ist, wenn ich das if und die Aktion in dieselbe Zeile setze. Das mache ich auch nicht sehr oft. Eigentlich bevorzuge ich das Leerzeichen, das eingeführt wird, indem die geschweifte Klammer auf eine eigene Linie gesetzt wird. Nach Jahren der K & R C-ähnlichen Programmierung muss ich jedoch daran arbeiten, die Linie mit einer Klammer zu beenden, wenn die IDE dies nicht erzwingt mich.

if (condition) action();  // ok by me

if (condition) // normal/standard for me
{
   action();
}

23

Ich denke, es ist eine Frage der Richtlinien für das Projekt, an dem Sie arbeiten, und des persönlichen Geschmacks.

Ich lasse sie normalerweise weg, wenn sie nicht benötigt werden, außer in einigen Fällen wie den folgenden:

if (something)
    just one statement; // i find this ugly
else
{
    // many
    // lines
    // of code
}

ich bevorzuge

if (something)
{
    just one statement; // looks better:)
}
else
{
    // many
    // lines
    // of code
}

15

Einer der Fälle, in denen dies Sie beißen kann, ist in den alten Tagen der C / C ++ - Makros. Ich weiß, dass dies eine C # -Frage ist, aber Codierungsstandards werden häufig ohne die Gründe übertragen, warum der Standard überhaupt erstellt wurde.

Wenn Sie beim Erstellen Ihrer Makros nicht sehr vorsichtig sind, können Probleme mit if-Anweisungen auftreten, die das {} nicht verwenden.

#define BADLY_MADE_MACRO(x) function1(x); function2(x);

if (myCondition) BADLY_MADE_MACRO(myValue)

Versteh mich nicht falsch, ich sage nicht, dass du immer {} tun solltest, um dieses Problem in C / C ++ zu vermeiden, aber ich musste mich aus diesem Grund mit einigen sehr seltsamen Fehlern befassen.


2
Wenn sich nur der gesamte Code als solcher deklarieren würde ... seufz
Nathan Strong

15

Ich denke immer genauso.

Bis eines Tages (warum gibt es immer diesen "einen Tag", der Ihr Leben für immer verändert?) Verbringen wir 24 bis 36 Stunden ohne Schlaf-Debugging des Produktionscodes, nur um herauszufinden, dass jemand keine geschweiften Klammern mit einer Such- / Ersetzungsänderung kombiniert hat .

Es war so etwas.

 if( debugEnabled ) 
      println( "About to save 1 day of work to some very important place.");
 saveDayData();

Was danach kam, war

 if( debugEnabled ) 
 //     println( "About to save 1 day of work to some very important place.");
 saveDayData();

Es stellte sich heraus, dass das System täglich 500 MB Protokolle generierte und wir aufgefordert wurden, es zu stoppen. Das Debug-Flag reichte nicht aus, sodass ein Such- und Ersetzungsdruck angebracht war.

Als die App in Produktion ging, war das Debug-Flag deaktiviert und die wichtigen "saveDayData" wurden nie aufgerufen.

BEARBEITEN

Jetzt ist der einzige Ort, an dem ich die geschweiften Klammern nicht benutze, das if / try-Konstrukt.

if( object != null ) try { 
     object.close();
} catch( .....

Nachdem ich einem Superstar-Entwickler dabei zugesehen habe.


3
Ich verstehe nicht. Sie haben eine Variable, die das Debuggen steuert (debugEnabled) und Sie verwenden weiterhin Kommentare, um das Debuggen zu deaktivieren ??? Warum haben Sie debugEnabled nicht einfach auf false gesetzt?
Igor Popov

Dies ist nicht genau das Szenario, aber Sie machen einen guten Punkt. Dumme Dinge (wie das Nicht-Setzen von Debug auf false) erzeugen subtile und dumme Fehler, die schwerer zu finden sind als "offensichtliche" Fehler. In diesem Fall hat es nicht allzu viel geholfen, keine Zahnspangen zu verwenden.
OscarRyz

1
@igor Wie wäre es, weil sie nur eine Protokollzeile entfernen wollten, nicht alle Protokollierungszeilen?
Gman

14

Ich bin sehr glücklich:

foreach (Foo f in foos)
  foreach (Bar b in bars)
    if (f.Equals(b))
      return true;

return false;

Persönlich verstehe ich nicht warum

foreach (Foo f in foos)
{
  foreach (Bar b in bars)
  {
    if (f.Equals(b))
    {
      return true;
    }
  }
}

return false;

ist nicht mehr lesbar.

Ja, Zeilen sind frei, aber warum sollte ich durch Seiten und Codeseiten scrollen müssen, wenn sie halb so groß sein könnten?

Wenn es einen Unterschied in der Lesbarkeit oder Wartbarkeit gibt, setzen Sie natürlich Klammern ein ... aber in diesem Fall sehe ich keinen Grund dafür.

Außerdem werde ich immer geschachtelte Klammern für verschachtelte if setzen, wo ich andere verschachtelt habe

if (condition1)
  if (condition2)
    doSomething();
  else (condition2)
    doSomethingElse();

vs.

if (condition1)
  if (condition2)
    doSomething();
else (condition2)
  doSomethingElse();

ist furchtbar verwirrend, deshalb schreibe ich es immer als:

if (condition1)
{
  if (condition2)
    doSomething();
  else (condition2)
    doSomethingElse();
}

Wann immer möglich, verwende ich ternäre Operatoren, aber ich verschachtele sie nie .


Ich habe gerade gesehen, dass dies fast in meinem Code passiert :) Ich dachte, ich werde mich umschauen, und siehe da ... es ist schon da draußen :)
Noctis

13

Um ehrlich zu sein, sehe ich es als:

Gute Programmierer programmieren defensiv, schlechte Programmierer nicht.

Da es oben einige Beispiele gibt und meine eigenen ähnlichen Erfahrungen mit Fehlern im Zusammenhang mit dem Vergessen von Zahnspangen, habe ich auf die harte Tour gelernt, IMMER STREBEN ZU SETZEN.

Alles andere ist die Wahl des persönlichen Stils gegenüber der Sicherheit, und das ist eindeutig eine schlechte Programmierung.

Joel erwähnt dies sogar in Making Wrong Code Look Wrong

Sobald Sie wegen fehlender Klammern von einem Fehler gebissen werden, stellen Sie fest, dass fehlende Klammern falsch aussehen, weil Sie wissen, dass möglicherweise ein weiterer Fehler auftritt.


Wenn offene Klammern selbst auf Linien platziert werden, sieht jeder Ort, an dem zwei oder mehr Linien ohne Klammerpaar eingerückt sind, falsch aus, ebenso wie jedes nicht übereinstimmende Klammerpaar. Eine solche Verwendung kostet eine leere Zeile in Fällen, in denen eine ifAnweisung einen Block steuert, vermeidet jedoch die Notwendigkeit eines Blocks in Fällen, in denen eine ifAnweisung eine einzelne Aktion anstelle eines Blocks steuert.
Supercat

10

Ich stimme zu: "Wenn Sie klug genug sind, jemanden dazu zu bringen, Sie für das Schreiben von Code zu bezahlen, sollten Sie klug genug sein, sich nicht nur auf Einrückungen zu verlassen, um den Codefluss zu sehen."

Es können jedoch ... Fehler gemacht werden, und dieser Fehler ist schwierig zu beheben ... insbesondere, wenn Sie sich den Code eines anderen ansehen.


10

Meine Philosophie ist, wenn es den Code lesbarer macht, warum nicht?

Offensichtlich muss man irgendwo die Grenze ziehen, wie das Finden dieses glücklichen Mediums zwischen prägnanten und übermäßig beschreibenden Variablennamen. Klammern vermeiden jedoch Fehler und verbessern die Lesbarkeit des Codes.

Sie können argumentieren, dass Leute, die klug genug sind, um Programmierer zu sein, klug genug sind, um Fehler zu vermeiden, die klammerlose Aussagen enthalten. Aber können Sie ehrlich sagen, dass Sie noch nie von etwas so Einfachem wie einem Rechtschreibfehler gestolpert sind? Minutien wie diese können bei großen Projekten überwältigend sein.


7
Das ist natürlich sehr subjektiv. Wenn Sie sie irgendwann weglassen, wird die Lesbarkeit verbessert.
Brian Knoblauch

Richtig, wenn ich jemals die Klammern weglasse, behalte ich eine Zeile, wie andere erwähnt haben. Ich bin zu oft gebissen worden, aber mehrzeilige klammerlose Aussagen. Selbst wenn Sie wissen, dass Sie darauf achten müssen, kann es Sie gelegentlich erwischen.
James McMahon

10

Es gibt immer Ausnahmen, aber ich würde dagegen argumentieren, Klammern nur dann wegzulassen, wenn sie in einer der folgenden Formen vorliegen:

if(x == y)
   for(/* loop */)
   {
      //200 lines
   }

//rampion's example:
for(/* loop */)
{
   for(/* loop */)
      for(/* loop */)
      {
         //several lines
      }
}

Ansonsten habe ich kein Problem damit.


4
Schlechte Beispiele. In beiden Fällen würde ich diese 200-Zeilen-for-Schleife in eine eigene Methode oder vorzugsweise mehrere Methoden einbeziehen.
Adam Jaskiewicz

2
Stimmt, aber es passiert. Jedes Mal, wenn ein Block länger als der Bildschirm des Lesers ist, tritt dieses Problem auf. Und Sie können die Bildschirmhöhe Ihres Codelesers nicht steuern. Sie sehen möglicherweise nur ein paar Zeilen auf jeder Seite.
Rampion

2
Es passiert. Das heißt nicht, dass es passieren sollte .
Adam Jaskiewicz

3
@ AdamJaskiewicz Richtig. Es passiert. Wir haben darüber nachzudenken , was nicht passieren, und nicht als das, was sollte passieren. Wenn wir uns auf das beschränken könnten, was passieren sollte , müssten wir uns keine Sorgen um Fehler machen.
Beska

10

Ich verwende gelegentlich den untersten Code (mehrere using-Anweisungen), aber ansonsten setze ich immer die geschweiften Klammern ein. Ich finde nur, dass dies den Code klarer macht. Aus mehr als nur Einrückungen geht hervor, dass eine Anweisung Teil eines Blocks ist (und somit wahrscheinlich Teil eines if usw.).

Ich habe das gesehen

if (...)
    foo();
    bar();

Fehler beißen mich (oder besser "ich und Kollegen" - ich habe den Fehler nicht wirklich eingeführt) einmal . Dies trotz der Tatsache, dass unsere damaligen Codierungsstandards die Verwendung von Klammern überall empfahlen. Ich habe überraschend lange gebraucht, um zu erkennen - weil Sie sehen, was Sie sehen möchten. (Das war vor ungefähr 10 Jahren. Vielleicht würde ich es jetzt schneller finden.)

Wenn Sie "Klammer am Ende der Linie" verwenden, werden natürlich die zusätzlichen Linien reduziert, aber ich persönlich mag diesen Stil sowieso nicht. (Ich benutze es bei der Arbeit und habe es weniger unangenehm gefunden als erwartet, aber es ist immer noch etwas unangenehm.)


Ich argumentiere immer, dass Konsistenz wichtiger ist als der tatsächliche Stil. Warum sollten wir nur bei Verwendungen eine Ausnahme machen?
Bob

@ Bob: Guter Punkt, und ich mache es nur gelegentlich. Ich möchte nicht so tun, als hätte ich hier tatsächliche Gründe :) Eigentlich gibt es einen vernünftigen Grund - das Verschachteln der Verwendungen (und nur der Verwendungen) ist ziemlich offensichtlich, und Sie haben immer noch einen Block. Ich kann die Gefahr nicht sofort erkennen.
Jon Skeet

Was nicht zu sagen , dass es nicht ist die Gefahr, natürlich.
Jon Skeet

1
Beste Lösung für diesen Fehler: Verwenden Sie Python. (Scherz natürlich.)
Joel Wietelmann

10

Ich bin beeindruckt und demütigt darüber, dass meine Kollegen auf diesem Gebiet der Computerprogrammierung (Sie viel) nicht von der Aussicht auf mögliche Fehler entmutigt sind, wenn Sie die Klammern in einzeiligen Blöcken überspringen.

Ich denke, das bedeutet, dass ich nicht schlau bin. Ich habe diesbezüglich mehrfach Fehler gemacht. Ich habe die Fehler anderer in dieser Hinsicht getestet. Ich habe gesehen, wie Software aus diesem Grund mit Fehlern ausgeliefert wurde (RDP auf einem Computer, auf dem VS2002 ausgeführt wird, und die Schriftart Ihres Überwachungsfensters wird wackelig).

Wenn ich mir all die Fehler ansehe, die ich gemacht habe und die mit einer Änderung des Codierungsstils hätten vermieden werden können, ist die Liste sehr lang. Wenn ich nicht in jedem dieser Fälle meinen Ansatz geändert hätte, hätte ich es wahrscheinlich nie als Programmierer geschafft. Auch hier bin ich wohl nicht schlau. Um dies zu kompensieren, bin ich seit langer Zeit ein überzeugter Benutzer von Klammern auf einzeiligen Blöcken.

Trotzdem haben sich einige Dinge in der Welt geändert, die die Regel "Du sollst Klammern für einzeilige Blöcke verwenden" heute weniger relevant machen als zu dem Zeitpunkt, als Moses sie uns vorlegte:

  • Bei einigen gängigen Sprachen wird das Problem behoben, indem der Computer die Einrückung liest, genau wie der Programmierer (z. B. Python).

  • Mein Editor formatiert automatisch für mich, sodass die Wahrscheinlichkeit, dass ich durch Einrückungen irregeführt werde, erheblich verringert wird.

  • TDD bedeutet, dass ich den Fehler viel schneller erkenne , wenn ich einen Fehler einführe, weil ich durch einen einzeiligen Block verwirrt werde.

  • Refactoring und Ausdruckskraft der Sprache bedeuten, dass meine Blöcke viel kürzer sind und einzeilige Blöcke viel häufiger vorkommen als früher. Hypothetisch könnte ich mit einer rücksichtslosen Anwendung von ExtractMethod möglicherweise nur einzeilige Blöcke in meinem gesamten Programm haben. (Ich frage mich, wie das aussehen würde?)

Tatsächlich kann es einen deutlichen Vorteil haben, rücksichtslos umzugestalten und Klammern in einzeiligen Blöcken wegzulassen: Wenn Sie Klammern sehen, kann in Ihrem Kopf ein kleiner Alarm ausgelöst werden, der besagt: "Komplexität hier! Vorsicht!". Stellen Sie sich vor, dies wäre die Norm:

if (condition) Foo();   // normal, everyday code

if (condition) 
{
    // something non-trivial hapening; pay attention!
    Foo();
    Bar();
}

Ich öffne mich der Idee, meine Codierungskonvention so zu ändern, dass "einzeilige Blöcke möglicherweise niemals geschweifte Klammern haben" oder "wenn Sie den Block in dieselbe Zeile wie die Bedingung setzen können und alles in 80 Zeichen passt". Klammern weglassen ". Wir werden sehen.


Als ehemaliger Java-Programmierer muss ich der automatisierten Formatierung als eigentliche Antwort auf das Problem voll und ganz zustimmen. Sie müssen Ihren Editor nicht einmal automatisch Klammern hinzufügen lassen - das automatische Einrücken allein kann dazu beitragen, Mehrdeutigkeiten zu vermeiden. Nachdem ich zu Python gewechselt bin, habe ich mich natürlich zunächst daran gewöhnt, meinen Code richtig zu formatieren.
Alan Plum

Bei Zahnspangen geht es mir genauso. Es geht nur um die Komplexität. Idealerweise hätten wir nur einen Zeilenblock. Das nenne ich Lesbarkeit, keine unnötigen Klammern.
Igor Popov

9

Aus den drei Konventionen:

if(addCurleyBraces()) bugFreeSofware.hooray();

und:

if(addCurleyBraces())
    bugFreeSofware.hooray();

und (die einen Einrückungsstil mit einer öffnenden und einer schließenden Klammer darstellen):

if(addCurleyBraces()) {
    bugFreeSofware.hooray();
}

Ich bevorzuge den letzten als:

  • Ich finde es einfacher zu lesen, wenn alle if-Anweisungen einheitlich geschrieben sind.
  • Dies kann die Software ein wenig robuster und fehlerfreier machen. Alle modernen IDEs und erweiterten Texteditoren verfügen jedoch über nette Funktionen zum automatischen Einrücken, die meiner Meinung nach jeder verwenden sollte, solange die Formatierung von Kommentaren nicht durcheinander gebracht wird oder gegen Teamstandards verstößt (in vielen Fällen ist es möglich, ein benutzerdefiniertes Formatierungsschema zu erstellen und teile es mit dem Team). Mein Punkt hier ist, dass bei korrekter Einrückung das Risiko einer Fehlereinführung etwas verringert wird.
  • Ich bevorzuge, dass der boolesche Ausdruck und die Anweisung (en) in verschiedenen Zeilen ausgeführt werden. Ich möchte in der Lage sein, eine Zeile für Debugging-Zwecke zu markieren. Selbst wenn ich eine IDE verwende, in der ich eine Anweisung markieren und darauf zugreifen kann, handelt es sich um eine interaktive Operation, und ich vergesse möglicherweise, wo ich mit dem Debuggen begonnen habe, oder es dauert zumindest ein bisschen länger, bis ich den Code mehrere Schritte durchlaufen habe Zeiten (da ich die Position jedes Mal während des Debuggens manuell markieren muss).

8

Ihre Hauptargumente gegen die Verwendung von geschweiften Klammern sind, dass sie zusätzliche Zeilen verwenden und zusätzliche Einrückungen erfordern.

Zeilen sind (fast) frei, die Minimierung der Anzahl der Zeilen in Ihrem Code sollte kein Ziel sein.

Die Einrückung ist unabhängig von der Verwendung der Zahnspange. In Ihrem kaskadierenden "using" -Beispiel denke ich immer noch, dass Sie sie einrücken sollten, auch wenn Sie die geschweiften Klammern weglassen.


8

Ich bin fest davon überzeugt, ordentlichen und prägnanten Code zu schreiben, aber ich würde immer geschweifte Klammern verwenden. Ich finde, dass sie eine bequeme Möglichkeit sind, schnell den Umfang zu erkennen, in dem eine bestimmte Codezeile existiert. Es gibt keine Mehrdeutigkeit, es wird nur explizit vor Ihnen dargelegt.

Einige mögen sagen, es sei ein Präferenzfall, aber ich finde den logischen Ablauf eines Programms viel einfacher zu verfolgen, wenn es intern konsistent ist, und ich glaube nicht, dass es konsistent ist, eine IF-Anweisung wie diese zu schreiben.

if(x < y)
    x = y;
else
    y = x;

Und noch so einer;

if(x < y)
{
    x = y;
    x++;
}
else
{
    y = x;
    y++;
}

Ich ziehe es vor, nur einen allgemeinen Stil auszuwählen und dabei zu bleiben :)


7

Eine der wichtigsten Fragen ist , wenn Sie Regionen Einzeiler und nicht-Einzeiler, zusammen mit der Trennung von der Steuer statment ( for, if, was Sie hat) und das Ende des statment.

Beispielsweise:

for (...)
{
  for (...)
    for (...) 
    {
      // a couple pages of code
    }
  // which for block is ending here?  A good text editor will tell you, 
  // but it's not obvious when you're reading the code
}

4
Warum haben Sie überhaupt ein paar Seiten Code in Ihrer for-Schleife?
Adam Jaskiewicz

b / c Ich bin ein unempfindlicher Klumpen und ich bin besessen davon, die "Kosten" von Funktionsaufrufen loszuwerden. :)
Rampion

4
Die paar Codeseiten sollten normalerweise eine separate Funktion haben.
Jonathan Leffler

1
Entschuldigung, ich meinte, ich spiele die Rolle eines solchen Klumpens. Ich bin jedoch der Meinung, dass das gleiche Problem bei kürzeren Regionen auftreten kann, wenn es durch ein kleines Ansichtsfenster betrachtet wird. Und das liegt außerhalb der Kontrolle des Codierers.
Rampion

7

Früher war ich ein großer Befürworter von "geschweiften Klammern sind ein MUSS!", Aber seit ich Unit-Tests eingeführt habe, finde ich, dass meine Unit-Tests braceless-Aussagen vor folgenden Szenarien schützen:

if (foo)
    snafu();
    bar();

Bei guten Unit-Tests kann ich geschweifte Klammern für einfache Aussagen weglassen, um die Lesbarkeit zu verbessern (ja, das kann subjektiv sein).

Alternativ würde ich für so etwas wie das wahrscheinlich inline setzen, dass es so aussieht:

if (foo) snafu();

Auf diese Weise kann der Entwickler, der der Bedingung bar () hinzufügen muss, den Mangel an geschweiften Klammern besser erkennen und hinzufügen.


2
Sie sagten "Ich brauche es nicht" und gaben dann einen Grund für die Verwendung an: Lesbarkeit!
Tvanfosson

4
Ich würde mich nicht auf einen Unit Test verlassen, um das herauszufinden. LINT vielleicht, Unit Test nein!
Kristen

2
@Kristen - Die Idee des Unit-Tests besteht darin, das Verhalten der Methode zu bestätigen. Wenn sich das Verhalten ändert (wie oben beschrieben), schlägt der Komponententest fehl. Ich sehe das Problem darin nicht.
Liggy

Aber warum sollten Sie sich auf Unit Test verlassen, um das offensichtliche Problem zu lösen, das behoben werden sollte, bevor Sie zu UT gehen?
Andrew

7

Verwenden Sie ein persönliches Urteilsvermögen.

if (foo)
  bar();

ist in Ordnung für sich. Es sei denn, Sie sind wirklich besorgt darüber, dass Idioten später so etwas einbauen:

if (foo)
  bar();
  baz();

Wenn Sie sich keine Sorgen um Idioten machen, geht es Ihnen gut (ich nicht - wenn sie die grundlegende Codesyntax nicht richtig verstehen, ist dies das geringste ihrer Probleme)>

Im Gegenzug ist es viel besser lesbar.

Der Rest der Zeit:

if (foo) {
  bar();
  baz();
}

Welches war mein Favorit, solange ich mich erinnern kann. Zusätzlich:

if (foo) {
  bar();
  baz();
} else {
  qux();
}

Funktioniert bei mir.

Der vertikale Raum an sich ist nicht besonders relevant, die Lesbarkeit jedoch. Die öffnende Klammer in einer Zeile selbst stoppt nur die Konversation für ein syntaktisches Element, bis Ihr Auge zur nächsten Zeile wechselt. Nicht was ich mag.


Ich bevorzuge den ersten Stil nur, wenn ich sofort zurückkehren oder einen Fehler auslösen muss, falls etwas nicht stimmt. Wie if (parameter == null) return null;.
Nawfal

7

Okay, das ist eine alte Frage, die zu Tode beantwortet wurde. Ich habe etwas hinzuzufügen.

Zuerst muss ich nur USE THE BRACES sagen. Sie können nur zur besseren Lesbarkeit beitragen, und die Lesbarkeit (für Sie und andere!) Sollte auf Ihrer Prioritätenliste ganz oben stehen, es sei denn, Sie schreiben eine Baugruppe. Unlesbarer Code führt immer zu Fehlern. Wenn Sie feststellen, dass Ihr Code durch geschweifte Klammern zu viel Platz beansprucht, sind Ihre Methoden wahrscheinlich zu lang. Die meisten oder alle Methoden sollten in eine Bildschirmhöhe passen, wenn Sie es richtig machen, und Find (F3) ist Ihr Freund.

Nun zu meinem Zusatz: Es gibt ein Problem damit:

if (foo) bar();

Versuchen Sie, einen Haltepunkt festzulegen, der nur erreicht wird, wenn bar () ausgeführt wird. Sie können dies in C # tun, indem Sie den Cursor auf die zweite Hälfte des Codes setzen, aber das ist nicht offensichtlich und ein bisschen schmerzhaft. In C ++ konnte man das überhaupt nicht machen. Einer unserer erfahrensten Entwickler, der an C ++ - Code arbeitet, besteht aus diesem Grund darauf, 'if'-Anweisungen in zwei Zeilen aufzuteilen. Und ich stimme ihm zu.

Also mach das:

if (foo)
{
    bar(); //It is easy to put a breakpoint here, and that is useful.
}

2
Klicken Sie mit der rechten Maustaste auf die Leiste und wählen Sie Haltepunkt einfügen ... Überhaupt nicht schwer. Kennen Sie Ihre Werkzeuge.
Bob

Ein Rechtsklick auf die Anzeigeleiste führt zu nichts. Meinst du Rechtsklick auf den Text? Wenn Sie möchten, dass der Haltepunkt nur erreicht wird, wenn die "if" -Anweisung wahr ist und "bar ()" sich in einer eigenen Zeile befindet, können Sie den Cursor an eine beliebige Stelle in dieser Zeile setzen und F9 drücken oder mit der linken Maustaste auf klicken Indikatormarge. Befindet sich der gesamte Code jedoch in einer einzelnen Zeile, müssen Sie den Cursor auf "bar ()" positionieren oder genau dort mit der rechten Maustaste klicken, bevor Sie F9 drücken. Das Klicken auf den Indikatorrand funktioniert nicht (setzt den Haltepunkt auf ' wenn'). Es ist nicht "schwer", aber es erfordert weniger Konzentration, wenn der Code in zwei Zeilen steht.
Stein

Oh, ha ha, klicke mit der rechten Maustaste auf "bar ()". Du hast den Text gemeint. Erwischt. Sicher, oder drücken Sie einfach F9 ...
Stein

>> Sie müssen den Cursor auf "bar ()" positionieren oder genau dort mit der rechten Maustaste klicken, bevor Sie F9 drücken (ich wollte den Cursor genau dort positionieren, bevor Sie entweder F9 drücken oder mit der rechten Maustaste klicken)
stone

7

Um zu verhindern, dass der Code mit geschweiften Klammern viel Platz beansprucht, verwende ich die im Buch Code Complete empfohlene Technik :

if (...) {
    foo();
    bar();
}
else {
    ...
}

Ich verstehe nicht, warum es heruntermodifiziert wurde. Es spart eine Zeile für jedes Klammerpaar, das ich ständig benutze
Eric

2
Dies ist im Volksmund als K & R-Stil bekannt. Basierend auf dem Buch The C Programming Language von Kernighan und Ritchie: en.wikipedia.org/wiki/The_C_Programming_Language_(book) . Und es sollte dich nicht modifizieren.
jmucchiello

Vielen Dank! Ich dachte, es sei nur persönlicher Geschmack. Früher fand ich diese Syntax selbst ärgerlich, aber ich habe sie nach dem Lesen von Code Complete übernommen und genieße sie jetzt wirklich.
Nathan Prather

Ich las alle Antworten über dieser Frage und dachte: "Warum hat das noch niemand vorgeschlagen?" Dadurch wird die schließende Klammer an dem Block ausgerichtet, den sie schließt, dh "wenn" oder "während" usw., kein bedeutungsloses "{". +1.
Nickf

Wenn offene Klammern immer alleine auf Zeilen gesetzt werden, kann eine, auf ifdie eine einzelne eingerückte Linie folgt, visuell als Steuerung einer einzelnen Anweisung erkannt werden, ohne dass Klammern erforderlich sind. Der Open-Brace-by-sich-Stil spart somit Leerzeichen in Situationen, in denen eine ifAnweisung etwas steuert, das semantisch eine einzelne Aktion ist (im Gegensatz zu einer Folge von Schritten, die zufällig nur einen einzelnen Schritt enthält). Zum Beispiel if (someCondition)/ `werfen Sie eine neue SomeException (...)`.
Supercat

6

Angenommen, Sie haben einen Code:

if (foo)
    bar();

und dann kommt jemand anderes und fügt hinzu:

if (foo)
    snafu();
    bar();

Entsprechend der Art und Weise, wie es geschrieben ist, bar (); wird jetzt bedingungslos ausgeführt. Indem Sie die geschweiften Klammern einschließen, verhindern Sie diese Art von versehentlichem Fehler. Code sollte so geschrieben sein, dass solche Fehler schwierig oder unmöglich zu machen sind. Wenn ich eine Codeüberprüfung durchführen und die fehlenden geschweiften Klammern sehen würde, insbesondere über mehrere Zeilen verteilt, würde ich einen Fehler verursachen. In Fällen, in denen dies gerechtfertigt ist, halten Sie es in einer Zeile, damit die Wahrscheinlichkeit eines solchen Fehlers erneut auf ein Minimum beschränkt wird.


Dieser Punkt wurde bereits in der Frage angesprochen.
Mike Scott

Eigentlich nicht ganz. Ja, er erwähnte das Potenzial für diese Art von Fehler, aber ich habe darüber gesprochen, Ihren Code fehlerfrei zu machen und das Fehlerpotential als Teil der Best Practices zu beseitigen.
Elie

Gibt es wirklich so etwas wie einen fehlerfreien Code?
Bob

Nein, aber Sie können es schwieriger machen. Lesen Sie "Best Kept Secrets of Peer Code Review" von Jason Cohen (siehe Link auf einigen Seiten hier), um eine bessere Vorstellung davon zu bekommen, warum Sie dies tun.
Elie

Wer ist dieser Mike Scott und warum ist er die Antwortpolizei? Es macht mich immer wahnsinnig, dass die Leute sagen müssen, was offensichtlich ist. Warum hat Mike die hinzugefügte Beschreibung, die Benutzer zu diesem Problem veröffentlichen, nicht weiter kommentiert? Beziehen sich nicht alle Antworten auf die Frage?
Bruceatk

6

Das Reduzieren von Linien ist kein gutes Argument, um geschweifte Klammern fallen zu lassen. Wenn Ihre Methode zu groß ist, sollte sie wahrscheinlich in kleinere Teile umgestaltet oder umstrukturiert werden. Dies erhöht zweifellos die Lesbarkeit mehr als das einfache Herausnehmen von Zahnspangen.


5

Ich lasse sie immer weg, wenn es angebracht ist, wie in Ihrem ersten Beispiel. Sauberer, prägnanter Code, den ich durch einen Blick sehen und verstehen kann, ist einfacher zu pflegen, zu debuggen und zu verstehen als Code, durch den ich scrollen und Zeile für Zeile lesen muss. Ich denke, die meisten Programmierer werden dem zustimmen.

Es ist leicht außer Kontrolle zu geraten, wenn Sie mehrere Verschachtelungen, if / else-Klauseln usw. durchführen, aber ich denke, die meisten Programmierer sollten in der Lage sein, zu sagen, wo sie die Grenze ziehen sollen.

Ich sehe es ein bisschen wie das Argument für if ( foo == 0 )vs if ( 0 == foo ). Letzteres kann Fehler für neue Programmierer (und möglicherweise sogar gelegentlich für Veteranen) verhindern, während Ersteres beim Verwalten von Code leichter schnell zu lesen und zu verstehen ist.


4

Meistens ist es als Codierungsstandard verankert, egal ob für ein Unternehmen oder ein FOSS-Projekt.

Letztendlich muss jemand anderes Ihren Code bearbeiten und es ist ein großer Zeitaufwand für jeden Entwickler, den spezifischen Stil des Codeabschnitts herauszufinden, an dem er arbeitet.

Stellen Sie sich außerdem vor, dass jemand mehr als einmal am Tag zwischen Python und einer Cish-Sprache wechselt ... In Python ist das Einrücken Teil der Blocksymantik der Sprache, und es wäre recht einfach, einen Fehler wie den von Ihnen zitierten zu machen.


+1 für einen Kommentar zu Python. Ich bin immer wieder erstaunt, wie "dumm" ich sein kann, wenn ich ständig zwischen Sprachen wechsle.
Kena

3

Err auf der Seite der Sicherheit - nur ein weiterer Fehler, den Sie möglicherweise nicht beheben müssen.

Ich persönlich fühle mich sicherer, wenn alle meine Blöcke in Locken gewickelt sind. Selbst für Einzeiler sind dies einfache Notationen, die Fehler leicht verhindern. Dies macht den Code in dem Sinne lesbarer, dass Sie deutlich sehen, was sich im Block befindet, um den Körper des Blocks nicht mit den folgenden Anweisungen außerhalb des Blocks zu verwechseln.

Wenn ich einen Einzeiler habe, formatiere ich ihn normalerweise wie folgt:

if( some_condition ) { do_some_operation; }

Wenn die Leitung einfach zu umständlich ist, verwenden Sie Folgendes:

if( some_condition )
{
    do_some_operation;
}
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.