Почему считать плохую практику опустить фигурные скобки?

Почему все говорят мне писать код, как будто это плохая практика?

if (foo)
    Bar();

//or

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

Мой самый большой аргумент в пользу упущения фигурных скобок заключается в том, что иногда они могут быть в два раза больше строк. Например, вот какой-то код для рисования эффекта свечения для метки на С#.

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));

Вы также можете получить дополнительную выгоду от цепочки usings вместе без необходимости отступа в миллион раз.

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
}

Наиболее распространенный аргумент для фигурных скобок вращается вокруг программирования технического обслуживания и проблем, возникающих при вставке кода между исходным оператором if и его предполагаемым результатом:

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

Вопросы:

  • Неправильно ли вам использовать более компактный синтаксис, который предлагает язык? Люди, которые разрабатывают эти языки, умны, я не могу себе представить, что они будут использовать функцию, которая всегда будет плохой.
  • Должны ли мы или не должны писать код, поэтому самый низкий общий знаменатель может понять и не иметь проблем с этим?
  • Есть ли еще один аргумент, который мне не хватает?

Ответ 1

На самом деле, единственный раз, когда-либо забитый мной, был, когда я отлаживался, и прокомментировал bar():

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

Кроме этого, я склонен использовать:

if(foo) bar();

Что позаботится об этом случае.

EDIT Спасибо за разъяснение вопроса, я согласен, мы не должны писать код в самый низкий общий знаменатель.

Ответ 2

Скорость чтения...

Помимо того, что уже упоминалось. На данный момент, я уже был обусловлен, чтобы анализировать выражения с фигурными скобками и пробелами. Поэтому я читал:

if (condition)
{
    DoSomething();
}

DoSomethingElse();

Чуть быстрее, чем я читал:

if (condition) DoSomething();

DoSomethingElse();

Я читал его немного медленнее, если он выглядит так:

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

Я читал это значительно медленнее, чем раньше:

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

потому что я не могу не прочитать его снова на всякий случай и задаться вопросом, предназначался ли автор:

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

Уже охвачено в целом, но когда дело доходит до чтения ниже, я буду изучать это довольно долго, чтобы убедиться, что автор намеревался. Я могу даже выследить оригинального автора, чтобы подтвердить.

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

Ответ 3

Если это что-то маленькое, напишите его вот так:

if(foo()) bar();

Если он достаточно длинный, чтобы разбить на две строки, используйте фигурные скобки.

Ответ 4

Я также привык думать, что лучше использовать только фигурные скобки, когда это действительно необходимо. Но не более того, основная причина, когда у вас много кода, делает ее более читаемой, и вы можете быстрее анализировать код, когда у вас есть согласованный стиль фиксации.

Еще одна веская причина всегда использовать фигурные скобки, помимо того, что кто-то добавляет второе утверждение в if, может произойти что-то вроде этого:

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

Вы заметили, что предложение else на самом деле относится к "if (b)"? Вы, наверное, сделали, но можете ли вы доверять кому-либо, чтобы быть знакомым с этой ошибкой?

Итак, если только для согласованности и потому, что вы никогда не знаете, какие неожиданные вещи могут произойти, когда кто-то другой (это всегда другие глупые) меняет код, я всегда ставил фигурные скобки, потому что он делает исходный код более читабельным, более быстрым для анализа вашим мозгом. Только для самых простых операторов if, таких как if, если делегирование сделано или похоже на коммутатор, где вы знаете, что предложение никогда не будет расширено, я бы не оставил фигурные скобки.

Ответ 5

Я предпочитаю ясность, которую предлагает фигурная скобка. Вы точно знаете, что имеется в виду, и не нужно догадываться, если кто-то просто ушел и оставил их (и представил ошибку). Единственный раз, когда я опускаю их, я устанавливаю if и action в одной строке. Я тоже не очень часто это делаю. Я фактически предпочитаю, чтобы пробелы вводились, вставляя фигурные скобки в свою линию, хотя из-за лет программирования K & R C, заканчивая линию с помощью скобки, я должен работать, чтобы преодолеть, если среда IDE не обеспечивает это для меня.

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

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

Ответ 6

Это не всегда считается плохой практикой. "Рекомендации по кодированию моногонов" предлагает не использовать фигурные скобки, если это не необходимо. То же самое для стандартов кодирования GNU. Я думаю, что это вопрос личного вкуса, как всегда, со стандартами кодирования.

Ответ 7

Линии дешевы. Мощность процессора дешева. Время разработки очень дорого.

Как правило, если я не разрабатываю какое-то абсолютно критичное для ресурса/скорость приложение, я бы всегда ошибался на стороне написания кода

(a) Легко для любого другого разработчика следить за тем, что я делаю

(b) Прокомментируйте отдельные части кода, которые могут ему понадобиться

(c) Легко отладить, если что-то пойдет не так

(d) Легко модифицировать, если это необходимо в будущем (например, добавление/удаление кода)

Скорость или академическая элегантность кода являются вторичными по отношению к этим факторам с точки зрения бизнеса. Это не значит, что я намеревался написать неуклюжий или уродливый код, но это MY-порядок приоритета.

В большинстве случаев, опуская фигурные скобки, для меня это делает (b), (c) и (d) более сложным (но не невозможно). Я бы сказал, что использование фигурных скобок или нет не влияет на (а).

Ответ 8

Я думаю, что это вопрос руководящих принципов для проекта, над которым вы работаете, и личного вкуса.

Я обычно опускаю их, когда они не нужны, кроме некоторых случаев, таких как:

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

Я предпочитаю

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

Ответ 9

Один из примеров, когда это может вас укусить, - это в старые времена макросов C/С++. Я знаю, что это вопрос С#, но часто стандарты кодирования переносятся без оснований, по которым стандарт был создан в первую очередь.

Если вы не очень осторожны при создании своих макросов, вы можете вызвать проблемы с операторами if, которые не используют {}.

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

if (myCondition) BADLY_MADE_MACRO(myValue)

Теперь, не поймите меня неправильно, я не говорю, что вы всегда должны {} просто избегать этой проблемы в C/С++, но из-за этого мне приходилось иметь дело с некоторыми очень странными ошибками.

Ответ 10

Я так же думаю.

До одного дня (почему всегда есть "один день", который изменяет вашу жизнь навсегда?), мы проводим с 24 до 36 часов подряд без сна, отлаживая производственный код только для того, чтобы узнать, что кто-то не поставил брекеты в сочетании с поиском/заменить изменение.

Это было что-то вроде этого.

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

То, что произошло после, было

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

Оказывается, система ежедневно генерировала 500 мб журналов, и нас попросили остановить ее. Флаг отладки был недостаточным, поэтому поиск и замена println были в порядке.

Когда приложение пришло в производство, флаг отладки отключился, и важная "saveDayData" никогда не вызывалась.

EDIT

Теперь единственное место, где я не использую фигурные скобки, - это построить if/try.

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

Посмотрите, как разработчик суперзвезды делает это.

Ответ 11

Я очень рад:

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

return false;

Лично я не понимаю, почему

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

return false;

является более читаемым.

Да, строки бесплатны, но почему мне приходится прокручивать страницы и страницы кода, когда это может быть вдвое меньше?

Если есть разница в удобочитаемости или ремонтопригодности, то, конечно, поместите скобки в..., но в этом случае я не вижу никаких причин.

Кроме того, я всегда буду устанавливать фигурные скобки для вложенных, если у меня есть вложенный

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

против

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

ужасно запутанно, поэтому я всегда пишу его как:

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

По возможности я использую тройные операторы, но я никогда не вложил их.

Ответ 12

Чтобы быть тупым, я вижу это как:

Хорошие программисты защищают оборону, Bad программисты этого не делают.

Так как есть несколько примеров выше и мой собственный подобный опыт с ошибками, связанными с забыванием фигурных скобок, тогда я усвоил трудный путь ВСЕГДА ПУТЬ БРАК.

Все остальное выбирает личный стиль над безопасностью и это явно плохое программирование.

Джоэл даже упоминает это в Неправильный код неправильного кода

Как только вы получите бит из-за отсутствия фигур, вы узнаете, что отсутствующие фигурные скобки выглядят неправильно, потому что вы знаете, что это потенциальное место для возникновения другой ошибки.

Ответ 13

Всегда есть исключения, но я бы возражал против опускания фигурных скобок только в том случае, если он находится в одной из форм:

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

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

В противном случае у меня нет проблем с этим.

Ответ 14

Я иногда использую самый нижний код (несколько с помощью операторов), но кроме этого я всегда помещаю фигурные скобки. Я просто нахожу, что он делает код более понятным. Это явно очевидно из более чем одного отступа, что оператор является частью блока (и, следовательно, вероятно, является частью if и т.д.).

Я видел

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

ошибка укусит меня (или, вернее, меня и коллег) - я фактически не вводил ошибку). Это было несмотря на то, что наши стандарты кодирования в то время рекомендовали использовать брекеты повсюду. Мне потребовалось довольно много времени, чтобы увидеть - потому что вы видите, что хотите видеть. (Это было около 10 лет назад. Возможно, я найду его быстрее.)

Конечно, если вы используете "скобку в конце строки", это уменьшает лишние строки, но мне лично не нравится этот стиль. (Я использую его на работе и считаю его менее неприятным, чем я ожидал, но это все еще немного неприятно.)

Ответ 15

Я согласен с тем, что "если вы достаточно умны, чтобы заставить кого-то платить вам за код, вы должны быть достаточно умны, чтобы не полагаться исключительно на отступ, чтобы увидеть поток кода".

Однако... ошибки могут быть сделаны, и это больно отлаживать... особенно если вы смотрите на код другого пользователя.

Ответ 16

Моя философия заключается в том, что он делает код более читаемым, почему бы не сделать это?

Очевидно, что вы должны нарисовать линию где-то, например, найти эту счастливую среду между краткими и чрезмерно описательными именами переменных. Но скобки действительно избегают ошибок и улучшают читаемость кода.

Вы можете утверждать, что люди, достаточно умные, чтобы быть кодовыми, будут достаточно умны, чтобы избежать ошибок, которые приводят к заявлениям без привязки. Но можете ли вы честно сказать, что вы никогда не сталкивались с чем-то простым, как орфографическая ошибка? Minutia, как это может быть подавляющим, глядя на крупные проекты.

Ответ 17

Я впечатлен и смирен, что мои сверстники в этой области компьютерного программирования (вы много) не испытывают недостатка в перспективах потенциальных ошибок при пропуске фигурных скобок на блоках одной строки.

Я полагаю, это означает, что я не умный. Я неоднократно совершал ошибки. Я отлаживал ошибки других. Из-за этого я наблюдал за программным кораблем с ошибками (RDP для машины, работающей на VS2002, и шрифт окна вашего браузера будет неудобным).

Если я посмотрю на все ошибки, которые я сделал, которых можно было избежать, с изменением стиля кодирования, список очень длинный. Если бы я не изменил свой подход в каждом из этих случаев, я, вероятно, никогда бы не стал его программистом. Опять же, я думаю, я не умный. Чтобы компенсировать это, я долгое время был стойким пользователем брекетов в однострочных блоках.

Тем не менее, некоторые вещи изменились в мире, которые заставляют "использовать брекеты на однострочных блоках" менее актуальными сегодня, чем когда Моисей привел это к нам:

  • Некоторые популярные языки устраняют проблему, заставляя компьютер читать отступ, как это делает программист (например, Python).

  • Мой редактор автоматически форматирует для меня, поэтому вероятность того, что я ошибаюсь в отступе, значительно сокращается.

  • TDD означает, что если я введю ошибку, потому что я запутался в однострочном блоке, я гораздо чаще обнаруживаю ошибку быстро.

  • Рефакторинг и выразительность языка означают, что мои блоки намного короче, а однострочные блоки происходят гораздо чаще, чем используемые. Гипотетически, с безжалостным применением ExtractMethod, я мог бы иметь только однострочные блоки во всей моей программе. (Интересно, как это будет выглядеть?)

На самом деле, существует явное преимущество реструктуризации безжалостно и опускания брекетов на однострочных блоках: когда вы видите брекеты, в голове может появиться небольшая тревога, в которой говорится "сложность здесь! остерегайтесь!". Представьте, если это была норма:

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

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

Я открываю себе идею изменить свое соглашение о кодировании на что-то вроде "однострочные блоки могут никогда не иметь брекетов" или "если вы можете поместить блок в ту же строку, что и условие, и все это вписывается 80 символов, опустите фигурные скобки". Посмотрим.

Ответ 18

Из трех условностей:

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

и

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

и (которые представляют любой стиль отступов, используя открывающую и закрывающую фигурные скобки):

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

Я предпочитаю последний вариант:

  • Мне легче читать, если все if-инструкции написаны единообразным образом.
  • Это может сделать программное обеспечение немного более надежным и без ошибок. Однако все современные IDE и расширенные текстовые редакторы имеют приятные функции автоматического отступов, которые, как я думаю, каждый должен использовать, если он не испортит форматирование комментариев или не противоречит командным стандартам (во многих случаях возможно создать настраиваемую схему форматирования и поделиться им с командой). Моя точка зрения заключается в том, что если отступ делается правильно, риск введения ошибки немного сокращается.
  • Я предпочитаю, чтобы логическое выражение и оператор выполнялись для разных строк. Мне нравится отмечать строку для целей отладки. Даже если я использую среду IDE, где я могу отметить инструкцию и шаг за ней, это интерактивная операция, и я могу забыть, где я начал отлаживать или, по крайней мере, мне потребуется немного времени, чтобы пройти через код несколько (поскольку я должен каждый раз отмечать позицию вручную во время отладки).

Ответ 19

Ваши основные аргументы против использования фигурных скобок заключаются в том, что они используют дополнительные строки и требуют дополнительного отступов.

Линии (почти) свободны, минимизируя количество строк в вашем коде, не должны быть объективными.

И отступ не зависит от использования скобок. В вашем каскадном "использовании" я все же думаю, что вы должны отступать от них, даже когда вы опускаете фигурные скобки.

Ответ 20

Хорошо, это старый вопрос, на который ответили до смерти. Мне есть что добавить.

Сначала я просто должен сказать ИСПОЛЬЗОВАТЬ БРАК. Они могут помочь только читабельности, а читаемость (для вас самих и для других!) Должна быть очень высокой в ​​списке приоритетов, если вы не пишете сборку. Нечитаемый код всегда, всегда приводит к ошибкам. Если вы обнаружите, что фигурные скобки заставляют ваш код занимать слишком много места, ваши методы, вероятно, слишком велики. Большинство или всех методов должны соответствовать одной высоте экрана, если вы делаете это правильно, а Find (F3) - ваш друг.

Теперь для моего добавления: есть проблема с этим:

if (foo) bar();

Попробуйте установить точку останова, которая будет нажата, только если bar() будет запущен. Вы можете сделать это на С#, поместив курсор во вторую половину кода, но это не очевидно и немного больно. В С++ вы не могли этого сделать вообще. По этой причине один из наших самых старших разработчиков, работающих над кодом на С++, настаивает на том, чтобы по этой причине разбивать "if" заявления на две строки. И я согласен с ним.

Сделайте так:

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

Ответ 21

Одной из основных проблем является то, что у вас есть области однострочных и не-одного лайнеров, наряду с отделением от контрольного состояния (for, if, что у вас есть) и конца статута.

Например:

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

Ответ 22

Я был огромным сторонником "фигурных скобок - это ДОЛЖЕН!", но, начиная с принятия модульного тестирования, я обнаружил, что мои модульные тесты защищают бесцельные заявления из сценариев, таких как:

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

С хорошими модульными тестами я могу уверенно пропускать фигурные скобки для простых операторов, чтобы улучшить читаемость (да, это может быть субъективным).

В качестве альтернативы, для чего-то вроде выше, я бы предположил, что это выглядит так:

if (foo) snafu();

Таким образом, разработчик, которому нужно добавить bar() к этому условию, будет более склонным распознавать отсутствие фигурных скобок и добавить их.

Ответ 23

Я твердо убежден в том, что пишу аккуратный и сжатый код, но я всегда буду использовать фигурные скобки. Я нахожу, что они являются удобным способом быстрого просмотра области, в которой существует определенная строка кода. Нет никакой двусмысленности, она прямо указывается перед вами.

Некоторые могут сказать, что это предпочтение, но я считаю, что логический поток программы намного проще отслеживать, если он внутренне непротиворечивый, и я не считаю, что он согласен написать один оператор IF, подобный этому;

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

И еще один такой:

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

Я предпочитаю просто выбрать один общий стиль и придерживаться его:)

Ответ 24

Используйте личное мнение.

if (foo)
  bar();

отлично. Если вы действительно не беспокоитесь о том, что идиоты вносят что-то вроде этого позже:

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

Если вас не беспокоят дебилы, вы в порядке (я не... если они не могут получить базовый синтаксис кода, это наименьшее из их проблем) >

Взамен это более читаемо.

Остальное время:

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

Это была моя любимая, пока я помню. Дополнительно:

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

Работает для меня.

Вертикальное пространство само по себе не очень важно, читаемость. Открывающая скобка на линии сама по себе просто останавливает разговор для синтаксического элемента, пока ваш глаз не опустится до следующей строки. Не то, что мне нравится.

Ответ 25

Скажем, у вас есть код:

if (foo)
    bar();

а затем приходит кто-то другой и добавляет:

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

Согласно способу написания, bar(); теперь выполняется безоговорочно. Включая фигурные скобки, вы предотвращаете такую ​​случайную ошибку. Код должен быть написан таким образом, чтобы сделать такие ошибки сложными или невозможными. Если бы я делал обзор кода и видел отсутствующие фигурные скобки, особенно разбросанные по нескольким строкам, я бы создал дефект. В тех случаях, когда это оправдано, держите его на одной линии, чтобы вероятность сделать такую ​​ошибку снова сведена к минимуму.

Ответ 26

Сокращение строк на самом деле не является хорошим аргументом в отношении сокращения фигурных скобок. Если ваш метод слишком велик, его следует, вероятно, переделать на мелкие куски или перестроить. Выполнение этого, несомненно, увеличит читаемость больше, чем просто снятие брекетов.

Ответ 27

чтобы код с фигурными скобками занимал много места, я использую технику, рекомендованную в книге Code Complete:

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

Ответ 28

Я всегда опускаю их, когда это необходимо, например, в вашем первом примере. Чистый, сжатый код, который я вижу и понимаю, просто взглянув на него, проще поддерживать, отлаживать и понимать, чем код, который я должен прокручивать и читать по строкам. Я думаю, что большинство программистов согласятся с этим.

Легко для него выйти из-под контроля, если вы начнете делать многократные вложения, if/else и т.д., но я думаю, что большинство программистов должны иметь возможность сказать, где рисовать линию.

Я вижу это как аргумент для if ( foo == 0 ) vs if ( 0 == foo ). Последний может предотвратить ошибки для новых программистов (и, возможно, даже изредка для ветеранов), в то время как первый легче быстро читать и понимать, когда вы поддерживаете код.

Ответ 29

В большинстве случаев он укореняется как стандарт кодирования, будь то для компании или проекта FOSS.

В конечном счете, кому-то еще нужно будет проверять свой код, и для каждого разработчика нужно потратить немало времени, чтобы выяснить, какой стиль раздела кода они работают.

Кроме того, представьте, что кто-то идет между Python и языком Cish более одного раза в день... В Python отступы являются частью блока Symantics языка, и было бы довольно легко сделать ошибку, как тот, который вы цитата.

Ответ 30

Err на стороне более безопасной - просто еще одна ошибка, которую вы, возможно, не будете исправлять.

Я лично чувствую себя более уверенным, если все мои блоки обернуты курсивом. Даже для однострочных, это простые обозначения, которые легко предотвращают ошибки. Это делает код более читаемым в том смысле, что вы четко видите, что находится в блоке, чтобы не путать тело блока со следующими утверждениями вне блока.

Если у меня есть однострочный шрифт, я обычно форматирую его следующим образом:

if( some_condition ) { do_some_operation; }

Если строка слишком громоздка, используйте следующее:

if( some_condition )
{
    do_some_operation;
}